tikz foreach ループでは変数のセットを 1 つだけ許可する

tikz foreach ループでは変数のセットを 1 つだけ許可する

現在、次のベン図を生成しようとしています。

\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。1 回の反復の複数の変数の値は で区切る必要があり/、異なる反復の値は で区切る必要があります,

    \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}

ここに画像の説明を入力してください

「パーサー」の動作 (つまり、 キーvennvenn ..キー) は、おそらく例を挙げて説明するのが最も適切でしょう。

を使用すると何が起こるか考えてみましょう\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 -> 
    

センチネル文字に到達すると、パーサーは終了します。

関連情報