\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.fractals}
\begin{document}
\usetikzlibrary {decorations.fractals}
\begin{tikzpicture}[line width=20pt, decoration=Cantor set]
{ \sffamily \bfseries \Huge
\begin{scope}[rotate=90]
\clip (0,.5) rectangle +(1,-4.85);
\draw decorate{ (0,0) -- (3,0) } node[white] at (0.5,0) { C};
\draw decorate{ decorate{ (0,-.75) -- (3,-.75) }} node[white] at (0.5,-0.75) {A};
\draw decorate{ decorate{ decorate{ (0,-1.5) -- (3,-1.5) }}} node[white] at (0.5,-1.5) {N};
\draw decorate{ decorate{ decorate{ decorate{ (0,-2.25) -- (3,-2.25) }}}} node[white] at (0.5,-2.25) {T};
\draw decorate{ decorate{ decorate{ decorate{ decorate{ (0,-3) -- (3,-3) }}}}} node[white] at (0.5,-3) {O};
\draw decorate{ decorate{ decorate{ decorate{ decorate{ decorate { (0,-3.75) -- (3,-3.75) }}}}}} node[white] at (0.5,-3.75) {R};
\end{scope}
}
\end{tikzpicture}
\end{document}
这个解决方案似乎是蛮力型的。我问你是否存在其他类型的剪辑来实现这种效果。
答案1
这是一个递归剪辑解决方案。
似乎从第五次递归计算开始,TeX/PGFMath 的精度就不够了,或者我的渲染器不再喜欢它了。
对于行X
s,PDF 到 PNG 转换器的分辨率已经太低了。我已将巨大的添加M
到示例中。
下面给出的解决方案单独剪辑每个字母。
如同dexteritas 的回答可以在整个区域安装一个剪辑,但这不会提高效率,因为剪辑掉的部分A
也会被剪辑掉N
。尽管此解决方案需要scope
为每个字母安装一个,但似乎并不会减慢速度。
代码
\documentclass[varwidth, border=1pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc, chains}
\tikzset{
cantor/start/.initial=0,
cantor/picture/.style={
start chain=going base right, node distance=+0mm, baseline=(chain-begin.base)},
cantor/node/.style={
text=black, inner sep=+0pt, outer sep=+0pt, node font=\sffamily\bfseries\Huge},
cantor/cantor/.style n args={3}{insert path={
coordinate (@1-#1) at ({$(#2)!.33333!(#3)$}-|#3)
\ifnum#1=1 (#2) rectangle (@1-#1)
\else [cantor/cantor/.expanded={\pgfinteval{#1-1}}{#2}{@1-#1}] \fi
coordinate (@2-#1) at ({$(#2)!.66667!(#3)$}-|#2)
\ifnum#1=1 (@2-#1) rectangle (#3)
\else [cantor/cantor/.expanded={\pgfinteval{#1-1}}{@2-#1}{#3}] \fi}}}
\newcommand*\cantortext[2][]{%
\begin{tikzpicture}[cantor/picture,#1]
\foreach[count=\CNT from \pgfkeysvalueof{/tikz/cantor/start}]\LTR in{#2}{
\node[cantor/node,on chain]{\phantom{\LTR}};
\begin{scope}
\ifnum\CNT>0 \clip[cantor/cantor={\CNT}{chain-end.south west}
{chain-end.north east}];\fi
\node[cantor/node]at(chain-end){\LTR};
\end{scope}}
\end{tikzpicture}}
\begin{document}
\Huge\bfseries\sffamily % just to have the same text in document as in TikZ
CANTOR\par
\cantortext{C, A, N, T, O, R}\par
\cantortext[cantor/start=3]{X, X, X, X, X, X}
%\cantortext[transform shape, scale=5, cantor/start=5]{M}
\end{document}
输出
答案2
我使用纯 pdfTeX 想出了这个解决方案。在我开始研究这个解决方案之前,我没有注意到您指定了 TikZ,而当我注意到时,我已经花了一些时间。如果这不能帮助回答您的问题,我很抱歉。
%% Useful TeX macros
\bgroup
\lccode`\?=`\p \lccode`\!=`\t
\lowercase{\egroup\def\rmpt#1?!{#1}}
% \idim{<dimension expression>} -> the evaluation of the expression without a dimension
\def\idim#1{\expandafter\rmpt\the\dimexpr #1\relax}
\def\gobble#1{}
% \map<\macro>{<general text>} -> applies \macro to every group in <general text>
\long\def\map#1#2{\mapA{#1}#2\nul}
\long\def\mapA#1#2{%
\ifx\nul#2%
\let\next=\gobble%
\else%
#1{#2}%
\let\next=\mapA%
\fi%
\next{#1}%
}
%% Helper macros for \cantorize
\def\cantorizeA#1#2#3#4{%
\ifnum#1>0 %
#2 #3 \cantorwd, #4 re
\cantorizeA{\the\numexpr #1-1\relax}%
{\idim{#2pt + \cantorwd,pt}}%
{#3}%
{\idim{#4pt / 3}}%
\cantorizeA{\the\numexpr #1-1\relax}%
{\idim{#2pt + \cantorwd,pt}}%
{\idim{#3pt + #4pt * 2 / 3}}%
{\idim{#4pt / 3}}%
\fi%
}
% Typeset character with width \cantorwd,
\def\cantorsetwidth#1{\hbox to\cantorwd,pt{\hss#1\hss}}
\newcount\cantorlen
% Update cantorlen and cantorwd
\def\cantorgetlen#1{%
\advance\cantorlen by 1\relax%
\setbox0=\hbox{#1}%
\ifdim\wd0>\cantorwd,pt\relax%
\edef\cantorwd,{\idim{\wd0}}%
\fi%
}
% vertical buffer around text in \cantorize
\def\cantorbuf,{.2}
\def\cantorize#1{{%
\setbox0=\hbox{#1}%
\def\cantorwd,{0}%
\edef\cantorht,{\idim{\ht0 + \cantorbuf,pt * 2}}%
\cantorlen=0\relax%
\map\cantorgetlen{#1}%
\quitvmode\pdfsave%
\pdfliteral{.96859 0 0 .96859 0 0 cm \cantorizeA{\cantorlen}{0}{-\cantorbuf,}{\cantorht,} W n}%
\rlap{\map\cantorsetwidth{#1}}%
\pdfrestore%
\hskip\cantorlen\dimexpr\cantorwd,pt\relax%
}}
%% Showcasing \cantorize
% Bigger font for showcasing the macro
\font\bigss=cmssbx10 at 50pt
{\bigss\cantorize{CANTOR}}
这样就不会绘制白色矩形,而是剪切文本,因此如果您还想使用背景颜色,则无需更改任何内容。
答案3
描述
首先,每个字符都绘制在自己的节点中。由于我没有找到反转康托尔集装饰结果的方法,所以我从头开始并定义了一个递归函数\drawmiddleline
。它在文本上绘制白线。它的四个参数在代码中描述。在下图中,我使用了不同的颜色(从浅红色到深红色)来展示它是如何一步一步绘制的。
我保存了当前级别,\cslet{dml-#2}{\level}
因为第一次递归调用会改变变量\level
,但第二次递归调用仍然需要该变量。
为了获得没有深度的字母高度,我使用了:
\settoheight{\myheight}{\huge A}%
\myspacing
定义字符节点之间的空间。
当然,您可以将字体更改为其他字体,但我认为这不是主要问题。
结果
代码
\documentclass[margin=2mm]{standalone}
\usepackage{etoolbox}
\usepackage{tikz}
\newcommand{\drawmiddleline}[4]{
% #1 = char index
% #2 = current level
% #3 = current width
% #4 = current yshift
\ifnumequal{#2}{1}{
% \pgfmathsetmacro{\c}{20*#1}
% \draw[red!\c!white, line width=#3/3] ([yshift=#4] c#1.west) -- ([yshift=#4] c\n.east);
\draw[white, line width=#3/3] ([yshift=#4] c#1.west) -- ([yshift=#4] c\n.east);
}{
\pgfmathsetmacro{\level}{int(#2-1)}
\cslet{dml-#2}{\level}
\drawmiddleline{#1}{\csuse{dml-#2}}{#3/3}{#4+#3/3}
\drawmiddleline{#1}{\csuse{dml-#2}}{#3/3}{#4-#3/3}
}
}
\newcommand{\cantortext}[1]{
\foreach \char [count=\i from 0] in {#1} {
\node[anchor=south west, inner sep=.3pt, font=\huge] (c\i) at (\i*\myspacing,0) {\char};
\xdef\n{\i}
}
\foreach \i in {1, ..., \n} {
\drawmiddleline{\i}{\i}{\the\myheight}{0pt}
}
}
\begin{document}
\newlength{\myheight}%
\settoheight{\myheight}{\huge A}%
\newlength{\myspacing}%
\setlength{\myspacing}{5mm}%
\begin{tikzpicture}
\cantortext{C,A,N,T,O,R}
\end{tikzpicture}
\end{document}