如何使用样式有条件地为网格中的节点着色

如何使用样式有条件地为网格中的节点着色

我有 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},
}

例如,确定哪些节点应采用 和 中的每一种样式S1S2仅使用数字命名节点可能不是一个好主意,但我没有在下面的代码中更改这一点。(为每个节点提供一个标准前缀是避免这种情况的一种简单方法,n\variable即 而不是\variable。)

我使用了\resultx\resulty\resultlabel来避免冲突。然后我们需要一个临时变量来保存结果,该结果将是12或 ,3具体取决于节点应获得的样式。

    \let\resultS\relax

我们现在使用两个循环,每个循环测试是否包含在获取样式或的\resultlabel定义集合之一中。S1S2

    \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

相关内容