# Drawing Cantor Set

I am trying to draw a cantor set in LaTeX and I am having issues doing this. I am trying multiple \put commands, but they just go to the right of one another. Does anyone know how to do this?

Any help would be much appreciated.

-
Welcome to TeX.SE. It is always best to compose a MWE that illustrates the problem including the \documentclass so that those trying to help have something to start with. –  Peter Grill Oct 19 '11 at 3:23
You should also consider using tikz. –  Peter Grill Oct 19 '11 at 3:25
There is code for the Cantor set on page 336 of the Tikz/PGF manual –  DJP Oct 19 '11 at 4:30

Just a try with MetaPost. So late after the question, it is really for the fun: it has been a long, long while since the last time I did some recursive programming :-). (Recursive programming is certainly the best way to tackle this sort of task.)

pair v; v = (0, -1cm);

def cantor_set(expr segm, n) =
draw segm;
if n>1:
cantor_set((point 0 of segm -- point 1/3 of segm) shifted v, n-1);
cantor_set((point 2/3 of segm -- point 1 of segm) shifted v, n-1);
fi;
enddef;

beginfig(1);
pickup penrazor rotated 90 scaled .5cm;
cantor_set(origin -- (12cm, 0), 6);
endfig;
end.


Edit: I've changed the "circle" pen for a "razor" pen, which gives a much better drawing precision.

-
+1 I honestly feel that MetaPost is the best tool for this task, especially considering the innate recursion involved. –  Sean Allred Mar 15 at 19:18
@SeanAllred I suppose Asymptote would also do well. I may write an Asymptote version of this program later. But can't tikz do recursion itself? –  fpast Mar 15 at 19:41
Yes, but the overhead doesn't really make sense for a TeX-native solution. –  Sean Allred Mar 15 at 19:46

Yes the pgfmanual gives a way in Fractal Decorations but it's more funny to find a personal way. I don't find very pretty the syntax to use with decoration.

The next code gives a macro \cantor without tikz. The macro needs two arguments : the first one is the step and the second is the length of the line.

To get :

you need to write :

\unitlength=1pt
\linethickness{3mm}
\xlen=270pt
\cantor{1}{270pt}\par
\cantor{2}{270pt}\par
\cantor{3}{270pt}\par
\cantor{4}{270pt}\par
\cantor{5}{270pt}\par
\cantor{6}{270pt}


Here the complete code

\documentclass{article}
\usepackage{fp}
\newcount\cnt \cnt=1
\newcount\ccnt \ccnt=0
\newdimen\xpos
\newdimen\xlen
\newcount\cnti
\makeatletter

%%%%%%%%%%%% main macro %%%%%%%%%%%%%%%%%%%
% get a string composed with 0 and  1.  If 1 a line is drawn.
% The string  is stored in \tmp
% the length of the string is  stored in \ccnt
\def\scan#1#2\end{%
\def\aux{#1}%
\ifx\aux\empty
\else
\ifnum #1=1
\ifnum\ccnt=0  \def\tmp{101}%
\else
\expandafter\def\expandafter\tmp\expandafter{\tmp 101}%
\fi
\else
\expandafter\def\expandafter\tmp\expandafter{\tmp 000}%
\fi
\def\aux{#2}%
\onestep{#1}%
\ifx\aux\empty
\else
\scan#2\end
\fi
\fi
\gdef\compteur{\the\ccnt}%
}%
%%%%%%%%%%%%% draw a line %%%%%%%%%%%%%%%%%%
\def\scandraw#1#2\end{%
\def\aux{#1}%
\ifnum #1=1
\put(\strip@pt\xpos,0){\line(1,0){\strip@pt\xlen}}%
\else
\fi
\def\aux{#2}%
\ifx\aux\empty
\else
\scandraw#2\end
\fi
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\cantor#1#2{%
\xpos=0pt \xlen=#2
\noexpand\def\tmp{1}
\ifnum #1>1
\cnti=1
\loop
\ccnt=0
\expandafter\scan \tmp\end
\ifnum \cnti<#1
\repeat
\FPeval{\tmpxlen}{\strip@pt\xlen/(3*\compteur)}%
\xlen=\tmpxlen pt
\fi
\begin{picture}(0,15)
\expandafter\scandraw \tmp\end
\end{picture}
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatother
\begin{document}

\unitlength=1pt
\linethickness{3mm}
\xlen=270pt
\cantor{1}{270pt}\par
\cantor{2}{270pt}\par
\cantor{3}{270pt}\par
\cantor{4}{270pt}\par
\cantor{5}{270pt}\par
\cantor{6}{270pt}
\end{document}

-
+1 for doing it without TikZ –  alexwlchan Mar 15 at 18:37

Here is my version of the first five rows for the Cantor set:

\begin{picture}(1.1,0.40)(-0.1, -0.1)
\put(0.45, 0.27){$S^c = C$}
\put(0, 0){\line(1, 0){1}}
\put(0, -0.025){\line(0, 1){0.025}}
\put(1, -0.025){\line(0, 1){0.025}}
\put(0, -0.05){\small 0}
\put(1, -0.05){\small 1}

\put(0, 0.25){\line(1, 0){1}}

% (0, 2) / 3
\put(0.0000, 0.20){\line(1, 0){0.3333}}
\put(0.6667, 0.20){\line(1, 0){0.3333}}

% (0, 2, 6, 8) / 9
\put(0.0000, 0.15){\line(1, 0){0.1111}}
\put(0.2222, 0.15){\line(1, 0){0.1111}}
\put(0.6667, 0.15){\line(1, 0){0.1111}}
\put(0.8889, 0.15){\line(1, 0){0.1111}}

% (0, 2, 6, 8, 18, 20, 24, 26) / 27
\put(0.0000, 0.10){\line(1, 0){0.037}}
\put(0.0741, 0.10){\line(1, 0){0.037}}
\put(0.2222, 0.10){\line(1, 0){0.037}}
\put(0.2963, 0.10){\line(1, 0){0.037}}
\put(0.6667, 0.10){\line(1, 0){0.037}}
\put(0.7407, 0.10){\line(1, 0){0.037}}
\put(0.8889, 0.10){\line(1, 0){0.037}}
\put(0.9630, 0.10){\line(1, 0){0.037}}

% (0, 2, 6, 8, 18, 20, 24, 26, 54, 56, 60, 62, 72, 74, 78, 80) / 81
\put(0.0000, 0.05){\line(1, 0){0.0123}}
\put(0.0247, 0.05){\line(1, 0){0.0123}}
\put(0.0741, 0.05){\line(1, 0){0.0123}}
\put(0.0988, 0.05){\line(1, 0){0.0123}}
\put(0.2222, 0.05){\line(1, 0){0.0123}}
\put(0.2469, 0.05){\line(1, 0){0.0123}}
\put(0.2963, 0.05){\line(1, 0){0.0123}}
\put(0.3210, 0.05){\line(1, 0){0.0123}}
\put(0.6667, 0.05){\line(1, 0){0.0123}}
\put(0.6914, 0.05){\line(1, 0){0.0123}}
\put(0.7407, 0.05){\line(1, 0){0.0123}}
\put(0.7654, 0.05){\line(1, 0){0.0123}}
\put(0.8889, 0.05){\line(1, 0){0.0123}}
\put(0.9136, 0.05){\line(1, 0){0.0123}}
\put(0.9630, 0.05){\line(1, 0){0.0123}}
\put(0.9877, 0.05){\line(1, 0){0.0123}}

\end{picture}

-

Although I would highly recommend using tikz, here is an example of using the \put command.

The syntax is \put(x,y){} where (x,y) is the coordinate of the start point, a the object to be placed at this coordinate is passed in as a parameter within the {} braces. Below I specified this object to be a line with the \line(u,v){n} command. In this case (u,v) is the direction vector of the line and the length of this line is passed in as n.

Here is the code for the above picture. If this does not help, please use this as a start to create a small piece of code the illustrates the problem that you are having.

\documentclass{article}
\begin{document}
\setlength{\unitlength}{1cm}
\begin{picture}(2, 2)
\put(0,0){\line(0,1){3}}% Vertical line of length 3 starting at (0,0)
\put(0,2){\line(1,0){1}}% Horizontal line of length 1 starting at (0,2)
\put(0,1){\line(1,0){5}}% Horizontal line of length 5 starting at (0,1)
\end{picture}
\end{document}

-

Let's do it again with TeX rules. I gave some thought to code efficiency. I do not use a loop as anyhow it can not decently go very far, if we want to draw something not at the sub-atomic scale...

The code defines a macro \cantorrule: the first parameter is the level (from 0 to 8; this parameter may be \count) the second a total width, the third a height (no depth parameter).

Code needs e-TeX (etex, pdftex on modern installations, etc..)

% first, commented-out, this method which is nice and elegant but
% not very efficient
% \def\1{\noexpand\1\noexpand\0\noexpand\1}
% \def\0{\noexpand\0\noexpand\0\noexpand\0}
% \def\cantor     {\1}
% \edef\cantori   {\cantor}   % 3
% \edef\cantorii  {\cantori}  % 9
% \edef\cantoriii {\cantorii} % 27
% \edef\cantoriv  {\cantoriii} % 81
% \edef\cantorv   {\cantoriv} % 243
% \edef\cantorvi  {\cantorv}  % 729
% \edef\cantorvii {\cantorvi} % 2187 % already very large-> tiny dimensions

% furthermore in the sequel we avoid sequences of  \0 we prefer
% \0{j} with j an integer
\newtoks\zerotoks
\newtoks\cantortoks

\def\cantor {\1} % 1
\cantortoks {\1}
\zerotoks   {\0{1}}

% we could do a loop, but what's the point as for example
% 3^10 is already 59049 and that will make truly tiny distances...

\edef\cantori {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantori}
\zerotoks   {\0{3}}

\edef\cantorii {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantorii}
\zerotoks   {\0{9}}

\edef\cantoriii {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantoriii}
\zerotoks   {\0{27}}

\edef\cantoriv {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantoriv}
\zerotoks   {\0{81}}

\edef\cantorv {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantorv}
\zerotoks   {\0{243}}

\edef\cantorvi {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantorvi}
\zerotoks   {\0{729}}

\edef\cantorvii {\the\cantortoks\the\zerotoks\the\cantortoks}
\cantortoks \expandafter{\cantorvii}
\zerotoks   {\0{2187}}

\edef\cantorviii {\the\cantortoks\the\zerotoks\the\cantortoks}

% does not make much sense to go any further, already \cantorviii has
% subdivisions of length 1/6561 of the total width
% \cantortoks \expandafter{\cantorvii}
% \zerotoks   {\0{6561}}

\def\cantorrule #1#2#3{% #1=0,1,2,..,7, 8; #2=width; #3=height
\leavevmode
\begingroup
\edef\x{\the\numexpr \dimexpr#2\relax/\ifcase \numexpr #1\relax
1\or 3\or 9\or 27\or 81\or 243
\or 729\or 2187\or 6561\else 1\fi\relax}%
\def\1{\vrule height \dimexpr #3\relax
width \dimexpr \x sp\relax
depth 0pt }%
\def\0##1{\kern \dimexpr \numexpr ##1*\x sp\relax }%
\hbox{\csname cantor\romannumeral#1\endcsname}%
% to allow #1 to be an infix expression like 2+3 or 7-4 one may use rather
%       \hbox{\csname cantor\romannumeral\numexpr #1\endcsname}%
\endgroup
}

\offinterlineskip
\noindent\cantorrule {0}{\hsize}{2cm}\par
\noindent\cantorrule {1}{\hsize}{2cm}\par
\noindent\cantorrule {2}{\hsize}{2cm}\par
\noindent\cantorrule {3}{\hsize}{2cm}\par
\noindent\cantorrule {4}{\hsize}{2cm}\par
\noindent\cantorrule {5}{\hsize}{2cm}\par
\noindent\cantorrule {6}{\hsize}{2cm}\par
\noindent\cantorrule {7}{\hsize}{2cm}\par
\noindent\cantorrule {8}{\hsize}{2cm}\par % has 2^8 = 256 little rules

\nopagenumbers

\bye

-

Just for reference, here is a TikZ solution derived from the TikZ/PGF manual:

\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.fractals}
\begin{document}
\begin{tikzpicture}[decoration=Cantor set,line width=3mm]
\draw (0,0) -- (3,0);
\draw decorate{ (0,-.5) -- (3,-.5) };
\draw decorate{ decorate{ (0,-1) -- (3,-1) }};
\draw decorate{ decorate{ decorate{ (0,-1.5) -- (3,-1.5) }}};
\draw decorate{ decorate{ decorate{ decorate{ (0,-2) -- (3,-2) }}}};
\end{tikzpicture}
\end{document}


-