В настоящее время я пытаюсь создать следующую диаграмму Венна:
\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 s в исходной части. Это, кажется, работает нормально, пока я не добавляю несколько областей (например, {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
На самом деле я в основном игнорирую вопрос ОП и предлагаю в основном более эффективный способ конкретизации диаграммы:
\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}
А вот вариант, который (а) по-прежнему не отвечает на вопрос ОП, но (б) позволяет задавать спецификацию как последовательность битов, например 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
'calls' .. 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 ->
Достигнув контрольного символа, синтаксический анализатор завершает работу.