请考虑以下代码:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\def\coord(#1){coordinate(#1)}
\begin{document}
\begin{tikzpicture}
\node[draw](A) at (0,0) {A};
\node[draw](B) at (3,3) {B};
% this works
\draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) coordinate(C);
% this fails
% \draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) \coord(C);
\node [right] at (C) {\pgfversion};
\end{tikzpicture}
\end{document}
注释行失败 --- 似乎let
路径中的\coord
宏未展开。这是预期的吗?
PD. 我使用这个是因为我使用了以下代码:
\def\normcoord(#1){coordinate(#1)}
\def\showcoord(#1){node[circle, red, draw, inner sep=1pt,pin={[red, overlay, inner sep=0.5pt, font=\tiny, pin distance=0.1cm, pin edge={red, overlay,}]45:#1}](#1){}}
\let\coord=\showcoord
在绘制图纸时在“标记”和“未标记”节点之间切换。
答案1
你只是运气不好,因为你选择调用宏\coord
,而这个宏已经有意义了。它让我们回忆起坐标是如何定义的。所以如果你使用 而不是 ,\mycoord
你\coord
的代码就会按预期工作。我还添加了一些内容来展示它的\coord
作用。你可以把它看作\n
、\p
和的近亲\x
,\y
它们在语法中也有特殊含义let ... in
。虽然\p
允许你“设置”点,\x
并\y
产生它们的屏幕坐标和\coord
定义坐标的字符串。更详细地说,可用的宏是(取自tikzlibrarycalc.code.tex
)
\let\p=\tikz@cc@dop%
\let\x=\tikz@cc@dox%
\let\y=\tikz@cc@doy%
\let\n=\tikz@cc@don%
\let\rawx=\tikz@cc@dotempx%
\let\rawy=\tikz@cc@dotempy%
\let\rawz=\tikz@cc@dotempz%
\let\coord=\tikz@cc@docoord%
截至目前,它还包含\rawx
和,\rawy
它们\rawz
是用于定义坐标的坐标的组成部分。
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\def\mycoord(#1){coordinate(#1)}
\begin{document}
\begin{tikzpicture}
\node[draw](A) at (0,0) {A};
\node[draw](B) at (3,3) {B};
% this works
\draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) coordinate(C);
% this also works
\draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) \mycoord(C);
\node [right] at (C) {\pgfversion};
\path let \p{A}=(A),\p{B}=(B),\p{C}=(C) in
(0,3) node[anchor=south west,align=left] {Let us show how\\
we were defined:\\$A=\coord{A}$\\
$B=\coord{B}$\\ $C=\coord{C}$\\};
\end{tikzpicture}
\end{document}
我还要提一下\coord
,或相关工具是 3D 计算中不可或缺的工具,因为屏幕坐标始终只是投影,也就是说,除其他外,您会丢失第三个组件。这将在多大程度上以有意义的方式使用取决于 Ti 的未来发展钾Z. 主要的问题是,到目前为止,还没有记录坐标是在哪个帧中定义的。
由于 Henri Menke 要求我这么做,我提到他决定删除\coord
、\rawx
和。在我看来,此举是不必要的\rawy
,\rawz
而且破坏了工作代码。但这个问题将来可能不会出现。
但是,这根本不是一个特殊情况。相反,例如我通常将循环变量称为\X
,\Y
等等,仅仅是因为 calc 语法使用并重新定义了\x
和\y
(和\x
也是默认的绘图参数)。也就是说,\x
和\y
也会在没有警告的情况下被覆盖,用户通常会通过不同地命名他们的宏来避免冲突。有时甚至非常基本的命令(例如\xi
)也会被覆盖,但只要知道这种情况会发生,就总能找到解决方法。宏名的数量是有限的。每个\foreach
循环都会在没有警告的情况下覆盖其循环变量。
答案2
在 PGF 3.1.4 中,我犯了一个错误,引入了新的用户级命令而没有记录它们。这些命令在操作内部定义let
,并无条件地覆盖可能的全局定义。这些本地宏是
\rawx
\rawy
\rawz
\coord
它原本是一个实验,但现在已经证明在许多情况下都失败了。因此,在即将发布的 PGF 3.1.5 版本中,我将再次删除这些命令。let
加载库后,您可以通过覆盖序言中的定义来恢复操作的正确行为calc
。
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\def\tikz@let@command et{%
\let\p=\tikz@cc@dop%
\let\x=\tikz@cc@dox%
\let\y=\tikz@cc@doy%
\let\n=\tikz@cc@don%
\pgfutil@ifnextchar i{\tikz@cc@stop@let}{\tikz@cc@handle@line}%
}%
\makeatother
\def\coord(#1){coordinate(#1)}
\begin{document}
\begin{tikzpicture}
\node[draw](A) at (0,0) {A};
\node[draw](B) at (3,3) {B};
% this works
\draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) coordinate(C);
% this fails
\draw let \p1=(A), \p2=(B) in (A) -- (\x1, \y2) \coord(C);
\node [right] at (C) {\pgfversion};
\end{tikzpicture}
\end{document}