我想画一个图形来表示在固定图上遍历的路径,如给定(黑色)图上的以下(红色)循环:
在这种情况下,我使用以下糟糕的代码生成了它:
\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
让我们尝试逐一回答这个问题。
- 有没有办法获得模块化的图表,即您可以更改许多参数并且图表不会破坏?
是的,代码如下:
[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
。
怎么做?使用calc
tikzlibrary。语法是($(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 corners
as,因为 as 会导致节点周围路径的起点和终点位置不完美。相反,它使用arc
s。
\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}