如何高效地生成所有可能的维恩图(如下图所示)?

如何高效地生成所有可能的维恩图(如下图所示)?

我能画维恩图但现在我的问题比逐一绘制维恩图更复杂。我需要高效地绘制所有可能的维恩图。我需要一种组合方法,因为有 256 种组合。

让我们选择以下集合作为要考虑的情况。二进制数字标签用于唯一标识每个“原子”区域。我的定义:原子区域不包含任何较小的区域。

因为有 8 个原子区域,每个区域都可以被选中或不被选中以组成新的化合物区域。因此有 2^8 种方法。

如何有效地生成所有可能的维恩图(上述情况)?

在此处输入图片描述

目标是生成 256 个维恩图,每个图都有一个独特的彩色复合区域,并具有相关的集合操作。

让我们使用 8 位整数来表示每个图表。

第一位(最左边的位或最高有效位)代表区域000

第二位代表区域100

...

最低有效位代表区域111

0表示不连接,产生新的复合区域。1否则。

如果第一个图的补码为,AuBuC那么它的二进制表示形式为1000 00001111 1111表示S。等等等等!

问题表

问题表将要求学生为每个红色化合物下图中每个图表中的区域。

在此处输入图片描述 在此处输入图片描述 在此处输入图片描述

...

答案1

好的,这是一些代码:

\documentclass{standalone}
%\url{https://tex.stackexchange.com/q/67395/86}
\usepackage{tikz}

\makeatletter

\def\venn@strip#1#2\venn@STOP{%
  \def\venn@next{#1}%
  \gdef\venn@rest{#2}%
}

\newcommand{\venn}[1]{%
\begin{tikzpicture}
\coordinate (A) at (0,0);
\coordinate (B) at (2,0);
\coordinate (C) at (1,{sqrt(3)});
\coordinate (S-SE) at (5,-3);
\coordinate (S-NW) at (-3,{sqrt(3)+3});
  \edef\venn@rest{#100000000}%
  \foreach \i in {0,...,7} {
  \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) circle[radius=2];
    \pgfmathparse{Mod(floor(\i/2),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
    \path[clip] \pgfmathresult (B) circle[radius=2];
    \pgfmathparse{Mod(floor(\i/4),2) == 1 ? "(S-SE) rectangle (S-NW)" : ""}
    \path[clip] \pgfmathresult (C) circle[radius=2];
    \fill[rounded corners,red] (S-SE) rectangle (S-NW);
    \fi
  \end{scope}
  }
    \draw[ultra thick] (A) circle[radius=2];
    \draw[ultra thick] (B) circle[radius=2];
    \draw[ultra thick] (C) circle[radius=2];
    \draw[ultra thick,rounded corners] (S-SE) rectangle (S-NW);
\end{tikzpicture}
}

\makeatother

\newcommand{\allvendiagrams}{
% To generate the lot:
\foreach \j in {0,...,255} {
  \def\venncode{}
  \foreach \k in {0,...,7} {
    \pgfmathparse{Mod(floor(\j/2^\k),2) == 1 ? "\venncode1" : "\venncode0"}
    \global\let\venncode=\pgfmathresult
  }
  \venn{\venncode}

}
}

\begin{document}
\venn{10000000}
\venn{01000000}
\venn{11000000}
\end{document}

结果如下:

维恩图示例

我几乎肯定会对不同的区域使用不同的代码 - 我选择了更简单的代码。规则是1第 k 位的 a 填充第 k 个区域,标签和区域之间的对应关系是将 k 写成二进制数,然后如果设置了位,则在内部使用该圆圈,如果没有,则在外部使用该圆圈。最后,我们在上面绘制区域和圆圈。我没有追求太多的可定制性,但希望可以很明显地看出需要更改哪些内容才能使其看起来不同。

编辑自提问者:通过使用\documentclass[border=3pt,tikz]{standalone}和调用\allvendiagrams而不是\venn{10000000}\venn{01000000}\venn{11000000},输出将显示所有维恩图,如下所示。但肯定不是 GIF。

在此处输入图片描述

答案2

这可以做得更优雅,但无论如何它都能工作。基于对是否可以用纯色填充(A 联合 B 联合 C)的补集,但其余区域保持透明?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
  (current page.south east) --
  (current page.south west) --
  (current page.north west) --
  (current page.north east)}
]

\tikzset{
    venn0/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (30:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (-210:0.7cm) circle [radius=1cm] [reverseclip];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn1/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm];
            \path  [clip] (30:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (-210:0.7cm) circle [radius=1cm] [reverseclip];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn2/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (30:0.7cm) circle [radius=1cm];
            \path  [clip] (-210:0.7cm) circle [radius=1cm] [reverseclip];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn3/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (30:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (-210:0.7cm) circle [radius=1cm];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn4/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (30:0.7cm) circle [radius=1cm] ;
            \path  [clip] (-210:0.7cm) circle [radius=1cm] ;
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn5/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm];
            \path  [clip] (30:0.7cm) circle [radius=1cm] [reverseclip];
            \path  [clip] (-210:0.7cm) circle [radius=1cm];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn6/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm];
            \path  [clip] (30:0.7cm) circle [radius=1cm] ;
            \path  [clip] (-210:0.7cm) circle [radius=1cm] [reverseclip];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    venn7/.code={
        \begin{scope}
            \begin{pgfinterruptboundingbox}
            \path  [clip] (-90:0.7cm) circle [radius=1cm];
            \path  [clip] (30:0.7cm) circle [radius=1cm] ;
            \path  [clip] (-210:0.7cm) circle [radius=1cm];
            \end{pgfinterruptboundingbox}
            \fill [orange] (-2,-2) rectangle (2,2);
        \end{scope}
    },
    vennoutlines/.code={
        \draw (-90:0.7cm) circle [radius=1cm];
        \draw (30:0.7cm) circle [radius=1cm];
        \draw (-210:0.7cm) circle [radius=1cm];
    }
}

\noindent%
\foreach \a in {0,1}
\foreach \b in {0,1}
\foreach \c in {0,1}
\foreach \d in {0,1}
\foreach \e in {0,1}
\foreach \f in {0,1}
\foreach \g in {0,1}
\foreach \h in {0,1}{%
\begin{tikzpicture}[remember picture, scale=0.2]
\ifnum\a=0
    \tikzset{venn0}
\fi
\ifnum\b=0
    \tikzset{venn1}
\fi
\ifnum\c=0
    \tikzset{venn2}
\fi
\ifnum\d=0
    \tikzset{venn3}
\fi
\ifnum\e=0
    \tikzset{venn4}
\fi
\ifnum\f=0
    \tikzset{venn5}
\fi
\ifnum\g=0
    \tikzset{venn6}
\fi
\ifnum\h=0
    \tikzset{venn7}
\fi
\tikzset{vennoutlines}
\end{tikzpicture}
}

\end{document}

答案3

这是我的解决方案。它就像杰克的解决方案,但有一些不同。我计算了“漂亮的”圆半径和中心间距(22*sqrt{3}),因此我可以直接使用坐标并避免reverseclip,这缩短了区域的定义。此外,我的foreach循环使用颜色作为变量,这样您就可以避免\ifnum \fi构造。最后\phantom{X}只是让最后一张图片与其他 15 张图片保持在同一行。我不知道速度有多快杰克的代码是,但是我的很慢。

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\begin{document}

\newcommand{\regionA}[1]
{   \fill[#1] (30:2) arc (60:0:{2*sqrt(3)}) arc (-60:120:{2*sqrt(3)}) arc (60:0:{2*sqrt(3)});
}

\newcommand{\regionB}[1]
{   \fill[#1] (150:2) arc (180:120:{2*sqrt(3)}) arc (60:240:{2*sqrt(3)}) arc (180:120:{2*sqrt(3)});
}

\newcommand{\regionC}[1]
{   \fill[#1] (270:2) arc (240:300:{2*sqrt(3)}) arc (360:180:{2*sqrt(3)}) arc (240:300:{2*sqrt(3)});
}

\newcommand{\regionAB}[1]
{   \fill[#1] (30:2) arc (0:60:{2*sqrt(3)}) arc (120:180:{2*sqrt(3)}) arc (120:60:{2*sqrt(3)});
}

\newcommand{\regionAC}[1]
{   \fill[#1] (30:2) arc (60:0:{2*sqrt(3)}) arc (300:240:{2*sqrt(3)}) arc (-60:0:{2*sqrt(3)});
}

\newcommand{\regionBC}[1]
{   \fill[#1] (150:2) arc (120:180:{2*sqrt(3)}) arc (240:300:{2*sqrt(3)}) arc (240:180:{2*sqrt(3)});
}

\newcommand{\regionABC}[1]
{   \fill[#1] (30:2) arc (60:120:{2*sqrt(3)}) arc (180:240:{2*sqrt(3)}) arc (-60:0:{2*sqrt(3)});
}

\newcommand{\regionDarkside}[1]
{   \fill[#1,even odd rule] (90:4) arc (120:-60:{2*sqrt(3)}) arc (360:180:{2*sqrt(3)}) arc (240:60:{2*sqrt(3)}) (0,0) circle (7);
}

\newcommand{\mycolor}{blue!50!cyan}
\newcommand{\mynocolor}{white}

\foreach \a in {\mycolor,\mynocolor}
{   \foreach \b in {\mycolor,\mynocolor}
    { \foreach \c in {\mycolor,\mynocolor}
        {   \foreach \d in {\mycolor,\mynocolor}
            {   \foreach \e in {\mycolor,\mynocolor}
                { \foreach \f in {\mycolor,\mynocolor}
                    {   \foreach \g in {\mycolor,\mynocolor}
                        {   \foreach \h in {\mycolor,\mynocolor}
                            {   \begin{tikzpicture}[scale=0.05]
                                    \regionA{\a}
                                    \regionB{\b}
                                    \regionC{\c}
                                    \regionAB{\d}
                                    \regionAC{\e}
                                    \regionBC{\f}
                                    \regionABC{\g}
                                    \regionDarkside{\h}
                                    \draw (30:2) circle ({2*sqrt(3)});
                                    \draw (150:2) circle ({2*sqrt(3)});
                                    \draw (270:2) circle ({2*sqrt(3)});
                                    \draw (0,0) circle (7);
                                    \clip (0,0) circle (7);
                                    \useasboundingbox (0,0) circle (7);
                                \end{tikzpicture}
                            }
                        }
                    }
                }
            }
        }
    }
}
\phantom{X}

\end{document}

在此处输入图片描述

答案4

这是 metapost 版本(使用 lualatex 编译)。部分输出:

在此处输入图片描述

\documentclass{article}
\usepackage{luamplib}

\begin{document}
\begin{mplibcode}
    u:=10;
    path p[];
    picture r[];
    numeric k[];
    cmykcolor mycol;
    mycol:=(0.21,0.12,0,0.07);

    z1 = (u/4,-(u/4)/sqrt(3));
    p1 = fullcircle scaled u;
    p2 = p1 shifted (u/2,0);
    p3 = p1 shifted (u/4,-u/4*sqrt(3));
    p4 = unitsquare scaled 1.6u shifted (-u/2-.05*u,-u);

    p.1 = buildcycle(p1,p2,reverse(p3));
    p.2 = buildcycle(p1,reverse(p2),reverse(p3));
    p.3 = buildcycle(reverse(p1),reverse(p2),reverse(p3));

    r0:=image(draw p1; draw p2; draw p3; draw p4;);
    drawoptions(withcolor mycol);
    r1:=image(fill p4; unfill p1;unfill p2;unfill p3;);
    r2:=image(fill p.1);
    r3:=image(fill p.2);
    r4:=image(fill p.3);
    r5:=image(fill p.1 rotatedabout(z1,120));
    r6:=image(fill p.1 rotatedabout(z1,240));
    r7:=image(fill p.2 rotatedabout(z1,120));
    r8:=image(fill p.2 rotatedabout(z1,240));
    drawoptions();

    % this converts a number to binary
    vardef tobinary(expr n)=
      save m; m = n;
      j:= 1;
      forever: exitunless m>0;
        b:= m mod 2;
        m:= floor (m/2);
        k[j]:=b;
        j:=j+1;
      endfor;
    k[0]:= j-1;
    enddef;

    beginfig(1);
    for i = 0 upto 255:
      drawoptions(shifted (1.6*u*(i div 16), -1.6*u*(i mod 16)));
      tobinary(i);
      for j = 1 upto k[0]:
        if k[j]=1: draw r[j]; fi;
      endfor;
      draw r[0];
    endfor;
    endfig;

end;

\end{mplibcode}
\end{document}

相关内容