在 Tikz 中使用角度参数制作自定义 Koch 装饰

在 Tikz 中使用角度参数制作自定义 Koch 装饰

因此,我尝试绘制类似于科赫雪花的分形,因此我想定义自己的装饰,该装饰可执行相同的操作,但允许您指定角度。例如,在此图片中,角度为 85 度:

塞萨罗曲线

但我似乎找不到任何关于定义装饰的教程。下面提供的内容只是我从其他装饰问题中收集到的开始部分,但它不起作用。有人能给我一个教程或展示一个允许这样做的代码示例吗?谢谢!

\documentclass[]{standalone}

\usepackage{calc,tikz}
\usetikzlibrary{decorations}

\tikzset{/pgf/decoration/.cd,
    angle/.initial=1.5pt,


% definition of the decoration
\pgfdeclaredecoration{cesaro}{initial}
{
    \state{initial}[width=1pt]%,%
    %next state=midd]
    {
    \def\angle{%
        \pgfkeysvalueof{/pgf/decoration/angle}%
    }   
        % First line
        \pgfpathlineto{\pgfpoint{0.0pt}{$\pgfdecoratedpathlength/2-2*\pgfdecoratedpathlength*cos{\angle}$}}

    }
%   \state{midd}[1pt]



%   \state{final}

}
\begin{document}
    \begin{tikzpicture}[scale=1]
    \node (a) at (0pt,50pt) {};
    \node (b) at (0pt,0pt) {};
    \draw[decorate, decoration={cesaro}] (a) -- (b);
    \end{tikzpicture}



\end{document}

答案1

手册(在基础层章节中)描述了创建装饰的基础知识,但仍有一些技巧可用于使事情变得更有效率:

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{decorations}
\pgfkeys{/pgf/decoration/.cd,
  Koch angle/.store in=\pgfkochangle, Koch angle=85
}
\pgfdeclaredecoration{Koch}{calculate}{
\state{calculate}[width=0pt, next state=draw, persistent precomputation={
  % Exploit the fact that all segment lengths should be the same.
  \pgfmathparse{\pgfdecoratedinputsegmentlength/(2*(1+cos(\pgfkochangle)))}%
  \let\pgfkochsegmentlength=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*sin(\pgfkochangle)}%
  \let\pgfkochy=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*(1 + cos(\pgfkochangle))}%
  \let\pgfkochxa=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*(1 + 2*cos(\pgfkochangle))}%
  \let\pgfkochxb=\pgfmathresult%
}]{}
\state{draw}[width=\pgfdecoratedinputsegmentlength]{
    \pgfpathmoveto{\pgfpointorigin}%
    \pgfpathlineto{\pgfqpoint{\pgfkochsegmentlength pt}{0pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfkochxa pt}{\pgfkochy pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfkochxb pt}{0pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfdecoratedinputsegmentlength}{0pt}}%
}}
\begin{document}
\begin{tikzpicture}
\foreach \a [count=\i] in {60, 72, 85}
  \draw [decoration={Koch, Koch angle=\a}] 
    decorate {decorate {decorate {decorate { decorate {(0,\i*4) -- ++(10,0) }}}}};
\end{tikzpicture}
\end{document}

在此处输入图片描述

虽然使用全局计数器并不理想,但order可以实现一个参数来消除对多个命令的需要decorate

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{decorations}
\newcount\pgfdecorationorder
\pgfkeys{/pgf/decoration/.cd,
  Koch angle/.store in=\pgfkochangle, Koch angle=85,
  Koch order/.code={\global\pgfdecorationorder=#1}, Koch order=1
}
\pgfdeclaredecoration{Koch}{calculate}{
\state{calculate}[width=0pt, next state=draw, persistent precomputation={
  % Exploit the fact that all segment lengths should be the same.
  \pgfmathparse{\pgfdecoratedinputsegmentlength/(2*(1+cos(\pgfkochangle)))}%
  \let\pgfkochsegmentlength=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*sin(\pgfkochangle)}%
  \let\pgfkochy=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*(1 + cos(\pgfkochangle))}%
  \let\pgfkochxa=\pgfmathresult%
  \pgfmathparse{\pgfkochsegmentlength*(1 + 2*cos(\pgfkochangle))}%
  \let\pgfkochxb=\pgfmathresult%
}]{}
\state{draw}[width=\pgfdecoratedinputsegmentlength]{
    \pgfpathmoveto{\pgfpointorigin}%
    \pgfpathlineto{\pgfqpoint{\pgfkochsegmentlength pt}{0pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfkochxa pt}{\pgfkochy pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfkochxb pt}{0pt}}%
    \pgfpathlineto{\pgfqpoint{\pgfdecoratedinputsegmentlength}{0pt}}%
}
\state{final}{
  \global\advance\pgfdecorationorder by -1\relax%
  \ifnum\pgfdecorationorder>0\relax%
    \pgfgetpath\decoratedpath%
    \pgfsetpath\empty%
    \begin{pgfdecoration}{{Koch}{\pgfdecoratedpathlength}}%
      \pgfsetpath\decoratedpath
    \end{pgfdecoration}%
  \fi
}}
\begin{document}
\begin{tikzpicture}
\foreach \i in {1,...,6}
  \draw [decoration={Koch, Koch angle=85, Koch order=\i}] 
    decorate  {(0,\i*5) -- ++(10,0)};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

这是一个使用该lindenmayer库的简单解决方案:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{lindenmayersystems}
\pgfdeclarelindenmayersystem{A}{\rule{F-> F+F--F+F}}
\begin{document}
\begin{tikzpicture}
  \draw[blue,line cap=round]
  [lindenmayer system={A,axiom=F,order=7,angle=80,step=1mm}]
  lindenmayer system;
\end{tikzpicture}
\end{document}

当角度为80时,结果是正确的(顺序=7):

在此处输入图片描述

当角度为 85 度时,计算误差会累积,并且在多次迭代(阶数=6)时清晰可见。

在此处输入图片描述

答案3

我喜欢用 MetaPost 制作分形,所以我忍不住要编写这个程序,使用递归宏,Koch(expr A, B, angl, n)以初始段的极端、角度和所需的递归顺序作为参数。

以下是将角度参数设置为 60、72 和 85(从下到上)、阶数为 5 的结果,如 Mark Wibrow 的示例所示:

vardef Koch(expr A, B, angl, n) =
    if n = 0: 
        draw A -- B;
    else:
        save b, v, C, D, E; pair v, C, D, E;
        v = unitvector(B-A);
        2b * (1 + cosd angl) = abs(B-A);
        C = A + b*v;
        D = .5[A,B] + b * sind angl * v rotated 90;
        E = B - b*v;
        Koch(A, C, angl, n-1); Koch(C, D, angl, n-1); 
        Koch(D, E, angl, n-1); Koch(E, B, angl, n-1); 
    fi
enddef;
beginfig(1);
    k := 0;
    for angl = 60, 72, 85:
        draw image(Koch(origin, (10cm, 0), angl, 5)) shifted (0, k*4cm);
        k := k+1;
    endfor;
endfig;
end.

在此处输入图片描述

为了好玩,这里是将角度设置为 85 时阶数为 8 的结果(可能需要一些时间):

在此处输入图片描述

相关内容