bucle tikz foreach que solo permite un conjunto de variables

bucle tikz foreach que solo permite un conjunto de variables

Actualmente estoy intentando generar el siguiente diagrama de Venn:

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

usando el bucle tikz \foreach, para mayor claridad, así:

\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

Para reemplazar la larga línea de \scope s en la pieza original. Esto parece funcionar bien, hasta que agrego varias áreas (como {1/1/1/1/black/0.2,0/1/0/1,black,0.2}), en cuyo caso aparece el siguiente error:

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

Me preguntaba cómo solucionar este problema o si hay algún problema con mi código, ya que soy bastante nuevo en tikz.

¡Gracias!

Respuesta1

Tu código funciona bien si

  • Hay que tener cuidado con los valores del \foreachbucle: los valores de varias variables de una iteración deben estar separados por /, los valores de diferentes iteraciones por ,.

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

    (En su lugar, lo intentaste {1/1/1/1/black/0.2,0/1/0/1,black,0.2}).

  • Encierre el cuerpo del bucle entre tirantes.

ingrese la descripción de la imagen aquí

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

Respuesta2

En realidad, estoy ignorando principalmente la pregunta de los OP y proporcionando una forma más eficiente de especificar el diagrama:

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

ingrese la descripción de la imagen aquí

Y aquí hay una variante que (a) todavía no responde a la pregunta de los OP pero (b) permite la especificación como una secuencia de bits, por ejemplo 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}

ingrese la descripción de la imagen aquí

La acción del 'analizador' (es decir, las teclas venny venn ..) quizás pueda explicarse mejor con un ejemplo.

Considere lo que sucede cuando se usa \venn{1100}.

La vennllave 'llama' .. venn=1100@;abcd@;. Son abcdlos sufijos de los comandos \ellipsea, y \ellipseb. Los caracteres son caracteres centinela (arbitrarios) que permiten detectar cuándo se ha llegado al final de una secuencia. Los caracteres son delineadores para marcar el final de las cadenas. Luego considere cada iteración por turno:\ellipsec\ellipsed@;

  1. Los argumentos de la .. vennclave son

    #1 -> 1 #2 -> 100@ 
    #3 -> a #4 -> bcd@
    
  2. Los argumentos de la .. vennclave son

    #1 -> 1 #2 -> 00@ 
    #3 -> b #4 -> cd@
    
  3. Los argumentos de la .. vennclave son

    #1 -> 0 #2 -> 0@ 
    #3 -> c #4 -> d@
    
  4. Los argumentos de la .. vennclave son

    #1 -> 0 #2 -> @ 
    #3 -> d #4 -> @
    
  5. Los argumentos de la .. vennclave son

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

Al alcanzar el carácter centinela, el analizador finaliza.

información relacionada