TikZ“let”命令中“\coord”宏的扩展

TikZ“let”命令中“\coord”宏的扩展

请考虑以下代码:

\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}

相关内容