如何绘制类似的 Smith-Volterra-Cantor 集(https://en.wikipedia.org/wiki/Smith-Volterra-Cantor_set)?它基本上是通过从单位间隔 开始,从4^{-n}
级的每个间隔的中间移除而形成的。这是来自 wiki 的 Smith-Volterra-Cantor 集的图像:n
[0,1]
我没有成功地制作出康托集代码的类似物(绘制康托集)。
答案1
(我在这个答案的底部添加了对 TikZ 矩形的翻译更新)
这里介绍一种使用的方法\rule
。我使用图片环境主要是为了方便将方法转换为 TikZ 语言,只需将\put
和转换\rule
为其语言即可。
\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}
结果:
该宏\L
保存了间隙长度。它仅使用整数,每次迭代时比例单位(默认)除以 4。此比例中的间隙长度均为偶数,实际规则的长度为奇数(2 的幂加 1)。关于其构造方式的解释,请参阅此评论。
这是翻译成 TikZ 绘图指令,但保留了所有实际算法及其血腥的 TeX 宏......因此我猜这不算作 TikZ 解决方案!
我最初犯了一个错误,使用\filldraw
了 ,而不是\fill
,这会使矩形变厚一些,使得从 4 级或 5 级开始的间隙变得不可见……(无论如何,我们在理性的几何级数上很快达到了亚原子尺度1/4
……)。感谢用户 @Kpym 的帮助。
\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}
这是错误使用\filldraw
where \fill
only must be used
结果如下\fill
:
与使用 LaTeX 相比\rule
:(也是紫色)
答案2
以下是基于的答案lindenmayersystems
。该答案的基础是这个较旧的。
\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}
精度问题在最后一级结束时可见。当阶数超过 4 时,情况会变得更糟。