我正在使用同事创建的 tikz 包来绘制框图。他使用 pgf 声明了块的基本形状。但它并没有完全按照预期工作,我正在尝试修复它。
虽然我理解了大部分代码,但我还是搞不懂最后一点。正如您在这张图片中看到的那样:
只有中间的形状(对应于x = 0
tikz 坐标系)是正确的,其他的则不正确。
我把问题归结为:
\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@xa
PGF\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}