I am running Ubuntu version 11.04 with PGF
package version 2.00-1.
I have trouble running this sample code posted to
How to generate all possible Venn diagrams (with the case below) efficiently?
\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}
After I changed documentclass to article
, I got this error
! Package PGF Math Error: Unknown function `Mod'
I thought may be my version of PGF
is old and therefore missing the Mod
function. Did sudo apt-get update
to get all missing updates, but the
error did not go away. Do I need to upgrade the level of Ubuntu to a higher
to get around this message?
After replacing all instances of Mod
with mod
in above code, I got this
error
! Illegal unit of measure (pt inserted).
<to be read again>
?
l.57 \venn{10000000}
I need help in getting around this error and getting this sample run successfully.
The \venn command accepts a 8 digit binary string, goes over each digit and if a digit is 1, fills certain areas. For example, calling \venn{00000010} will fill everything in circle A which does not overlap with circle B or C.
Code relevant to iteration of binary string:
\def\venn@strip#1#2\venn@STOP{%
\def\venn@next{#1}%
\gdef\venn@rest{#2}%
}
\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
..............
I went through basic info about \def statement at http://en.wikibooks.org/wiki/TeX/def and confused about the \venn@STOP in \venn@strip after end of second argument and start of macro contents. All examples, I have seen have macro name followed by any optional arguments, immediately followed by contents of macro.
In a call of \venn{00000010}, before start of the 'for' loop, \venn@rest will be assigned 0000001000000000. In the 1st iteration \venn@next will be assigned 0000001000000000(same as what was passed into first argument) and \venn@rest will be assigned ""(nothing), same as what was passed into second argument to \venn@strip which was \venn@STOP(which has not been defined at this point). The \ifnum statement expects in \venn@next either a 0 or 1 for the position in the binary string corresponding to current iteration. I don't see where in the code such stripping of digits is happening.
The \relax directive asks TeX to do nothing. Not sure why we need \relax as part of \ifnum statement.
On a call of \venn{00000010}, statements related to filling are
\begin{scope}[even odd rule]
\path[clip] (S-SE) rectangle (S-NW) (A) circle[radius=2];
\path[clip] (B) circle[radius=2];
\path[clip] (C) circle[radius=2];
\fill[rounded corners,red] (S-SE) rectangle (S-NW);
\end{scope}
In iteration 2 of the for loop, \i = 1 and this is the only iteration which fills anything in the call.
Based on what is mentioned in the PGF manual, a clipping path restricts painting to a certain area. Also, multiple clippings accumulate and clipping is always done against the intersection of all clipping areas that have been specified inside the current scope.
The first clip statement, gives the circle at A as the clipping area. The second clip statement, gives the intersection of circle at A and B as the clipping area. The third third clip statement gives the intersection region of circles A, B and C as the clipping area. At the end when the rectangle is being filled, I expect the clipped area to be filled. Instead, what is filled is the area in circle A which is not overlapping with circle B or C.
The even odd rule probably makes the fill to work the way it does. This rule is explained in the manual in terms of shooting rays and count how often we hit the path. I could not understand how to use it.