这是我想要做的:给定两个(水平)节点,计算它们之间的 x 距离,并生成一个宽度与节点之间的 x 距离相同的矩形节点,放置在它们下方。
我已经尝试了以下代码,重复使用在路径/计算中使用 \pgfmathparse - 为什么这个 let 表达式在 TikZ 中不起作用(计算中点)? - TeX - LaTeX - Stack Exchange:
\usetikzlibrary{shapes.arrows,chains,positioning,matrix,calc}
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let \p1 = (A1.west), \p2 = (A2.east)
in \pgfextra{
\pgfmathparse{\x2 - \x1}
}
node[draw,right,below=of A1,text width=\pgfmathresult pt]{test};
\end{tikzpicture}
结果如下图所示:
显然 - 该框的宽度不如 A1 和 A2 节点之间的距离(并且其右边缘均未与 A1.west 对齐)。
然后我想尝试一些类似于给出的代码回复:tikz:以编程方式获取节点的宽度,它也使用\pgfextra
,所以我尝试了类似如下的方法:
\usetikzlibrary{shapes.arrows,chains,positioning,matrix,calc}
\newdimen{\mydim}
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let \p1 = (A1.west), \p2 = (A2.east)
in \pgfextra{
\pgf@x=\n1
\pgf@y=1cm
\divide\pgf@x by \pgf@y
\setlength{\mydim}{\pgf@x}
}
node[draw,right,below=of A1,text width=\mydim pt]{test};
\end{tikzpicture}
...但是,对于该代码,LaTeX 在遇到时似乎会崩溃\pgf@x
,因为错误消息是:
! Undefined control sequence.
<argument> \pgf
@x=\n 1 \pgf @y=1cm \divide \pgf @x by \pgf @y \setlength {...
l.40 }
! ==> Fatal error occurred, no output PDF file produced!
我发现的唯一与此相关的错误是pgfdeclareshape 示例不可编译 - pgf-users,其中建议为:
如果将 \makeatletter 放在 \pgfdeclareshape{...} 之前并将 \makeatother 放在之后,是否可以编译?(手册中的示例中缺少它,但我认为它是必要的)。
... 但是,我不知道它在这里如何应用 - 因为这里使用所有这些 pgf 的目的只是计算(而不是实际的绘图/渲染)。
好吧,提前感谢任何指点,
干杯!
编辑:好吧,通过上述方法的组合,我开始取得一些进展:
\usetikzlibrary{shapes.arrows,chains,positioning,matrix,calc}
\newdimen{\mydim}
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let \p1 = (A1.west), \p2 = (A2.east)
in \pgfextra{%
\pgfmathparse{\x2 - \x1}
\setlength{\mydim}{\pgfmathresult pt}
}
node[draw,right,below=of A1.west,anchor=west,text width=\mydim]{test};
\end{tikzpicture}
...但还是不太好。通过使用anchor=west
,现在可以正确对齐;通过删除\pgf@x
,并使用\pgfmathresult
设置\mydim
长度 - 宽度看起来会好一些,但比预期的要长,见图:
所以现在剩下的问题是:
- 我如何获得框的正确宽度——以便它的左边缘与 A2 的左边缘对齐?
- 为什么会发生这种‘碰撞
\pgf@x
’\pgfextra
?
再次感谢,
干杯!
答案1
我猜想您的第一个示例没有给出正确的长度的原因是,\pgfmathresult
在应用于选项之前,某个地方覆盖了 (您还忘记减去inner sep
,这就是您编辑的长度不正确的原因)。但是,节点被正确地放置在 (A1) 下方,因为默认节点对齐是居中。
第一步:修复\pgfmathresult
。\pgfmathparse
这里其实不需要 ,我们可以简单地执行以下操作(inner sep
文本和边框之间的默认值为 0.3333em,因此我们需要减去 的两倍text width
):
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let \p1 = (A1.west), \p2 = (A2.east) in
node[draw,right,below=of A1,text width={\x2-\x1-0.6666em}]{test};
\end{tikzpicture}
第二步:修复对齐。该right
选项不执行任何操作,因此我们可以直接删除它。默认情况下,节点锚定在其中心。实际上,对于below=of ..
,它们锚定在北(中心)。所以我们必须设置anchor=north west
让节点位于右侧。但它位于 A1.center 的右侧(具体来说,node distance
在 A1.south 下方)。所以我们需要指定below=of A1.south west
。不幸的是,这不太管用,因为 A1 以圆圈为界(因此south west
在圆圈上,而不是我们希望的那么西和南)。A1.west 是第一个近似值:
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let \p1 = (A1.west), \p2 = (A2.east) in
node[draw,below={of A1.west},anchor=north west,text width={\x2-\x1-0.6666em}]{test};
\end{tikzpicture}
这还不够完美,因为第三个节点现在有点太高了。形状circle
没有提供正确的锚点,所以我们必须计算它的位置(这很容易:A1.west 给出正确的 x 坐标,A1.south 给出正确的 y 坐标)。另外,让我们将align=center
文本添加到节点的中心:
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\draw let
\p1 = (A1.west),
\p2 = (A2.east),
\p3 = (A1.south)
in node [
draw,
below={of (\x1,\y3)},
anchor=north west,
text width={\x2-\x1-0.6666em},
align=center
] {test};
\end{tikzpicture}
要使第二个示例编译,您需要在适当的位置添加\makeatletter
和\makeatother
。默认情况下,@ 属于“其他”类,不能用于命令名称。但是,它通常用于用户不应访问的内部命令。\makeatletter
使 @ 成为“字母”,以便它可以用于命令名称。另请参阅为什么 LaTeX 内部命令中带有 @?。但是代码似乎还有其他问题,添加\makeatletter
只会改变错误。我还不太熟悉 TeX 和 LaTeX 处理尺寸和长度的方式,无法为您提供如何更正该代码的建议。
答案2
感谢@Caramdir,这里也是一个使用 的版本\pgf@x
;虽然\makeatletter
/\makeatother
是摆脱 所必需的! Undefined control sequence
,但 OP 代码还需要使用“计数器”而不是“维度”,以便完全发生一些宽度缩放。
下面的代码应该构建并生成一个图像 - 但这次它的宽度将稍微更短比 A1 和 A2 之间的“总”距离更大:
\usetikzlibrary{shapes.arrows,chains,positioning,matrix,calc}
\newdimen{\mydim}
\newcounter{counterOne}
\begin{tikzpicture}[font=\tt]
\node (A1) [shape=circle,draw] {A1};
\node (A2) [shape=circle,draw,right=of A1] {A2};
% draw a rectangular node
\makeatletter
\draw let \p1 = (A1.west), \p2 = (A2.east)
in let \n{width} = {\x2 - \x1}
in \pgfextra{
% \pgf@x=\n1 % ! Missing number, treated as zero. \tikz@cc@n@1
% manual: "the \p, \x, and \y macros refer to the same logical point, while the \n macro has “its own namespace.”"
\pgf@x=\n{width}
\pgf@y=1cm
\divide\pgf@x by \pgf@y
\setcounter{counterOne}{\pgf@x} % NOWORK: \setlength{\mydim}{\pgf@x}
}
node[draw,right,below=of A1.west,anchor=west,text width=\thecounterOne cm]{test};
\makeatother
\end{tikzpicture}
... 结果图像:
好吧,无论如何,我很高兴这个问题得到了解决:)
干杯!