如何在 TikZ 中迭代/延续一个模式?

如何在 TikZ 中迭代/延续一个模式?

我需要在 TikZ 中绘制一个图表,虽然我得到的结果看起来像我预期的那样,但我想知道是否有更好/更通用的解决方案来解决我的问题。

基本上,我想绘制一个具有 n 个连接的节点(在我的实现中为 3),然后重复/继续该模式(根据我想要继续该模式的连接进行旋转和平移)。

我想知道是否有可能得到如下解决方案:

 \drawGraph{(position0)}{rotation0}{[2,3,1,3,1,3,3,3,3,2]}

得到与我所实现的类似的东西。

这是我当前的解决方案:

    \documentclass{article}
    \usepackage{ifthen}
    \usepackage{tikz}
    \usetikzlibrary{calc}
    \begin{document}

    \begin{tikzpicture}
        \newcommand\robotMovement[3]{
            \begin{scope}[shift={#1},rotate=#2,black!30]
                \ifthenelse{\equal{#3}{2}}{\draw[black,thick]}{\draw} (0,0) arc (0:45:1cm);
                \ifthenelse{\equal{#3}{1}}{\draw[black,thick]}{\draw} (0,0) -- (0,1cm);
                \ifthenelse{\equal{#3}{3}}{\draw[black,thick]}{\draw} (0,0) arc (0:-45:-1cm);
            \filldraw (0,0) circle (0.1cm);
            \end{scope}
        }
        % The whole map
        \draw (0,0) rectangle (5cm,5cm);
        \clip (0,0) rectangle (5cm,5cm);

        % Obstacles
        \draw[fill=black] (3cm,2cm) rectangle (5cm,2.5cm);
        \draw[fill=black] (3cm,2.5cm) rectangle (3.5cm,4cm);

        % Robot C-space coordinates
        \coordinate (path00) at (4.6cm,0.6cm);

        \coordinate (path0f) at ($(path00)+(0,1cm)$);
        \coordinate (path01) at ($(path00)!   1!   45:(path0f)$);
        \coordinate (path02) at ($(path00)!0.79! 22.5:(path01)$);
        \coordinate (path03) at ($(path00)!0.79!-22.5:(path01)$);

        \coordinate (path1f) at ($(path02)+(0,1cm)$);
        \coordinate (path11) at ($(path02)!   1!   90:(path1f)$);
        \coordinate (path12) at ($(path02)!0.79! 22.5:(path11)$);
        \coordinate (path13) at ($(path02)!0.79!-22.5:(path11)$);

        \coordinate (path2f) at ($(path13)+(0,1cm)$);
        \coordinate (path21) at ($(path13)!   1!   45:(path2f)$);
        \coordinate (path22) at ($(path13)!0.79! 22.5:(path21)$);
        \coordinate (path23) at ($(path13)!0.79!-22.5:(path21)$);

        \coordinate (path3f) at ($(path23)+(0,1cm)$);
        \coordinate (path31) at ($(path23)!   1!   45:(path3f)$);
        \coordinate (path32) at ($(path23)!0.79! 22.5:(path31)$);
        \coordinate (path33) at ($(path23)!0.79!-22.5:(path31)$);

        \coordinate (path4f) at ($(path31)+(0,1cm)$);
        \coordinate (path41) at ($(path31)!   1!    0:(path4f)$);
        \coordinate (path42) at ($(path31)!0.79! 22.5:(path41)$);
        \coordinate (path43) at ($(path31)!0.79!-22.5:(path41)$);

        \coordinate (path5f) at ($(path41)+(0,1cm)$);
        \coordinate (path51) at ($(path41)!   1!    0:(path5f)$);
        \coordinate (path52) at ($(path41)!0.79! 22.5:(path51)$);
        \coordinate (path53) at ($(path41)!0.79!-22.5:(path51)$);

        \coordinate (path6f) at ($(path53)+(0,1cm)$);
        \coordinate (path61) at ($(path53)!   1!  -45:(path6f)$);
        \coordinate (path62) at ($(path53)!0.79! 22.5:(path61)$);
        \coordinate (path63) at ($(path53)!0.79!-22.5:(path61)$);

        \coordinate (path7f) at ($(path63)+(0,1cm)$);
        \coordinate (path71) at ($(path63)!   1!  -90:(path7f)$);
        \coordinate (path72) at ($(path63)!0.79! 22.5:(path71)$);
        \coordinate (path73) at ($(path63)!0.79!-22.5:(path71)$);

        \coordinate (path8f) at ($(path73)+(0,1cm)$);
        \coordinate (path81) at ($(path73)!   1! -135:(path8f)$);
        \coordinate (path82) at ($(path73)!0.79! 22.5:(path81)$);
        \coordinate (path83) at ($(path73)!0.79!-22.5:(path81)$);

        \coordinate (path9f) at ($(path83)+(0,1cm)$);
        \coordinate (path91) at ($(path83)!   1! -135:(path9f)$);
        \coordinate (path92) at ($(path83)!0.79! 22.5:(path91)$);
        \coordinate (path93) at ($(path83)!0.79!-22.5:(path91)$);

        \robotMovement{(path00)}{45}{2}
        \robotMovement{(path02)}{90}{3}
        \robotMovement{(path13)}{45}{1}
        \robotMovement{(path21)}{45}{3}
        \robotMovement{(path31)}{0}{1}
        \robotMovement{(path41)}{0}{3}
        \robotMovement{(path53)}{-45}{3}
        \robotMovement{(path63)}{-90}{3}
        \robotMovement{(path73)}{-135}{3}
        \robotMovement{(path83)}{-180}{2}
        \filldraw[black!70] (path93) circle (0.1cm);

        % Robot
        \begin{scope}[shift={(4.6cm,0.6cm)},rotate=45,scale=0.5]
        % Body
        \draw[fill=white] (-3mm,-3mm) rectangle (3mm,3mm);
        % Wheels
        \draw[fill=black] (-4mm,0.75mm) rectangle (-3mm,2.25mm);
        \draw[fill=black] (3mm,0.75mm) rectangle (4mm,2.25mm);
        \draw[fill=black] (-4mm,-0.75mm) rectangle (-3mm,-2.25mm);
        \draw[fill=black] (3mm,-0.75mm) rectangle (4mm,-2.25mm);
        \end{scope}
    \end{tikzpicture}
    \end{document}

生成如下内容: 大车

答案1

这对于这个特殊情况来说非常特殊,但它几乎可以推广到更多路径情况。这个想法本质上是一样的。

我为三向路径替代方案编写了一个简单的装饰,并将其绘制在原始路径下方。然后绘制路径本身并在其上放置一个点装饰。许多参数可以移动到键并单独设置,但这取决于您的方便和用例。

要使用它,需要两个参数。第一个参数是起始方向的 45 的倍数,第二个参数是路径选择数组。我从左转、直行、右转数到一到三。例如,

\robotrace{5}{3,1,2,1} 

从面向西南开始,向右转、向左转、直行,然后再向左转。您也可以将此命令放在范围内,然后移动它以更改初始点。

所以整个代码是;

\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{decorations}
\pgfdeclaredecoration{xroad}{junction}{%
\state{junction}[width=\pgfdecoratedinputsegmentlength]{%
\pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfpointpolar{0}{1cm}}%
\pgfpathmoveto{\pgfpointorigin}\pgfpatharc{90}{45}{1cm}%
\pgfpathmoveto{\pgfpointorigin}\pgfpatharc{90}{135}{-1cm}}%
}
\pgfdeclaredecoration{xpost}{dot}{%
\state{dot}[width=\pgfdecoratedinputsegmentlength]{%
\pgfsetfillcolor{gray!50}
\pgfpathcircle{\pgfpointorigin}{1mm}\pgfusepath{fill}}%
}

\def\robotrace#1#2{
\def\mytotalrot{#1}
\draw[preaction={decorate,decoration={xroad},draw,very thin,gray},
      postaction={decoration=xpost,decorate}]
(0,0) \foreach\x in {#2}{
\ifnum\x>1\ifnum\x>2%
    arc (90+\mytotalrot*45:{90+(\mytotalrot-1)*45}:1cm)
  \else
    --++(\mytotalrot*45:1cm)
  \fi\else
    arc (-90+\mytotalrot*45:{-90+(\mytotalrot+1)*45}:1cm)
\fi
\pgfextra{\pgfmathparse{\mytotalrot+2-\x}\xdef\mytotalrot{\pgfmathresult}}}
    node[circle,fill=black,inner sep=0,minimum size=2mm]{};
}

\begin{document}
\begin{tikzpicture}
\draw[style=help lines] (0,0) grid[step=1cm] (5,5);
\robotrace{1}{2,3,1,1,1,3,3,2,3,3,3,2,2,3,1,1}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

我认为这样就可以了。

\documentclass[border=5]{standalone}
\usepackage{tikz} 
\usetikzlibrary{decorations.pathreplacing}
\tikzset{%
  robot/.style={
     %robot path,
     postaction={decoration={robot}, decorate},
     robot movements/.cd, #1
  },
  robot swoosh/.style={draw=gray},
  robot movements/.cd,
  .unknown/.code={
    \let\robotkey\pgfkeyscurrentname% 
    \pgfkeys{/tikz/\robotkey/.try={#1}}%
  },
  robot step/.store in=\robotstep,
  robot step=3cm,
  robot swoosh factor/.store in=\robotswooshfactor,
  robot swoosh factor=1.25,
  home/.style={ insert path={ (0,0)  } },
  forward/.style={ 
    insert path={ [shift=(90:\robotstep)] -- (0,0) } 
  },
  left/.style={ 
    insert path={ arc (0:45:\robotstep*sqrt 2)
    [shift=(112.5:2*\robotstep*sqrt 2*sin 22.5),rotate=45] } 
  },
  right/.style={ 
    insert path={  arc (180:135:\robotstep*sqrt 2)
    [shift=(90-22.5:2*\robotstep*sqrt 2*sin 22.5),rotate=-45] } 
  },
  turn left/.style={ rotate=45 },
  turn right/.style={ rotate=-45 },
  stop/.style={  insert path={ (0,0)  } }
}
\def\curvetotext{curveto}

\pgfdeclaredecoration{robot}{start}{
\state{start}[next state=draw, width=0pt]{
\fill [black!75] circle [radius=0.25];}
\state{draw}[width=\pgfdecoratedinputsegmentlength,
switch if less than=\pgfdecoratedinputsegmentlength+1pt to final]{%
  \dorobotswoosh
  \fill [black!50] circle [radius=0.25];
}
\state{final}{
  \dorobotswoosh 
  \dorobot
}
}

\def\getrobotangle{%
\pgfmathparse{\pgfdecoratedinputsegmentstartangle-\pgfdecoratedinputsegmentendangle}
\pgfmathparse{int(round(\pgfmathresult/45)*45)}%
\pgfmathparse{\pgfmathresult >180 ? \pgfmathresult-360 : \pgfmathresult}
\pgfmathparse{\pgfmathresult <-180 ? 360+\pgfmathresult : \pgfmathresult}
\let\robotangle=\pgfmathresult
\pgftransformshift{\pgfpointdecoratedinputsegmentlast}%
\pgftransformresetnontranslations
\pgftransformrotate{\pgfdecoratedinputsegmentendangle}%
}
\def\dorobotswoosh{%
  \getrobotangle%
  \ifx\pgfdecorationcurrentinputsegment\curvetotext
  \draw [robot swoosh/.try] (0,0) -- (180:\robotstep/2*\robotswooshfactor) [yscale=\robotangle/45] 
   (0,0) arc (270:225:\robotstep*\robotswooshfactor/sqrt 2 and \robotstep/2);
  \else
    \draw [robot swoosh/.try] 
   (0,0) arc (270:225:\robotstep*\robotswooshfactor/sqrt 2 and \robotstep/2)
   [yscale=-1] 
   (0,0) arc (270:225:\robotstep*\robotswooshfactor/sqrt 2 and \robotstep/2);
  \fi
}%
\def\dorobot{
 \filldraw [fill=white, draw=black]
     (-0.5,-0.5) rectangle ++(1,1);
 \fill (-0.375,0.375) rectangle ++(0.25,0.25)
 (0.375,0.375) rectangle ++(-0.25,0.25)
 (-0.375,-0.375) rectangle ++(0.25,-0.25)
 (0.375,-0.375) rectangle ++(-0.25,-0.25);
}

\begin{document}
\begin{tikzpicture}
\draw [robot={home, turn left, right, left, left, left, left, 
  forward, left, forward, left, right, stop}];

\end{tikzpicture} 
\end{document}

在此处输入图片描述

相关内容