我有 3 种样式,分别称为 S1、S2 和 S3。我想有条件地为节点着色。我尝试了 \ifnum,但没有成功。您可以看到已被注释掉的一行代码。这就是我概念上想要的。此示例适用于 3 x 3 网格,但我的实际网格是 6 x 6,因此如果我可以使用某种集合符号来描述 S1 和 S2 的节点,那就太好了。
\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
[S1/.style={circle,draw=black,fill=white!80!black,minimum size=20},
S2/.style={circle,draw=black,fill=red!40,minimum size=20},
S3/.style={circle,draw=black,fill=green!40,minimum size=20}]
\foreach \i in {1,...,9}
\foreach \i in {1,...,9}
{
\pgfmathtruncatemacro{\y}{(\i - 1) / 3};
\pgfmathtruncatemacro{\x}{\i - 3 * \y};
\pgfmathtruncatemacro{\label}{\x + 3 * (2 - \y)};
% \node[ IF \label = 4,6,8 THEN S1 ELSE IF \label=1,9 THEN S2 ELSE S3]
\node[S3]
(\label) at (1.5*\x,1.5*\y) {\label};
\node[above right=0mm of \label] {\scriptsize\label};
}
\draw (1) -- (2);
\draw (2) -- (3);
\draw (4) -- (5);
\draw (5) -- (6);
\draw (7) -- (8);
\draw (8) -- (9);
\draw (1) -- (4);
\draw (2) -- (5);
\draw (3) -- (6);
\draw (4) -- (7);
\draw (5) -- (8);
\draw (6) -- (9);
\end{tikzpicture}
\end{document}
答案1
此版本采用了etoolbox
,非常强大的条件设置包。我猜它可以包含在 中,\tikzset
但我还不确定如何。我会编辑答案以防万一。
输出
代码
\documentclass[margin=10pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{tikz}
\usepackage{etoolbox}
\usetikzlibrary{positioning}
\tikzset{
filcirc/.style={circle,draw=black,minimum size=20},
}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,9}
{
\pgfmathtruncatemacro{\y}{(\i - 1) / 3};
\pgfmathtruncatemacro{\x}{\i - 3 * \y};
\pgfmathtruncatemacro{\label}{\x + 3 * (2 - \y)};
% \node[ IF \label = 4,6,8 THEN S1 ELSE IF \label=1,9 THEN S2 ELSE S3]
\expandafter\ifboolexpr{%
test {\ifnumequal{\label}{4}}
or
test {\ifnumequal{\label}{6}}
or
test {\ifnumequal{\label}{8}}
}{% then
\node[filcirc, fill=white!80!black, label={45:\scriptsize\label}] (\label) at (1.5*\x,1.5*\y) {\label};
}{% else
\expandafter\ifboolexpr{%
test {\ifnumequal{\label}{1}} or test {\ifnumequal{\label}{9}}
}{% then
\node[filcirc, fill=red!40, label={45:\scriptsize\label}] (\label) at (1.5*\x,1.5*\y) {\label};
}{% else
\node[filcirc, fill=green!40, label={45:\scriptsize\label}] (\label) at (1.5*\x,1.5*\y) {\label};
}
}
}
\draw (1) -- (2);
\draw (2) -- (3);
\draw (4) -- (5);
\draw (5) -- (6);
\draw (7) -- (8);
\draw (8) -- (9);
\draw (1) -- (4);
\draw (2) -- (5);
\draw (3) -- (6);
\draw (4) -- (7);
\draw (5) -- (8);
\draw (6) -- (9);
\end{tikzpicture}
\end{document}
答案2
以下是使用 PGF 键和几个宏来实现此目的的方法。它允许您说
\tikzset{%
S1 set={3,5,8},
S2 set={1,4},
}
例如,确定哪些节点应采用 和 中的每一种样式S1
。S2
仅使用数字命名节点可能不是一个好主意,但我没有在下面的代码中更改这一点。(为每个节点提供一个标准前缀是避免这种情况的一种简单方法,n\variable
即 而不是\variable
。)
我使用了\resultx
、\resulty
和\resultlabel
来避免冲突。然后我们需要一个临时变量来保存结果,该结果将是1
、2
或 ,3
具体取决于节点应获得的样式。
\let\resultS\relax
我们现在使用两个循环,每个循环测试是否包含在获取样式或的\resultlabel
定义集合之一中。S1
S2
\foreach \j in \Sone
{
\ifnum\resultlabel=\j \gdef\resultS{1}\fi
};
\foreach \j in \Stwo
{
\ifnum\resultlabel=\j \gdef\resultS{2}\fi
};
如果没有的话,我们想要的是S3
其他的。
\ifx\resultS\relax\def\resultS{3}\fi
然后我们resultS
在选项中使用\node
\node[S\resultS] ...
代码:
\documentclass[tikz,border=10pt,multi]{standalone}
\usetikzlibrary{positioning}
\begin{document}
\tikzset{%
S base/.style={circle, draw=black, minimum size=20},
S1/.style={S base, fill=white!80!black},
S2/.style={S base, fill=red!40},
S3/.style={S base, fill=green!40},
S1 set/.store in=\Sone,
S2 set/.store in=\Stwo,
S1 set={4,6,8},
S2 set={1,9},
}
\begin{tikzpicture}
\foreach \i in {1,...,9}
{
\pgfmathtruncatemacro{\resulty}{(\i - 1) / 3};
\pgfmathtruncatemacro{\resultx}{\i - 3 * \resulty};
\pgfmathtruncatemacro{\resultlabel}{\resultx + 3 * (2 - \resulty)};
% \node[ IF \label = 4,6,8 THEN S1 ELSE IF \label=1,9 THEN S2 ELSE S3]
\let\resultS\relax
\foreach \j in \Sone
{
\ifnum\resultlabel=\j \gdef\resultS{1}\fi
};
\foreach \j in \Stwo
{
\ifnum\resultlabel=\j \gdef\resultS{2}\fi
};
\ifx\resultS\relax\def\resultS{3}\fi
\node[S\resultS] (\resultlabel) at (1.5*\resultx,1.5*\resulty) {\resultlabel};
\node[above right=0mm of \resultlabel] {\scriptsize\resultlabel};
}
\foreach \i/\j in {1/2,1/4,2/3,2/5,3/6,4/5,4/7,5/6,5/8,6/9,7/8,8/9}
\draw (\i) -- (\j);
\end{tikzpicture}
\end{document}
您可能希望查看matrix
和/或chains
库,以更轻松地绘制晶格结构。但这不是这个问题的主题……
答案3
坦率地说,我不明白你在代码中做什么以及你的结果应该是什么,所以这个答案的主要目的就是澄清这一点。
下面的 MWE 生成了这张图片:
其中颜色是根据偶数/奇数选择的\label
:
\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amsfonts,amssymb}
\usepackage{tikz}
\usetikzlibrary{backgrounds, positioning, scopes}
\usepackage{ifthen}
\begin{document}
\begin{tikzpicture}[
every label/.style={node distance=0pt,font=\scriptsize},
base/.style = {circle, draw=black, minimum size=20},
S1/.style={base,fill=white!80!black},
S2/.style={base,fill=red!40},
S3/.style={base,fill=green!40}
]
%\foreach \i in {1,...,9}
\foreach \i in {1,...,9}
{
\pgfmathtruncatemacro{\y}{(\i - 1) / 3};
\pgfmathtruncatemacro{\x}{\i - 3 * \y};
\pgfmathtruncatemacro{\label}{\x + 3 * (2 - \y)};
\ifthenelse{\isodd{\label}}
{\node[S1,label=above right:\label] (\label) at (1.5*\x,1.5*\y) {\label};
}{
\node[S3,label=above right:\label] (\label) at (1.5*\x,1.5*\y) {\label};
}
\ifnum\label=1
\node[S2,label=above right:\label] (\label) at (1.5*\x,1.5*\y) {\label}; \fi
\ifnum\label=9
\node[S2,label=above right:\label] (\label) at (1.5*\x,1.5*\y) {\label}; \fi
}
% \node[ IF \label = 4,6,8 THEN S1 ELSE IF \label=1,9 THEN S2 ELSE S3]
\scoped[on background layer]
\draw (1) -- (3) (4) -- (6) (7) -- (9)
(1) -- (7) (2) -- (8) (3) -- (9);
\end{tikzpicture}
\end{document}
选择\label
内容作为节点名称不是一个好主意,该名称已在 TikZ 中使用。如您所见,我稍微简化了您的代码(为什么需要两个具有相同变量的循环?),但是,为了获得进一步的帮助,您需要说明预期结果是什么。这个网格是 6 x 6 个不同颜色的圆圈吗?这就是圆圈的内容,标签(!)的用途是什么,即它们右上方的数字?至少您看到了一个例子,如何使用条件。
附录: 在多次观察上述代码得到的图片后,我突然想到,除了第一个节点(编号为 1)之外,对角线上的节点具有相同的颜色,并且从对角线到对角线交替出现。对于这种情况,我(尝试)将代码推广到任意数量的节点:
\documentclass[border=3mm,
tikz,
preview
]{standalone}
\usetikzlibrary{backgrounds, positioning, scopes}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amsfonts,amssymb}
\usepackage{ifthen}
\begin{document}
\begin{tikzpicture}[
every label/.style={inner sep=1pt,font=\scriptsize},
base/.style = {circle, draw=black, minimum size=20},
S1/.style={base,fill=white!80!black},
S2/.style={base,fill=green!40},
S3/.style={base,fill=red!40},
]
\pgfmathtruncatemacro{\xmax}{6}
\foreach \x in {1,2,...,\xmax}
\foreach \y in {1,2,...,\xmax}
{
\pgfmathtruncatemacro{\i}{\x + (\y-1)*\xmax};
\pgfmathparse{\x+\y}
\ifnum\i=1
\node[S3,label=45:\x\y] (\i) at (1.5*\x,-1.5*\y) {\i};
\else
\ifthenelse{\isodd{\pgfmathresult}}
{ \node[S1,label=45:\x\y] (\i) at (1.5*\x,-1.5*\y) {\i};
}{\node[S2,label=45:\x\y] (\i) at (1.5*\x,-1.5*\y) {\i};
}
\fi
}
\end{tikzpicture}
\end{document}
此代码提供:
节点之间的缺失线很容易添加。当我的想法得到确认并导致所需的着色结果时,我会制作它们。对于条件,我使用\ifnum
和的组合\ifthenelse
。