# How to draw the Smith-Volterra-Cantor set by tikz?

How to draw the similar Smith-Volterra-Cantor set (https://en.wikipedia.org/wiki/Smith-Volterra-Cantor_set)? It is formed basically by removing 4^{-n} from the middle of every interval at level n, starting from the unit interval [0,1]. Here is an image of the Smith-Volterra-Cantor set from wiki:

I did not succeed in making an analog of the codes for Cantor set (Drawing Cantor Set).

• Welcome to TeX.SE. It would be helpful if you provided appropriate links for the two sets you mention and perhaps provide a fully compilable MWE including \documentclass and the appropriate packages that uses the decorations you mention ti draw the Cantor Ternary Set. – Peter Grill Nov 30 '18 at 6:34
• Welcome to TeX.SE! Not everybody knows what a Smith-Volterra-Cantor set is, I think you should add also an image of the desired result (a photo of a manual drawing is enough), other than a minimal example of what you tried so far. – CarLaTeX Nov 30 '18 at 6:54
• @sandu The image you added is the regular Cantor set. I rolled back the edit. – Henri Menke Nov 30 '18 at 10:02
• You can generate iteratively the sequence of lengths of included/excluded by following rule. odd->(2odd-1, 2, 2odd-1), even->4even. With starting state 3, 2, 3 (total 8) which represents first division. Thus 5,2,5,8,5,2,5 (total 32) then 9,2,9,8,9,2,9,32,9,2,9,8,9,2,9 (total 128) then 17,2,17,8,17,2,17,32,17,2,17,8,17,2,17,128,17,2,17,8,17,2,17,32,17,2,17,8,17,2,17 (total 512). Odd length intervals are those of the set, even lengths are the excluded ones. Easy to generate by recursive TeX macros. If you do feel the linked question is not enough, then I agree with re-opening. – user4686 Nov 30 '18 at 21:52
• Here is (proportions) of lengths at next subdivision: {33}{2}{33}{8}{33}{2}{33}{32}{33}{2}{33}{8}{33}{2}{33}{128}{33}{2}{33}{8}{33}{2}{33}{32}{33}{2}{33}{8}{33}{2}{33}{512}{33}{2}{33}{8}{33}{2}{33}{32}{33}{2}{33}{8}{33}{2}{33}{128}{33}{2}{33}{8}{33}{2}{33}{32}{33}{2}{33}{8}{33}{2}{33} (total 2048). – user4686 Nov 30 '18 at 22:15

(I added an update with translation to TikZ rectangles at bottom of this answer)

Here is a way with \rule. I use a picture environment mainly to facilitate conversion of the methode to TikZ lingua, it is only a matter to convert the \put and the \rule into its language.

\documentclass[a4paper]{article}

\usepackage{picture}

\begin{document}

\setlength{\unitlength}{1sp}

\noindent
\begin{picture}(\linewidth,7\baselineskip)(0,-6\baselineskip)
\def\split #1#2\into#3#4{\def#3{#1}\def#4{#2}}%
\def\DrawL{%
\edef\rulewidth{\the\numexpr\y*\totalwidth/\SUM}%
\edef\Zdim{\the\numexpr\Zdim-\baselineskip}%
\def\Y{0}\def\Ydim{0}\let\M\L
\loop
\put(\Ydim,\Zdim){\rule{\rulewidth sp}{.5\baselineskip}}%
\unless\ifx\M\empty
\expandafter\split\M\into\gap\M
\edef\Y{\the\numexpr\Y+\y+\gap}%
\edef\Ydim{\the\numexpr\Y*\totalwidth/\SUM}%
\repeat
}%
\def\UpdateL{%
\edef\x{\the\numexpr4*\x}%
\edef\y{\the\numexpr2*\y-1}%
\edef\SUM{\the\numexpr4*\SUM}%
\edef\L{\L{\x}\L}%
}%
\edef\totalwidth{\number\linewidth}%
\def\Zdim{0}%
\put(0,\Zdim){\rule{\totalwidth sp}{.5\baselineskip}}
\def\L{{2}}\def\x{2}\def\y{3}\def\SUM{8}%
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
%\UpdateL
\end{picture}
\end{document}


Result:

The macro \L holds the sequence of gap lengths. It is uses only integers, the scale unit is (tacitly) divided by 4 at each iteration. The gap lengths are all even in this scale, and the actual rules have odd lengths (a power of 2 plus one). As per the explanations on how it is constructed, see this comment.

Here is translation into TikZ drawing instructions, but keeping all of the actual algorithm with its gory TeX macros... thus this does not count as a TikZ solution I guess!

I initially committed a mistake of using \filldraw, not \fill and this makes rectangles a bit thicker, making invisible the gaps starting at level 4 ot 5 already... (anyway we reach quickly sub-atomic scale on the geometric progression of reason 1/4...). Thanks to user @Kpym for helping out.

\documentclass[a4paper]{article}

\usepackage{tikz}

\begin{document}

\noindent
\begin{tikzpicture}
\def\split #1#2\into#3#4{\def#3{#1}\def#4{#2}}%
\def\DrawL{%
\edef\rulewidth{\the\numexpr\y*\totalwidth/\SUM}%
\edef\Zdim{\the\numexpr\Zdim-\baselineskip}%
%
\def\Y{0}\def\Ydim{0}\let\M\L
\loop
% attention, \fill, not \filldraw !
\fill[color=purple]
(\Ydim sp,\Zdim sp) rectangle +(\rulewidth sp,0.5\baselineskip);
\unless\ifx\M\empty
\expandafter\split\M\into\gap\M
\edef\Y{\the\numexpr\Y+\y+\gap}%
\edef\Ydim{\the\numexpr\Y*\totalwidth/\SUM}%
\repeat
}%
\def\UpdateL{%
\edef\x{\the\numexpr4*\x}%
\edef\y{\the\numexpr2*\y-1}%
\edef\SUM{\the\numexpr4*\SUM}%
\edef\L{\L{\x}\L}%
}%
\edef\totalwidth{\number\linewidth}%
\def\Zdim{0}%
%
\fill[color=purple]
(0,\Zdim) rectangle +(\totalwidth sp,.5\baselineskip);
%
\def\L{{2}}\def\x{2}\def\y{3}\def\SUM{8}%
%
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
\UpdateL
\DrawL
%    \UpdateL
\end{tikzpicture}
\end{document}


Here is with faulty usage of \filldraw where \fill only must be used

Here is result with \fill:

Compare to using LaTeX \rule: (with purple color too)

• thanks it really helps! Hope someone gives a tikz solution. – David Wang Dec 1 '18 at 16:28
• @kwgl the picture already shows one can not go much farther before reaching atomic scale... on the other hand the total number of intervals (included as excluded) grows only like a power of 2 (2^n-1) which even for n=7, 8, isn't gigantic. Thus, clearly, generate them by python e.g. (or you can add \typeout{\meaning\L} above and examine console output), then use search/replace in your editor to convert this into TikZ. You will spend more time trying to automatize it and this may raise problems anyway (TikZ computations will cause overflow easier than \numexpr scaling operations). – user4686 Dec 1 '18 at 22:15
• perhaps TikZ draws the border with a certain width (say 0.4pt) symmetrically around exact mathematical border? (thus 0.2pt added towards exterior ?). One sees very clearly at step 4 that the inner gaps are reduced compared to \rule solution. – user4686 Dec 4 '18 at 13:07
• \filldraw fill and draw ;) so the draw line is centered on the rectangle border so it goes half line width out of the rectangle. By replacing \filldraw with \fill it should be ok, I hope. – Kpym Dec 5 '18 at 10:43

Here is an answer based on lindenmayersystems. The base for this answer is this older one.

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{lindenmayersystems,decorations.pathreplacing,calc}

\tikzset{
% starting options for the Cantor systems
cantor/.style = {
l-system={Cantor, axiom=F, order=#1, step=1cm},
},
% the mid factor will be 1/4,1/16,...
mid factor/.code={
\pgfmathparse{#1}\global\let\midfactor\pgfmathresult
\pgfmathsetmacro{\sidefactor}{(1-\midfactor)/2}
}, mid factor = {1/4},
}
% define the cantor system
\pgfdeclarelindenmayersystem{Cantor}{
\symbol{A}{\pgftransformscale{\sidefactor}}
\symbol{B}{\pgftransformscale{(\midfactor)/(\sidefactor)}}
\symbol{C}{\pgftransformscale{(\sidefactor)/(\midfactor)}}
\symbol{D}{\pgftransformscale{1/(\sidefactor)}}
\symbol{M}{\tikzset{mid factor=\midfactor/2/(1-\midfactor)}}
\symbol{N}{\tikzset{mid factor=\midfactor/(.5+\midfactor)}}
\rule{F -> MAF Bf CF DN}
}
\begin{document}
\begin{tikzpicture}[xscale=10, line width=2mm, purple]
\draw
foreach \order in {0,...,4}{
[yshift=-\order*3mm] l-system [cantor=\order]
};
\end{tikzpicture}
\end{document}


The precision problem can be seen at the end of the last level. And it gets worse for orders over 4.

• who cares about precision with such a nice color? :) – user4686 Dec 4 '18 at 8:36
• perhaps there is a way to maintain precision by using only integers? if I understand correctly \midfactor stands for the ratio of middle gap to length, so 1/4 initially (n=1) then 1/(2^n + 2) (for example at step 2 we have a gap of 1/16 in a length of 3/8 (ratio 1/6), then a gap of 1/64 in a length of 5/32 (ratio 1/10) then a gap of 1/256 in a length of 9/128 (ratio 1/18) and formula 1/(2^n + 2) is confirmed. – user4686 Dec 4 '18 at 8:55
• @jfbu probably you are right, but I have no curage to hack this with "non canonical" solution ;) – Kpym Dec 5 '18 at 10:52