我能够修改 Loop Space 的代码(第一个答案在这里找到:如何高效地生成所有可能的维恩图(如下图所示)?) 使用椭圆绘制四组维恩图。它似乎适用于单个维恩图,但当我尝试使用时\allvendiagrams
,我收到一条错误消息,指出维度太大。我意识到有 65,536 种可能的变化,尝试打印包含所有这些变化的文档是不切实际的,但如果可能的话,我希望代码能够正常工作。我的代码如下:
\documentclass[border=3pt,tikz]{standalone}
%\url{https://tex.stackexchange.com/q/67395/86}
\usepackage{tikz}
\usetikzlibrary{positioning,shapes.geometric}
\makeatletter
\def\venn@strip#1#2\venn@STOP{%
\def\venn@next{#1}%
\gdef\venn@rest{#2}%
}
\newcommand{\venn}[1]{%
\begin{tikzpicture}
\coordinate (A) at (1.6,0);
\coordinate (B) at (0.3,1);
\coordinate (C) at (-1.6,0);
\coordinate (D) at (-0.3,1);
\coordinate (S-SE) at (5,-4);
\coordinate (S-NW) at (-5,5);
\edef\venn@rest{#100000000}%
\foreach \i in {0,...,15} {
\begin{scope}[even odd rule]
\expandafter\venn@strip\venn@rest\venn@STOP
\ifnum\venn@next=1\relax
\pgfmathparse{Mod(\i,2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (A) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\pgfmathparse{Mod(floor(\i/2),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (B) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\pgfmathparse{Mod(floor(\i/4),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (C) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\pgfmathparse{Mod(floor(\i/8),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (D) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\fill[rounded corners,gray!80] (S-SE) rectangle (S-NW);
\fi
\end{scope}
}
\draw[ultra thick] (A) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\draw[ultra thick] (B) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\draw[ultra thick] (C) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\draw[ultra thick] (D) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\draw[ultra thick,rounded corners] (S-SE) rectangle (S-NW);
\end{tikzpicture}
}
\makeatother
\newcommand{\allvendiagrams}{
% To generate the lot:
\foreach \j in {0,...,65535} {
\def\venncode{}
\foreach \k in {0,...,15} {
\pgfmathparse{Mod(floor(\j/2^\k),2) == 1 ? "\venncode1" : "\venncode0"}
\global\let\venncode=\pgfmathresult
}
\venn{\venncode}
}
}
\begin{document}
%\venn{0000000000000000} %0
%\venn{0000000000000001} %1
%\venn{0000000000000010} %2
%\venn{0000000000000011} %3
%\venn{0000000000000100} %4
%\venn{0000000000000101} %5
%\venn{0000000000000110} %6
%\venn{0000000000000111} %7
%\venn{0000000000001000} %8
%\venn{0000000010000000} %128
%\venn{0000000011111111} %255
%\venn{1111111111111111} %65535
\allvendiagrams
\end{document}
值得注意的是,Overleaf 给出了“Dimension 太大”的错误,但仍能生成维恩图。正如预期的那样,它在尝试生成所有 65,536 个变体时超时;我目前一次运行 100 个变体。TexWorks 给出了“Dimension 太大”的错误,并且没有生成任何内容;如果可能的话,我想让代码在 TexWorks 中运行,因为我家里没有可靠的互联网连接。
答案1
我使用的设备无法对此进行全面测试,但有限的测试表明这应该可以满足要求。正如我在评论中所说,似乎是生成二进制字符串的位导致了问题,因此这以更简单的方式重新实现了它。
“更简单”显然是一个主观术语!虽然代码看起来可能更复杂,但它所做的技术上更底层。原始代码的工作原理是取一个数字并将其转换为二进制字符串,使用数学上没问题但达到 TeX 数字能力边界的例程。然而,这确实意味着我们可以使用 pgfmath 的数学解析器。此代码将二进制数表示为 0 和 1 的字符串。这避免了 TeX 对数字的上限,但确实意味着我们必须手动实现“加 1”操作。这就是宏\step_bin
。
(这段代码可能并不像它应该的那样优雅。它是使用 LaTeX3 函数编写的,但我认为我的命名方案并不完全符合正确的 L3 约定。此外,LaTeX3 的整数处理实际上可能可以处理大数字,所以这可能有点过头了。我现在没有可以轻松测试这些假设的设备,但其他人可能会逐步改进——考虑不接受这个答案以表明还有一些事情要做。)
\documentclass[border=3pt,tikz]{standalone}
%\url{https://tex.stackexchange.com/q/67395/86}
\usepackage{tikz}
\usepackage{expl3}
\usepackage{xparse}
\usetikzlibrary{positioning,shapes.geometric}
\ExplSyntaxOn
\tl_new:N \l__bin_tl
\tl_new:N \l__bin_tmpa_tl
\int_new:N \l__bin_tmpa_int
\cs_new_nopar:Npn \reset_bin {
\tl_set:Nn \l__bin_tl {0000000000000000}
}
\cs_new_nopar:Npn \step_bin {
\tl_clear:N \l__bin_tmpa_tl
\int_set:Nn \l__bin_tmpa_int {1}
\tl_map_inline:Nn \l__bin_tl {
\int_add:Nn \l__bin_tmpa_int {##1}
\tl_put_left:Nx \l__bin_tmpa_tl { \int_mod:nn {\l__bin_tmpa_int} {2}}
\int_set:Nn \l__bin_tmpa_int { (\l__bin_tmpa_int - \int_mod:nn {\l__bin_tmpa_int}{2})/2}
}
\tl_set_eq:NN \l__bin_tl \l__bin_tmpa_tl
}
\DeclareDocumentCommand \AllVenns {} {
\reset_bin
\prg_replicate:nn {65536} {
\exp_args:NV \venn \l__bin_tl
\step_bin
}
}
\ExplSyntaxOff
\makeatletter
\def\venn@strip#1#2\venn@STOP{%
\def\venn@next{#1}%
\gdef\venn@rest{#2}%
}
\newcommand{\venn}[1]{%
\begin{tikzpicture}
\coordinate (A) at (1.6,0);
\coordinate (B) at (0.3,1);
\coordinate (C) at (-1.6,0);
\coordinate (D) at (-0.3,1);
\coordinate (S-SE) at (5,-4);
\coordinate (S-NW) at (-5,5);
\edef\venn@rest{#100000000}%
\foreach \i in {0,...,15} {
\begin{scope}[even odd rule]
\expandafter\venn@strip\venn@rest\venn@STOP
\ifnum\venn@next=1\relax
\pgfmathparse{Mod(\i,2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (A) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\pgfmathparse{Mod(floor(\i/2),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (B) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\pgfmathparse{Mod(floor(\i/4),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (C) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\pgfmathparse{Mod(floor(\i/8),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
\path[clip] \pgfmathresult (D) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\fill[rounded corners,gray!80] (S-SE) rectangle (S-NW);
\fi
\end{scope}
}
\draw[ultra thick] (A) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\draw[ultra thick] (B) ellipse [x radius=3cm, y radius=1.5cm, rotate=50];
\draw[ultra thick] (C) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\draw[ultra thick] (D) ellipse [x radius=3cm, y radius=1.5cm, rotate=-50];
\draw[ultra thick,rounded corners] (S-SE) rectangle (S-NW);
\end{tikzpicture}
}
\makeatother
\begin{document}
%\venn{0000000000000000} %0
%\venn{0000000000000001} %1
%\venn{0000000000000010} %2
%\venn{0000000000000011} %3
%\venn{0000000000000100} %4
%\venn{0000000000000101} %5
%\venn{0000000000000110} %6
%\venn{0000000000000111} %7
%\venn{0000000000001000} %8
%\venn{0000000010000000} %128
%\venn{0000000011111111} %255
%\venn{1111111111111111} %65535
%\allvendiagrams
\AllVenns
\end{document}