我用这段代码定义了两个装饰:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\thispagestyle{empty}
\usetikzlibrary{decorations}
\tikzset{%
pneumatic signal/.style={%
decoration={%
pneumatic signal decoration,
segment length=6pt,
amplitude=3pt
},
very thin,
decorate
}
}
\tikzset{%
system signal/.style={%
decoration={%
system signal decoration,
segment length=10pt,
amplitude=5pt
},
very thin,
decorate
}
}
\makeatletter
\pgfdeclaredecoration{pneumatic signal decoration}{line}
{%
\state{line}[width=+\pgfdecorationsegmentlength,next state=tick,%
switch if input segment less than=.5\pgfdecorationsegmentlength %
to segment 1,%
switch if input segment less than=+\pgfdecorationsegmentlength %
to segment 2]{%
\pgfpathlineto{\pgf@x=+\pgfdecorationsegmentlength \pgf@y=0pt}
}
\state{tick}[width=1.6\pgfdecorationsegmentamplitude,next state=line,
switch if input segment less than=1.2\pgfdecorationsegmentamplitude%
to segment 2]{%
\pgfpathlineto{\pgf@x=1.6\pgfdecorationsegmentamplitude \pgf@y=0pt}
\pgfpathmoveto{\pgf@x=0pt \pgf@y=-.5\pgfdecorationsegmentamplitude}
\pgfpathlineto{\pgf@x=+\pgfdecorationsegmentamplitude
\pgf@y=.5\pgfdecorationsegmentamplitude}
\pgfpathmoveto{\pgf@x=.6\pgfdecorationsegmentamplitude
\pgf@y=-.5\pgfdecorationsegmentamplitude}
\pgfpathlineto{\pgf@x=1.6\pgfdecorationsegmentamplitude
\pgf@y=.5\pgfdecorationsegmentamplitude}
\pgfpathmoveto{\pgf@x=1.6\pgfdecorationsegmentamplitude \pgf@y=0pt}
}
\state{segment 1}[next state=line,%
width=+\pgfdecoratedinputsegmentremainingdistance]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
}
\state{segment 2}[next state=segment 3,%
width=+\pgfdecoratedinputsegmentremainingdistance]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
}
\state{segment 3}[next state=tick,%
width=.2\pgfdecorationsegmentlength,
switch if input segment less than=.2\pgfdecorationsegmentlength %
to segment 2]{%
\pgfpathlineto{\pgf@x=.2\pgfdecorationsegmentlength \pgf@y=0pt}
}
\state{final}{%
\pgfpathlineto{\pgfpointdecoratedpathlast}
}
}
\pgfdeclaredecoration{system signal decoration}{line}
{%
\state{line}[width=+\pgfdecorationsegmentlength,next state=symbol,%
switch if input segment less than=.5\pgfdecorationsegmentlength %
to segment 1,%
switch if input segment less than=+\pgfdecorationsegmentlength %
to segment 2]{%
\pgfpathlineto{\pgf@x=+\pgfdecorationsegmentlength \pgf@y=0pt}
}
\state{symbol}[width=+\pgfdecorationsegmentamplitude,next state=line,
switch if input segment less than=+\pgfdecorationsegmentamplitude%
to segment 2]{%
\pgfpathcircle{\pgf@x=.5\pgfdecorationsegmentamplitude \pgf@y=0pt}
{.5\pgfdecorationsegmentamplitude}
\pgfpathcircle{\pgf@x=.5\pgfdecorationsegmentamplitude \pgf@y=0pt}
{.25\pgfdecorationsegmentamplitude}
\pgfpathmoveto{\pgf@x=+\pgfdecorationsegmentamplitude \pgf@y=0pt}
}
\state{segment 1}[next state=line,%
width=+\pgfdecoratedinputsegmentremainingdistance]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
}
\state{segment 2}[next state=segment 3,%
width=+\pgfdecoratedinputsegmentremainingdistance]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
}
\state{segment 3}[next state=symbol,%
width=.2\pgfdecorationsegmentlength,
switch if input segment less than=.2\pgfdecorationsegmentlength %
to segment 2]{%
\pgfpathlineto{\pgf@x=.2\pgfdecorationsegmentlength \pgf@y=0pt}
}
\state{final}{%
\pgfpathlineto{\pgfpointdecoratedpathlast}
}
}
\makeatother
\tikz\draw[->,pneumatic signal] (0,0) -- (2,0);
\tikz\draw[->,system signal] (0,0) -- (2,0);
\end{document}
我的问题是,我无法使用“系统信号”装饰绘制以箭头结尾的路径。虽然代码完全相同,但我不明白为什么“气动信号”装饰有效,而“系统信号”装饰无效。我错过了什么?
编辑:根据要求添加缺失的 MWE 代码(抱歉......)
编辑2:添加了有问题的装饰代码
答案1
问题在于使用\pgfpathcircle
,或者更具体地说,这个命令包含一个关闭路径的低级命令。我不得不四处寻找它,但手册(我的 2.10 版本中的第 15.3.4 节)确实指出
如果路径由多段组成,则只有最后一段会获得箭头提示。闭合路径的行为尚未指定,将来可能会发生变化
这可能应该被解释为,不应该期望在包含close-path
任何地方(不仅仅是在最后)。请注意,这还包括用\pgfpathrectangle
及其变体绘制的矩形。
但是,至少在这种情况下,一切都没有丢失。由于您无需使用圆形的闭合路径(无论如何,根据我的眼睛),因此您可以只使用圆弧:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations}
\tikzset{%
system signal/.style={%
decoration={%
system signal decoration,
segment length=10pt,
amplitude=5pt
},
very thin,
decorate
}
}
\pgfdeclaredecoration{system signal decoration}{line}%
{%
\state{line}[
width=+\pgfdecorationsegmentlength,next state=symbol,
switch if input segment less than=.5\pgfdecorationsegmentlength to segment 1,
switch if input segment less than=+\pgfdecorationsegmentlength to segment 2
]{%
\pgfpathlineto{\pgfqpoint{\pgfdecorationsegmentlength}{0pt}}%
}
%
\state{symbol}[
width=+\pgfdecorationsegmentamplitude,
next state=line,
switch if input segment less than=+\pgfdecorationsegmentamplitude to segment 2
]{%
\pgfpatharc{180}{-180}{.5\pgfdecorationsegmentamplitude}%
\pgfpathmoveto{\pgfqpoint{.25\pgfdecorationsegmentamplitude}{0pt}}%
\pgfpatharc{180}{-180}{.25\pgfdecorationsegmentamplitude}%
\pgfpathmoveto{\pgfqpoint{\pgfdecorationsegmentamplitude}{0pt}}%
}%
%
\state{segment 1}[%
next state=line,
width=+\pgfdecoratedinputsegmentremainingdistance
]%
{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}%
}%
%
\state{segment 2}[%
next state=symbol,
width=+\pgfdecoratedinputsegmentremainingdistance
]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}%
}%
%
\state{segment 3}[
next state=symbol,%
width=.2\pgfdecorationsegmentlength,
switch if input segment less than=.2\pgfdecorationsegmentlength to segment 2
]{%
\pgfpathlineto{\pgfqpoint{.2\pgfdecorationsegmentlength}{0pt}}%
}%
%
\state{final}{%
\pgfpathlineto{\pgfpointdecoratedpathlast}%
}%
}
\begin{document}
\tikz\draw[->,system signal] (0,0) -- (2,0);
\end{document}
这会产生类似这样的结果:
另外,我们可以破解!此破解添加了一个\ifpgfarrowsonclosedpath
和一个关联键(结果与上面相同)。
\documentclass{standalone}
\usepackage{tikz}
\makeatletter
\newif\ifpgfarrowsonclosedpath
\def\pgf@check@for@arrows{%
\pgf@drawarrowsfalse%
\ifx\pgf@startarrow\pgfutil@empty\else\pgf@drawarrowstrue\fi%
\ifx\pgf@endarrow\pgfutil@empty\else\pgf@drawarrowstrue\fi%
\ifdim\pgf@shorten@end@additional=0pt\relax\else\pgf@drawarrowstrue\fi%
\ifdim\pgf@shorten@start@additional=0pt\relax\else\pgf@drawarrowstrue\fi%
\ifpgf@drawarrows%
\pgfsyssoftpath@getcurrentpath\pgf@arrowpath%
\ifx\pgf@arrowpath\pgfutil@empty%
\pgf@drawarrowsfalse%
\else%
\ifpgfarrowsonclosedpath%
\else%
\pgfprocesscheckclosed{\pgf@arrowpath}{\pgf@drawarrowsfalse}%
\fi%
\fi%
\fi%
}
\tikzset{arrows on closed path/.is if=pgfarrowsonclosedpath}
\usetikzlibrary{decorations}
\tikzset{%
system signal/.style={%
decoration={%
system signal decoration,
segment length=10pt,
amplitude=5pt
},
very thin,
arrows on closed path,
decorate
}
}
\pgfdeclaredecoration{system signal decoration}{line}%
{%
\state{line}[
width=+\pgfdecorationsegmentlength,next state=symbol,
switch if input segment less than=.5\pgfdecorationsegmentlength to segment 1,
switch if input segment less than=+\pgfdecorationsegmentlength to segment 2
]{%
\pgfpathlineto{\pgfqpoint{\pgfdecorationsegmentlength}{0pt}}%
}
%
\state{symbol}[
width=+\pgfdecorationsegmentamplitude,
next state=line,
switch if input segment less than=+\pgfdecorationsegmentamplitude to segment 2
]{%
\pgfpathcircle{\pgfqpoint{.5\pgfdecorationsegmentamplitude}{0pt}}{.5\pgfdecorationsegmentamplitude}%
\pgfpathcircle{\pgfqpoint{.5\pgfdecorationsegmentamplitude}{0pt}}{.25\pgfdecorationsegmentamplitude}%
\pgfpathmoveto{\pgfqpoint{\pgfdecorationsegmentamplitude}{0pt}}%
}%
%
\state{segment 1}[%
next state=line,
width=+\pgfdecoratedinputsegmentremainingdistance
]%
{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}%
}%
%
\state{segment 2}[%
next state=symbol,
width=+\pgfdecoratedinputsegmentremainingdistance
]{%
\pgfpathlineto{\pgfpointdecoratedinputsegmentlast}%
}%
%
\state{segment 3}[
next state=symbol,%
width=.2\pgfdecorationsegmentlength,
switch if input segment less than=.2\pgfdecorationsegmentlength to segment 2
]{%
\pgfpathlineto{\pgfqpoint{.2\pgfdecorationsegmentlength}{0pt}}%
}%
%
\state{final}{%
\pgfpathlineto{\pgfpointdecoratedpathlast}%
}%
}
\begin{document}
\tikz\draw[->,system signal] (0,0) -- (2,0);
\end{document}
编辑:扩展了未绘制箭头的情况并添加了 hack。