Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
1  
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
1  
You should also consider using tikz. –  Peter Grill Oct 19 '11 at 3:25
5  
There is code for the Cantor set on page 336 of the Tikz/PGF manual –  DJP Oct 19 '11 at 4:30

6 Answers 6

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.

enter image description here

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

share|improve this answer
1  
+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 :

enter image description here

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

\def\onestep#1{\advance\ccnt by1 }  
%%%%%%%%%%%% 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}}%
      \advance\xpos by \xlen 
  \else 
      \advance\xpos by \xlen 
\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 
    \advance\cnti by 1 %
    \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}
share|improve this answer
1  
+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}
share|improve this answer

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.

enter image description here

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}
share|improve this answer

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).

cantor trickle down

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
share|improve this answer

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}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.