如何使 \pgfdeclareshape 独立于初始坐标?

如何使 \pgfdeclareshape 独立于初始坐标?

我正在使用同事创建的 tikz 包来绘制框图。他使用 pgf 声明了块的基本形状。但它并没有完全按照预期工作,我正在尝试修复它。

虽然我理解了大部分代码,但我还是搞不懂最后一点。正如您在这张图片中看到的那样:

在此处输入图片描述

只有中间的形状(对应于x = 0tikz 坐标系)是正确的,其他的则不正确。

我把问题归结为:

\pgfpathquadraticcurveto{\pgfpoint{\pgf@xa}{\pgf@yb}}{\pgfpoint{\pgf@xb}{\pgf@yb}}

不知何故,在 y 方向上应用的坐标是错误的,这我不明白,因为绘制框架时使用相同的坐标并且可以工作。您知道这是什么原因造成的吗?如何解决?

完整 MWE

\documentclass{article}

\usepackage{tikz}                  % tikz base packages
\usetikzlibrary{
    chains,
    arrows,
    shapes.symbols,
    shapes.multipart,
    positioning
}  

\usepgfmodule{plot}

\makeatletter
% shape for PT1-blocks
\pgfdeclareshape{pt1}{
    % new shape is based on rectangle
    % inherit the two saved anchors \southwest and \northeast
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    % inherit frame
    \inheritbackgroundpath[from=rectangle]
    % inherit user visible anchors
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    % define additional drawing commands
    \foregroundpath{
        % coordinates on frame
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
        % coordinates of plot coordinate system
        \advance\pgf@xa by+3pt 
        \advance\pgf@ya by+3pt
        \advance\pgf@xb by-3pt 
        \advance\pgf@yb by-3pt
        % draw plot coordinates system
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        % draw curve
        \advance\pgf@yb by-2pt
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathquadraticcurveto{\pgfpoint{\pgf@xa}{\pgf@yb}}{\pgfpoint{\pgf@xb}{\pgf@yb}}
    }
}
\makeatother


% Quellen und Senken
\tikzstyle{Source} = [text height=1.5ex,text depth=.25ex]
\tikzstyle{Sink} = [text height=1.5ex,text depth=.25ex]
\tikzstyle{PT1} = [draw, shape=pt1, line width = 0.6pt,  minimum width = 3em, minimum height=2em]
\tikzstyle{PT1flex} = [draw, shape=pt1, line width = 0.6pt,  minimum width = 3em, minimum height=2em]


\tikzstyle{BlockDiagramChain} = [ %
    >=stealth,
    start chain,
    node  distance=4mm,
    Source/.append  style={join=by ->,on chain},
    Sink/.append  style={join=by ->,on chain},
    PT1/.append   style={join=by ->,on chain},
]

\begin{document}
\begin{tikzpicture}

\begin{scope}[BlockDiagramChain]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\begin{scope}[BlockDiagramChain,shift={(0,-1cm)}]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\begin{scope}[BlockDiagramChain,shift={(0,1cm)}]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\node[PT1flex] at (5,1) {};
\node[PT1flex] at (5,0) {};
\node[PT1flex] at (5,-1) {};

\end{tikzpicture}

\end{document}

答案1

问题在于,诸如、等维度寄存器\pgf@x\pgf@xaPGF\pgf@yb内部用于点计算和路径构建等方面,因此无法保证保留赋予它们的值。

最简单的方法是使用以下命令将它们“保存”在宏中\edef

\documentclass[tikz,border=5]{standalone}

\usepackage{tikz}
\usetikzlibrary{
    chains,
    arrows,
    shapes.symbols,
    shapes.multipart,
    positioning
}  

\usepgfmodule{plot}

\makeatletter
% shape for PT1-blocks
\pgfdeclareshape{pt1}{
    % new shape is based on rectangle
    % inherit the two saved anchors \southwest and \northeast
    \inheritsavedanchors[from=rectangle]
    \inheritanchorborder[from=rectangle]
    % inherit frame
    \inheritbackgroundpath[from=rectangle]
    % inherit user visible anchors
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    % define additional drawing commands
    \foregroundpath{
        % coordinates on frame
        \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
        \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
        % coordinates of plot coordinate system
        \advance\pgf@xa by+3pt 
        \advance\pgf@ya by+3pt
        \advance\pgf@xb by-3pt 
        \advance\pgf@yb by-3pt
        \edef\xa{\the\pgf@xa}%
        \edef\xb{\the\pgf@xb}%
        \edef\ya{\the\pgf@ya}%
        \edef\yb{\the\pgf@yb}%
        % draw plot coordinates system
        \pgfpathmoveto{\pgfpoint{\xa}{\yb}}%
        \pgfpathlineto{\pgfpoint{\xa}{\ya}}%
        \pgfpathlineto{\pgfpoint{\xb}{\ya}}%
        % draw curve
        \pgf@yb=\yb\relax
        \advance\pgf@yb by-2pt%
        \edef\yb{\the\pgf@yb}%
        \pgfpathmoveto{\pgfpoint{\xa}{\ya}}%
        \pgfpathquadraticcurveto{\pgfpoint{\xa}{\yb}}{\pgfpoint{\xb}{\yb}}%
    }
}
\makeatother


% Quellen und Senken
\tikzstyle{Source} = [text height=1.5ex,text depth=.25ex]
\tikzstyle{Sink} = [text height=1.5ex,text depth=.25ex]
\tikzstyle{PT1} = [draw, shape=pt1, line width = 0.6pt,  minimum width = 3em, minimum height=2em]
\tikzstyle{PT1flex} = [draw, shape=pt1, line width = 0.6pt,  minimum width = 3em, minimum height=2em]


\tikzstyle{BlockDiagramChain} = [ %
    >=stealth,
    start chain,
    node  distance=4mm,
    Source/.append  style={join=by ->,on chain},
    Sink/.append  style={join=by ->,on chain},
    PT1/.append   style={join=by ->,on chain},
]

\begin{document}
\begin{tikzpicture}

\begin{scope}[BlockDiagramChain]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\begin{scope}[BlockDiagramChain,shift={(0,-1cm)}]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\begin{scope}[BlockDiagramChain,shift={(0,1cm)}]
    \node[Source] (w)   {$\omega$};
    \node[PT1]    (pt)  {};
    \node[Sink]   (x)   {$x$};
\end{scope}

\node[PT1flex] at (5,1) {};
\node[PT1flex] at (5,0) {};
\node[PT1flex] at (5,-1) {};

\end{tikzpicture}

\end{document} 

在此处输入图片描述

相关内容