我目前正在尝试生成以下维恩图:
\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
@
;
密钥的参数
.. venn
是#1 -> 1 #2 -> 100@ #3 -> a #4 -> bcd@
密钥的参数
.. venn
是#1 -> 1 #2 -> 00@ #3 -> b #4 -> cd@
密钥的参数
.. venn
是#1 -> 0 #2 -> 0@ #3 -> c #4 -> d@
密钥的参数
.. venn
是#1 -> 0 #2 -> @ #3 -> d #4 -> @
密钥的参数
.. venn
是#1 -> @ #2 -> #3 -> @ #4 ->
到达标记字符后,解析器终止。