在 \pgfdeclareshape 命令中使用已保存的维度

在 \pgfdeclareshape 命令中使用已保存的维度

\saveddimen我对命令内部的用法有疑问\pgfdeclareshape 。我的代码如下:

\documentclass{article}
\usepackage{tikz}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
\makeatletter
\pgfdeclareshape{myshape}{
   \savedanchor{\centerpoint}{\pgf@x=0pt\pgf@y=0pt}
   \saveddimen{\mydima}{%
      \pgf@x=20pt
   }
   \saveddimen{\mydimb}{%
      \pgf@x=20pt  %% =\mydima
      \pgf@x=-\pgf@x
   }
   %   
   \anchor{center}{\centerpoint}
   \backgroundpath{%
        \pgf@xa=\mydima \pgf@ya=\mydima
        \pgf@xb=\mydimb \pgf@yb=\mydimb
        \pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}
        \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
   }     
}
\makeatother
\begin{document}
\begin{tikzpicture}
   \draw[help lines] (0,0) grid (4,4);
   \node[myshape,draw] at (2,2) {test};
\end{tikzpicture}
\end{document}

这将生成一个节点,顶部和底部有水平线。在我的实际示例中,我希望有一个维度,\dimenb 它是 的函数。如果我在 命令设置中\dimena取消注释 , 我会收到一条错误消息。%%\saveddimen{\dimenb}\pgf@x=\dimmena

问题:在另一个已保存的维度的定义中使用一个已保存的维度是否合法?如果合法,该如何做?

答案1

在评论中,percusse建议写作:

\saveddimen{\mydima}{\pgf@x=20pt}
\saveddimen{\mydimb}{\pgf@x=-\pgf@x}

要了解其工作原理,我们需要追溯定义。其中\pgfdeclareshape实际上\saveddimen\pgf@sh@saveddimen其定义:

\def\pgf@sh@saveddimen#1#2{%
  \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@\shape@name\endcsname{\pgf@sh@resaveddimen{#1}{#2}}}

因此,当声明形状时,我们会看到\pgf@sh@s@<shapename>获得命令。据推测,当使用形状设置所有尺寸等时,会运行\pgf@sh@resaveddimen{#1}{#2}该宏。因此,要找出运行时会发生什么,我们需要查看。这是:\pgf@sh@s@<shapename>\pgf@sh@resaveddimen

\def\pgf@sh@resaveddimen#1#2{%
  {#2\global\pgf@x=\pgf@x}%
  \edef\pgf@sh@marshal{%
    \noexpand\pgfutil@g@addto@macro\noexpand\pgf@sh@savedpoints{%
      \noexpand\def\noexpand#1{\the\pgf@x}%
    }}%
  \pgf@sh@marshal%
}

因此#2(这是执行代码)运行,然后\pgf@x设置为全球的版本本身(这很重要)。现在这个没有保存为给定的名称,但代码\def\<given name>{<the actual value of \pgf@x>}保存为\pgf@sh@savedpoints。请注意,这是实际的值,而不是宏\pgf@x

因此,我们分为三个阶段:宣言当模板设置完成后,定义定义形状的位置,使用各个部件的使用情况(其中部分部件位于定义阶段,因此这可能会令人困惑)。

让我们通过上面的代码及其变体来追踪这一点。

  1. 宣言。因此,我们在这里运行\saveddimen执行代码附加的命令。最后,它\pgf@sh@s@myshape具有(除了它具有的其他内容之外):

    \pgf@sh@resaveddimen{\mydima}{\pgf@x=20pt}
    \pgf@sh@resaveddimen{\mydimb}{\pgf@x=-\pgf@x}
    
  2. 定义。现在\pgf@sh@s@myshape运行。这将执行上述两个命令(以及其他命令)。运行第一个命令后,运行状态如下\pgf@x全球设置为20pt并且其中\pgf@sh@savedpoints有。其中第一个是我们可以在 的定义中\def\mydima{20pt}使用 的原因。第二个是我们为什么不能使用 的原因。\pgf@x\mydimbmydima

    然后最后\pgf@sh@savedpoints包含\def\mydima{20pt}\def\mydimb{-20pt}

  3. 使用。这是\pgf@sh@savedpoints执行的位置,所有宏最终都已定义。所以一切都已设置好任务已完成。

总之,\mydima在设置的代码时不可用\mydimb,但只要它们一个接一个地声明,那么在\mydimb执行的定义代码时,的值就是设置的\pgf@x值。\mydima

相关内容