如何沿图形绘制路径

如何沿图形绘制路径

我想画一个图形来表示在固定图上遍历的路径,如给定(黑色)图上的以下(红色)循环:

在此处输入图片描述

在这种情况下,我使用以下糟糕的代码生成了它:

\documentclass{amsart}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
    [vertex/.style={circle, inner sep=0pt,minimum size=4mm}]    
    \node (A) [vertex] at (90:1) {};
    \node (B) [vertex] at (330:1) {};
    \node (C) [vertex] at (210:1) {};
    \draw (A) circle (1mm);
    \draw (B) circle (1mm);
    \draw (C) circle (1mm);
    \draw (A) -- (B) -- (C) -- (A);
    \draw[red,->] 
        (A.30) 
        -- (B.30) arc (30:-90:2mm)
        -- (C.270) arc (270:150:2mm)
        -- (A.150);
\end{tikzpicture}
\end{document}

我想以一种不太糟糕的方式来做到这一点,以便(a)当我更改节点大小或位置等基本参数时它不会中断,并且(b)当节点位置不同或图形更复杂时,我不必计算奇怪的角度等。

一般来说,路径可能很长而且很复杂,而且它们可能会回溯或重复使用边,例如 ABCBA 在上面图表中描述了一条路径(一旦你标记了节点)。我希望能够绘制这样的东西。

我真正希望的是拥有代码和/或宏,让我能够相对轻松地从一系列图形节点生成红色路径。我愿意修改和定制各个路径,并不期望整个过程自动化。在生成的图像中,整个路径应该是可见的。

在此先感谢您的任何建议。

答案1

让我们尝试逐一回答这个问题。

  1. 有没有办法获得模块化的图表,即您可以更改许多参数并且图表不会破坏?

是的,代码如下:

    [vertex/.style={circle, inner sep=0pt,minimum size=4mm}]    
        \node (A) [vertex] at (90:1) {};
        \node (B) [vertex] at (330:1) {};
        \node (C) [vertex] at (210:1) {};
        
        \draw (A) circle (1mm);
        \draw (B) circle (1mm);
        \draw (C) circle (1mm);
        \draw (A) -- (B) -- (C) -- (A);
        
        \coordinate (a0) at ($(A) + (180:3mm) $);   
        \coordinate (d)  at ($(A) + (0:3mm) $);
        \coordinate (e)  at ($(B) + (-30:3mm) $);
        \coordinate (f)  at ($(C) + (-90-60:3mm) $);    
    
        \draw[rounded corners](d) -- (e) --(f) -- (a0);

我做的第一件事就是coordinate根据已经存在的 A、B、C 定义 4 个点node

怎么做?使用calctikzlibrary。语法是($(A) + (180:3mm) $),即抓取 A 的位置,然后向其添加此值。此处的值是极坐标系中定义的位置(angle:radius)。就像您已经做过的那样。

然后,绘制一条经过 4 个坐标但带有圆角的路径。

模块化已实现。

下一步:概括,这更难。

第一个问题:我可以将红色和黑色之间的距离设为参数化吗?

是的,我可以\def\radius{3}在里面添加行tikzpicture并替换其中的 3 3 mm

在此处输入图片描述

让我们把这一切自动化


    \begin{tikzpicture}[vertex/.style={draw, circle, inner sep=0pt, minimum size=2mm}]    
        \def\nodescount{8}
        \def\radius{5}
        
        \foreach \X [remember=\X as \lastx (initially 0)] in {0,1,...,\nodescount}{
            \node (A\X) [vertex] at (\X*360/\nodescount:1) {};
            \draw (A\lastx)--(A\X);
            \coordinate (B\X) at ($(A\X) + (\X*360/\nodescount:\radius mm) $);  
        }
        \draw [red,rounded corners=3mm] (B1)-- (B2)--(B3) --(B4) --(B5)--(B6) --(B7);
    \end{tikzpicture}

在此处输入图片描述

使用foreach循环利用\def\nodescount{8}将 360° 分成 8 个部分来创建 8 个节点。通过 将每个节点与前一个节点链接起来[remember=\X as \lastx (initially 0)]。定义红色路径所需的坐标。

由于存在一些不一致,我无法自动绘制红色部分。我需要改进这一点。

最后,请记住,有更好的方法和工具可以做到这一点。这是一个纯粹的可能解决方案tikz。我很享受制作它的过程。

答案2

以下适用于大于 2 的任意节点数。节点有规律地放置。您可以使用一些选项来根据自己的喜好进行调整。

它不使用rounded cornersas,因为 as 会导致节点周围路径的起点和终点位置不完美。相反,它使用arcs。

\documentclass[border=3.14,tikz]{standalone}

\usetikzlibrary{calc}

\makeatletter
\newif\ifpwp@closed
\newif\ifpwp@straights
\pgfqkeys{/pwp}
  {
    .is family
    ,radius/.initial = 1
    ,start angle/.initial = 90
    ,vertex/.style = {draw, circle}
    ,vertex/radius/.initial = 1mm
    ,path/.style = {->, red}
    ,path/radius/.initial = 2mm
    ,path/closed/.is if = pwp@closed
    ,prefix/.code = {\def\pwp@coord##1{#1-\@Alph{##1}}}
    ,draw straights/.is if = pwp@straights
    ,straights/.style = {}
  }
\newcommand*\pwp@coord[1]{\@Alph{#1}}
\newcommand*\pwp@val[1]{\pgfkeysvalueof{/pwp/#1}}
\newcommand\polygonwithpath[2][]
  {%
    \begingroup
      \pgfqkeys{/pwp}{#1}%
      \pgfmathsetmacro\pwp@angle{360/#2}%
      \foreach\i in {1,...,#2}
        {
          \node
            [/pwp/vertex,minimum size=2*\pwp@val{vertex/radius},inner sep=0pt]
            (\pwp@coord{\i})
            at ({\pwp@val{start angle} - \pwp@angle * (\i-1)}:\pwp@val{radius})
            {}
            ;
        }
      \ifpwp@straights
        \draw[/pwp/straights] (\pwp@coord{#2}) -- (\pwp@coord{1})
          \foreach\i in{2,...,#2}{(\pwp@coord{\numexpr\i-1})--(\pwp@coord\i)}
          ;
      \fi
      \xdef\pwp@path
        {%
          \ifpwp@closed
            ($(\pwp@coord{1})+(\pwp@val{start angle}:\pwp@val{path/radius})$)
            arc[start angle=\pwp@val{start angle}, end angle=\pwp@val{start angle}-\pwp@angle/2]
          \else
            ($(\pwp@coord{1})+(\pwp@val{start angle}-\pwp@angle/2:\pwp@val{path/radius})$)
          \fi
        }%
      \foreach\i in {2,...,#2}
        {%
          \xdef\pwp@path
            {%
              \pwp@path
              --
              ($(\pwp@coord{\i})+({\pwp@val{start angle}-(\i-1.5)*\pwp@angle}:\pwp@val{path/radius})$)
              arc[start angle=\pwp@val{start angle}-(\i-1.5)*\pwp@angle, end
              angle=\pwp@val{start angle}-(\i-0.5)*\pwp@angle]
            }%
        }%
      \xdef\pwp@path
        {%
          \noexpand\draw
            [%
              /pwp/path,
              radius = \pwp@val{path/radius},
            ]%
          \pwp@path
          --($(\pwp@coord{1})+({\pwp@val{start angle}-(#2-0.5)*\pwp@angle}:\pwp@val{path/radius})$)
          \ifpwp@closed
          arc[start angle=\pwp@val{start angle}-(#2-0.5)*\pwp@angle, end angle=-270]
          \fi
          ;%
        }%
      \pwp@path
    \endgroup
  }
\makeatother

\begin{document}
\begin{tikzpicture}
  \polygonwithpath{2}
  \begin{scope}[xshift=25mm]
    \polygonwithpath[vertex/radius=2mm]{3}
    \begin{scope}[xshift=25mm]
      \polygonwithpath[path/radius=3mm,path/closed]{3}
    \end{scope}
  \end{scope}
  \begin{scope}[yshift=-25mm]
    \polygonwithpath{4}
    \begin{scope}[xshift=25mm]
      \polygonwithpath[path/closed = true]{4}
      \begin{scope}[xshift=25mm]
        \polygonwithpath[draw straights]{4}
      \end{scope}
    \end{scope}
    \begin{scope}[yshift=-20mm]
      \polygonwithpath[radius=5mm, draw straights, straights/.style=green]{5}
      \begin{scope}[xshift=25mm]
        \polygonwithpath[radius=5mm,vertex/.style={draw}]{5}
        \begin{scope}[xshift=25mm]
          \polygonwithpath[radius=5mm,path/.style={blue},start angle=0]{5}
        \end{scope}
      \end{scope}
    \end{scope}
  \end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

使用nfold图书馆有助于创建一条平行线。将其与spath3库结合可以帮助我们将其中两条线切在一起。

不幸的是,使用这些rounded corners选项会在不同的点上给它们带来麻烦,但总有办法。

对于简单的凸包,只需nfold要将它与圆线连接一起使用即可产生良好的效果。

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta, graphs.standard, nfold}
\usetikzlibrary{spath3}
\makeatletter
\tikzset{
  offset round/.code=
    \tikz@addmode{%
      \pgfsetroundjoin         \pgfgetpath   \tikz@temp
      \pgfsetpath\pgfutil@empty\pgfoffsetpath\tikz@temp{#1}}}
\makeatother
\tikzset{
  vertex/.style={circle, inner sep=+0pt, minimum size=+2mm, draw},
  graphs/every graph/.append style={nodes=vertex, clockwise, typeset=}}
\begin{document}
\begin{tikzpicture}
\graph[n=3]{subgraph C_n};
\draw[red, ->] plot[samples at={1, 2, 3, 1}] (\x) [offset round=2mm];
\end{tikzpicture}

\begin{tikzpicture}
\graph[n=3]{subgraph C_n};
\path plot[samples at={1, 2, 3, 1}] (\x) [offset round=+ 2mm, spath/save=p];
\path plot[samples at={1, 3, 2, 1}] (\x) [offset round=+-4mm, spath/save=q];
\draw[->, red, spath/use=p] -- (spath cs:q 0) [spath/use={q, weld}];
\end{tikzpicture}

\begin{tikzpicture}
\graph[n=6]{subgraph I_n, 1 -- 2 -- 3 -- 1 -- 6 -- 4};
\draw[red, ->] plot[samples at={1, 2, 3, 1, 6, 4}] (\x) [offset round=2mm];
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述 在此处输入图片描述 在此处输入图片描述

相关内容