为什么我的代码会失败?如果没有,foreach
我的代码可以正常工作。
通常,我何时以及如何在命令foreach
中使用path
?这是一种不好的做法吗?如果是,应该有什么替代方案?
\documentclass{standalone}
\usepackage{tikz}
\tikzset{ myVrtxStyle/.style = {
circle, minimum size= 4mm, fill = blue
}
}
\begin{document}
\begin{tikzpicture}
\node[myVrtxStyle = black] (u) {};
\newcommand{\midSepAngle}{20};
\newcommand{\remNi}{6}
\draw (u.{135 + \midSepAngle}) to [out = {135 + \midSepAngle}, in = {135 - \midSepAngle}, looseness = 100]
\foreach \i in {1,..., \remNi}{
node[ myVrtxStyle, pos = {\i / \remNi} ] (C1\i) {}
}
(u.{135 - \midSepAngle});
\end{tikzpicture}
\end{document}
我看到过一些相关的帖子,例如这个但我还是不完全明白到底发生了什么。
答案1
在路径中,您应使用
foreach
。由于历史原因,您也可以使用\foreach
来代替foreach
(参见第节“14.14 Foreach 操作”,第 167 页,pgfmanual v3.1.9a)。有两种方法可以指定直线或曲线上的节点:要么明确使用 pos 选项,要么隐式地将节点放置在路径操作“内部”(参见章节“17.8 在线或曲线上明确放置节点”,第 245 页和“17.9 在线或曲线上隐式放置节点”,第 249 页,pgfmanual v3.1.9a)。
隐式示例:
\draw (0,0) -- node[pos=.7]{a} (1,1);
只有直线到 (--
) 和曲线到 (..
) 操作支持隐式方式。关键字foreach
不受支持隐式方式。明确示例:
\draw (0,0) -- (1,1) node[pos=.7] {a};
只有线到(--
)、水平和垂直线到(-|
和|-
)、曲线到(..
)和圆弧(arc
)操作支持明确的方式。对于所有其他路径构造操作(就像
to
你的情况一样),目前位置放置不起作用(参见第 246 页,pgfmanual,v3.1.9a)。
因此,您必须使用明确的方式,并将您的to
操作替换为曲线到(..
)操作,如Andrew Stacey 的解决方案。
答案2
我不知道为什么它不能通过to
命令工作 - 我必须调查这一点 - 但是使用明确的贝塞尔曲线它就可以工作。
- 目标坐标必须位于 foreach 之前
- foreach 是一个关键词,而不是命令
- 我修改了你的节点样式,以将参数作为填充颜色,默认为蓝色
\documentclass {standalone}
\usepackage{tikz}
\tikzset{
myVrtxStyle/.style = { circle, minimum size= 4mm, fill = #1 },
myVrtxStyle/.default = blue
}
\begin{document}
\begin{tikzpicture}
\node[myVrtxStyle = black]
(u) {};
\newcommand{\midSepAngle}{20};
\newcommand{\remNi}{6}
\draw (u.{135 + \midSepAngle})
.. controls +(135+\midSepAngle:20) and +(135-\midSepAngle: 20) ..
(u.{135-\midSepAngle})
foreach \i in {1,..., \remNi}{
node[ myVrtxStyle, pos = \i/\remNi ] (C1\i) {}
}
;
\end{tikzpicture}
\end{document}
答案3
以下语法实际上有效,并且与您的原始代码几乎相同。
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
myVrtxStyle/.style={
circle,minimum size=4mm,fill=blue,fill=#1
}
}
\begin{document}
\begin{tikzpicture}
\node[myVrtxStyle=black](u){};
\newcommand{\midSepAngle}{20};
\newcommand{\remNi}{6}
\draw
(u.{135 +\midSepAngle})
to
[out={135+\midSepAngle},in={135-\midSepAngle},looseness=100]
node foreach\i in{1,...,\remNi}[pos=\i/\remNi,myVrtxStyle](C1\i){}
(u.{135-\midSepAngle})
;
\draw foreach\i in{1,...,\remNi}{
(C1\i)--+(-90-\i*40:1)node{\i}
};
\end{tikzpicture}
\end{document}
评论
我在这个问题下的评论是错误的,因为你实际上可以在(A) --
和之间使用 for 循环(B)
。但是,这个 for 循环不能是任意的 for 循环;它必须是专用于节点的 for 循环。所以这
(A) -- foreach\i in{1,2,3}{node{\i}} (B)
很糟糕,但这
(A) -- node foreach\i in{1,2,3}{\i} (B)
是好事。
这是因为当 Ti钾Z 的解析器已读取(A) --
并正在等待(B)
,它还会留意是否有node...{...}
。一旦发现n
,它将收集节点规范并将其存储在 中\tikz@collected@onpath
,后者将其传输到\tikz@tonodes
和\tikztonodes
。 Ti 之后钾Z 计算了你的贝塞尔表示to path
,它将节点规范放置在路径的末尾,如下所示(tikzlibrarytopaths.code.tex#L134-L140)
\def\tikz@to@curve@path{%
[every curve to]% ⬇️ This is the main computation ⬇️
\pgfextra{\iftikz@to@relative\tikz@to@compute@relative\else\tikz@to@compute\fi}
\tikz@computed@path% ⬅️ this is the Bézier curve (A)..controls(B)and(C)..(D)
\pgfextra{\tikz@updatenexttrue\tikz@updatecurrenttrue}%
\tikztonodes% ⬅️ your nodes here (notice the plural)
}
因此,您需要做的就是确保\tikztonodes
确实捕获了您的节点规范。如果自然语法失败,您可以随时强迫。 例如
to[bend left,/utils/exec=\def\tikztonodes{...}]
。