tikz foreach循环只允许一组变量

tikz foreach循环只允许一组变量

我目前正在尝试生成以下维恩图:

\usetikzlibrary{shapes,backgrounds}
\usepackage{tikz}
\usepackage{xcolor}
\begin{tikzpicture}[scale=.8, show background rectangle]
    \def\ellipsea{(0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
    \def\ellipseb{(-0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
    \def\ellipsec{(1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
    \def\ellipsed{(-1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
    \def\negating{(-4.5cm,-4.5cm) rectangle (4.5cm,4.5cm)}
    \node (a) at (-2.5cm,2.5cm) {C};
    \node (b) at (2.5cm,2.5cm) {B};
    \node (c) at (-3.5cm,1.5cm) {N};
    \node (d) at (3.5cm,1.5cm) {S};
    %~A~B~C~D
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb\negating;
        \clip \ellipsec\negating;
        \clip \ellipsed\negating;
        \fill[color=black,opacity=0.2] \negating;
    \endscope
    %ABC~D      
    \scope
        \clip \ellipsea;
        \clip \ellipseb;
        \clip \ellipsec;
        \clip \ellipsed\negating;
        \fill[color=black,opacity=0.2] \negating;
    \endscope
    %AB~CD  
    \scope
        \clip \ellipsea;
        \clip \ellipseb;
        \clip \ellipsec\negating;
        \clip \ellipsed;
        \fill[color=black,opacity=0.2] \negating;
    \endscope
    %A~BCD  
    \scope
        \clip \ellipsea;
        \clip \ellipseb\negating;
        \clip \ellipsec;
        \clip \ellipsed;
        \fill[color=black,opacity=0.2] \negating;
    \endscope
    %~ABCD
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb;
        \clip \ellipsec;
        \clip \ellipsed;
        \fill[color=blue,opacity=0.2] \negating;
    \endscope
    %ABCD
    \scope
        \clip \ellipsea;
        \clip \ellipseb;
        \clip \ellipsec;
        \clip \ellipsed;
        \fill[color=black,opacity=0.2] \negating;
    \endscope   
    %AB~C~D
    \scope
        \clip \ellipsea;
        \clip \ellipseb;
        \clip \ellipsec\negating;
        \clip \ellipsed\negating;
        \fill[color=green,opacity=0.2] \negating;
    \endscope
    %A~B~CD 
    \scope
        \clip \ellipsea;
        \clip \ellipseb\negating;
        \clip \ellipsec\negating;
        \clip \ellipsed;
        \fill[color=yellow,opacity=0.2] \negating;
    \endscope
    %~AB~CD
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb;
        \clip \ellipsec\negating;
        \clip \ellipsed;
        \fill[color=black,opacity=0.2] \negating;
    \endscope       
    %~ABC~D
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb;
        \clip \ellipsec;
        \clip \ellipsed\negating;
        \fill[color=red,opacity=0.2] \negating;
    \endscope       
    %~A~BCD
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb\negating;
        \clip \ellipsec;
        \clip \ellipsed;
        \fill[color=orange,opacity=0.2] \negating;
    \endscope
    %~AB~C~D
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb;
        \clip \ellipsec\negating;
        \clip \ellipsed\negating;
        \fill[color=black,opacity=0.2] \negating;
    \endscope
    %~A~B~CD
    \scope
        \clip \ellipsea\negating;
        \clip \ellipseb\negating;
        \clip \ellipsec\negating;
        \clip \ellipsed;
        \fill[color=purple,opacity=0.2] \negating;
    \endscope
    %A~B~D
    \scope
        \clip \ellipsea;
        \clip \ellipseb\negating;
        \clip \ellipsed\negating;
        \fill[color=red,opacity=0.5] \negating;
    \endscope
    %~BC~D
    \scope
        \clip \ellipseb\negating;
        \clip \ellipsec;
        \clip \ellipsed\negating;
        \fill[color=blue,opacity=0.5] \negating;
    \endscope


    \node (ABcd) at (0,1cm) {1};
    \node (aBCD) at (0.5cm,-2.25cm) {1};
    \node (AbcD) at (-1.2cm,-1.9cm) {1};
    \node (aBCd) at (1.2cm,-1.9cm) {2};
    \node (abCD) at (0,-3cm) {4};
    \node (abcD) at (-3cm,0cm) {1}; 
    \node (Abd) at (1.8cm,1.1cm) {3};
    \node (bCd) at (2.5cm,.5cm) {4};

    \draw \ellipsea;
    \draw \ellipseb;
    \draw \ellipsec;
    \draw \ellipsed;    

\end{tikzpicture}

为了清楚起见,使用 tikz \foreach 循环,如下所示:

\foreach \abool/\bbool/\cbool/\dbool/\colchoose/\opchoose in {1/1/1/1,black,0.2}
            \scope  
            \ifnum \abool=1
                \clip \ellipsea;
                [\else \clip \ellipsea\negating;]
            \fi
            \ifnum \bbool=1
                \clip \ellipseb;
                [\else \clip \ellipseb\negating;]               
            \fi
            \ifnum \cbool=1
                \clip \ellipsec;
                [\else \clip \ellipsec\negating;]
            \fi
            \ifnum \dbool=1
                \clip \ellipsed;
                [\else \clip \ellipsed\negating;]
            \fi
            \fill[color=\colchoose,opacity=\opchoose] \negating;
            \endscope

替换原始片段中的长行 \scope 。这似乎工作正常,直到我添加多个区域(例如 {1/1/1/1/black/0.2,0/1/0/1,black,0.2}),在这种情况下我收到以下错误:

! Missing } inserted.<inserted text>} \end{tikzpicture}
! Missing \endgroup inserted.<inserted text>\endgroup \end{document}

我想知道如何修复这个问题或者我的代码是否有问题,因为我对 tikz 还很陌生。

谢谢!

答案1

如果您的代码运行正常

  • 要小心处理循环的值\foreach:一次迭代的几个变量的值必须用 分隔/,不同迭代的值必须用分隔,

    \foreach ... in {1/1/1/1/black/0.2,0/1/0/1/black/0.2}
    

    (你{1/1/1/1/black/0.2,0/1/0/1,black,0.2}反而尝试了。)

  • 将循环主体括在括号中。

在此处输入图片描述

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,backgrounds}
%\usepackage{xcolor}
\begin{document}
\begin{tikzpicture}[scale=.8, show background rectangle]
    \def\ellipsea{(0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
    \def\ellipseb{(-0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
    \def\ellipsec{(1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
    \def\ellipsed{(-1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
    \def\negating{(-4.5cm,-4.5cm) rectangle (4.5cm,4.5cm)}
    \node (a) at (-2.5cm,2.5cm) {C};
    \node (b) at (2.5cm,2.5cm) {B};
    \node (c) at (-3.5cm,1.5cm) {N};
    \node (d) at (3.5cm,1.5cm) {S};



\foreach \abool/\bbool/\cbool/\dbool/\colchoose/\opchoose in {1/1/1/1/black/0.2,0/1/0/1/black/0.2}
{            \scope  
            \ifnum \abool=1
                \clip \ellipsea;
                [\else \clip \ellipsea\negating;]
            \fi
            \ifnum \bbool=1
                \clip \ellipseb;
                [\else \clip \ellipseb\negating;]               
            \fi
            \ifnum \cbool=1
                \clip \ellipsec;
                [\else \clip \ellipsec\negating;]
            \fi
            \ifnum \dbool=1
                \clip \ellipsed;
                [\else \clip \ellipsed\negating;]
            \fi
            \fill[color=\colchoose,opacity=\opchoose] \negating;
            \endscope
}


    \node (ABcd) at (0,1cm) {1};
    \node (aBCD) at (0.5cm,-2.25cm) {1};
    \node (AbcD) at (-1.2cm,-1.9cm) {1};
    \node (aBCd) at (1.2cm,-1.9cm) {2};
    \node (abCD) at (0,-3cm) {4};
    \node (abcD) at (-3cm,0cm) {1}; 
    \node (Abd) at (1.8cm,1.1cm) {3};
    \node (bCd) at (2.5cm,.5cm) {4};

    \draw \ellipsea;
    \draw \ellipseb;
    \draw \ellipsec;
    \draw \ellipsed;    

\end{tikzpicture}
\end{document}

答案2

实际上,我大多忽略了 OP 的问题,并提供了一种更有效的方式来指定图表:

\documentclass[tikz,border=5]{standalone} 
\tikzset{%
    venn/.code 2 args={\scope\def\c{#1}\def\n{}\tikzset{.. venn=#2@;}\endscope},
    .. venn/.code args={#1#2;}{%
        \ifx#1@%
            \path[fill=\c]\negating;
        \else%
            \ifx#1~
                \let\n=\negating
            \else%
                \clip \csname ellipse#1\endcsname\n;
                \def\n{}%
            \fi%
            \tikzset{.. venn=#2;}%
        \fi}}
\def\ellipsea{(0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
\def\ellipseb{(-0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
\def\ellipsec{(1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
\def\ellipsed{(-1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
\def\negating{(-4.5cm,-4.5cm) rectangle (4.5cm,4.5cm)}
\newcommand\venn[2][]{\tikzset{venn={#1}{#2}}}
\begin{document}
\begin{tikzpicture}
\venn [red]       {abcd}
\venn [yellow]    {~abcd}
\venn [pink]      {a~bcd}
\venn [green]     {ab~cd}
\venn [orange]    {abc~d}
\venn [purple]    {~a~bcd}
\venn [blue]      {~ab~cd}
\venn [magenta]   {~abc~d}
\venn [olive]     {a~b~cd}
\venn [violet]    {a~bc~d}
\venn [teal]      {ab~c~d}
\venn [brown]     {~a~b~cd}
\venn [teal]      {~a~bc~d}
\venn [lime]      {~ab~c~d}
\venn [darkgray]  {a~b~c~d}
\venn [lightgray] {~a~b~c~d}
\end{tikzpicture}
\end{document}

在此处输入图片描述

这里有一个变体,其(a)仍然不能回答 OP 的问题,但(b)可以将其指定为位序列,例如1101

\documentclass[tikz,border=5]{standalone} 
\tikzset{%
    venn/.code 2 args={\scope\def\c{#1}\tikzset{.. venn/.expanded=#2@;abcd@;}\endscope},
    .. venn/.code args={#1#2;#3#4;}{%
        \ifx#1@%
            \path[fill=\c]\negating;
        \else%
            \ifcase#1
                \clip \csname ellipse#3\endcsname\negating;
            \or%
                \clip \csname ellipse#3\endcsname;
            \fi%
            \tikzset{.. venn=#2;#4;}%
        \fi%
}}
\def\ellipsea{(0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
\def\ellipseb{(-0.5cm,0) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
\def\ellipsec{(1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=50]}
\def\ellipsed{(-1.5cm,-1cm) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50]}
\def\negating{(-4.5cm,-4.5cm) rectangle (4.5cm,4.5cm)}
\newcommand\venn[2][]{\tikzset{venn={#1}{#2}}}
\pgfmathsetbasenumberlength{4}
\begin{document}
\begin{tikzpicture}
\foreach \i [evaluate={\r=rnd;\g=rnd;\b=rnd;}] in {0,...,15}{
  \definecolor{tmp}{rgb}{\r,\g,\b}
  \pgfmathdectobase\n{\i}{2}%
  \venn[tmp]{\n}
}
\end{tikzpicture}
\end{document}

在此处输入图片描述

也许可以通过一个例子来最好地解释“解析器”(即venn和键)的作用。venn ..

考虑一下使用时会发生什么\venn{1100}

venn“调用” .. venn=1100@;abcd@;。是、和命令的后缀。字符abcd是(任意)标记字符,用于检测何时到达序列的末尾。字符是标记字符串末尾的分隔符。然后依次考虑每次迭代:\ellipsea\ellipseb\ellipsec\ellipsed@;

  1. 密钥的参数.. venn

    #1 -> 1 #2 -> 100@ 
    #3 -> a #4 -> bcd@
    
  2. 密钥的参数.. venn

    #1 -> 1 #2 -> 00@ 
    #3 -> b #4 -> cd@
    
  3. 密钥的参数.. venn

    #1 -> 0 #2 -> 0@ 
    #3 -> c #4 -> d@
    
  4. 密钥的参数.. venn

    #1 -> 0 #2 -> @ 
    #3 -> d #4 -> @
    
  5. 密钥的参数.. venn

    #1 -> @ #2 ->  
    #3 -> @ #4 -> 
    

到达标记字符后,解析器终止。

相关内容