2

I'm using a tikz package created by a colleague for drawing block diagrams. He declared basic shapes for the blocks using pgf. But it does not entirely work as intended and I'm trying to fix it.

Though I understand most of the code, I can't get a last thing right. As you can see in this image:

enter image description here

just the shapes in the middle, which correspond to x = 0 in the tikz coordinate system, are right, the others not.

I boiled the problem down to the line:

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

Somehow the applied coordinate in y-direction is wrong, which I don't understand, because for drawing the frame the same coordinates are used and it works. Do you have an idea, what could be the reason and how to fix it?

Full 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 Answer 1

4

The problem is that dimension registers like \pgf@x, \pgf@xa, \pgf@yb and so on, are used internally by PGF in things like point calculations and path construction and so cannot be guaranteed to retain the values that are given to them.

The easiest thing to do is to "save" them in macros using \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} 

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .