我正在编译:
- pdfTeX,版本 3.1415926-2.3-1.40.12(MiKTeX 2.9 64 位)(预加载格式=pdflatex 2011.7.8)
- pgf 2008/01/15 v2.10 (rcs-修订版 1.12)
- tikz 2010/10/13 v2.10 (rcs-修订版 1.76)
我正在尝试创建两个新形状,用于 PGF/TikZ 环境,用于嵌入式工程的最终论文。这些符号的目的是制作一个任务图,有点像 UML 图。第一个符号是一个简单的 FIFO 队列符号,我认为它可以作为第二个符号的模板。
这些是我以前上过的嵌入式编程课程中的图。所以我可以自由地创建自己的图。但这些似乎是我学校的标准,所以我不想偏离太多。
通过阅读这个答案我已经明白了(使用 TikZ 绘制 3D 立方体的最简单方法是什么?并感谢 Matthew Leingang 的回答)我可以复制矩形并删除西边和东边,如下所示:
\makeatletter
\pgfkeys{/pgf/.cd,
fifo offset x/.initial=20pt,
fifo offset y/.initial=20pt
}
\pgfdeclareshape{fifo}
{
\inheritsavedanchors[from=rectangle] % this is nearly a rectangle
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
\backgroundpath{
% store lower right in xa/ya and upper right in xb/yb
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/fifo offset x}}%
\pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/fifo offset y}}%
\def\ppd@offset{\pgfpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}%
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}%
\pgfpathclose%
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
\pgfpathclose
}
}
\makeatother
这给了我这个:
我可以接受这一点,将文本放在中心还可以为指向其他节点的箭头打开更多连接点。但我仍然需要一个带有信号量符号和信号量名称的 FIFO。就我而言,我无法破解这一点。我在想我应该做一个多部分节点,这样我就会有一个用于队列名称和信号量名称的字段。
我尝试创建内部垂直线,但只创建了第一条,然后接下来的几条导致编译崩溃。我首先定义它们之间的偏移量:
通过增加:
\pgfkeys{/pgf/.cd,
internal_displacement x/.initial=5pt,
internal_displacement y/.initial=5pt
}
在第一个 \pgfkeys 和 \pgfdeclareshape 之间,然后我使用以下命令为垂直线定义了新的 x 轴值:
\pgf@xc=\pgf@xb \advance\pgf@xc by-\pgfkeysvalueof{/pgf/internal_displacement x}%
并添加路径:
\pgfpathmoveto{\pgfqpoint{\pgf@xc}{\pgf@ya}}
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yb}}
\pgfpathclose
这给了我这个:
太棒了!对吧?!但是我想定义更多的垂直线,所以我在声明 \pgf@xc 之后立即添加了这个:
\pgf@xd=\pgf@xc \advance\pgf@xd by-\pgfkeysvalueof{/pgf/internal_displacement x}%
\pgf@xe=\pgf@xd \advance\pgf@xe by-\pgfkeysvalueof{/pgf/internal_displacement x}%
\pgf@xf=\pgf@xe \advance\pgf@xf by-\pgfkeysvalueof{/pgf/internal_displacement x}%
我认为这应该将 x 值向左移动 internal_displacement x,但是我却得到了一大堆错误,如下所示:
\pgf@sh@bg@fifo ...nternal_displacement x}\pgf@xe
=\pgf@xd \advance \pgf@xe ...
l.10 ...idth=2cm,align=center] (fifo1) {Node One};
我猜想 internal_displacement x 在第一次读取后就被清除了?这似乎适得其反。一定还有其他方法可以做到这一点。
那么有谁知道:
- 获取使用多部分节点添加的信号量符号(因此我必须使用文本字段)
- 我在垂直线上做错了什么?我在想,如果我能解决这个问题,我就不会在垂直线和水平线之间的距离上遇到麻烦了。
答案1
如果形状声明变得困难,您还可以用图案填充来放置节点并对其进行装饰。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{patterns}
\makeatletter
\tikzset{
mynode/.style={outer sep=1mm,
pattern=vertical lines,
minimum width=2cm,
minimum height=1cm,
append after command={
\pgfextra{
\draw(\tikzlastnode.north east) -- (\tikz@last@[email protected] west);
\draw(\tikz@last@[email protected] east) -- (\tikz@last@[email protected] west);
\node[anchor=north] at (\tikz@last@[email protected]) {#1};}
}
},
with flag/.style={append after command={
\pgfextra{
\draw[fill=white](\tikzlastnode.135) circle (3mm);
\draw[fill,line width=1mm,line cap=round,line join=round]
([xshift=-1pt]\tikzlastnode.135) +(0,-2mm) -- ++(0,2mm) --++(-35:2mm) --++(-145:2mm);
}
},
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[mynode={Queue Name}] (a) at (0,0) {};
\node[mynode={Another Queue}, with flag] (b) at (1,2) {};
\end{tikzpicture}
\end{document}
答案2
以下是一些入门知识。首先,基本要点:
错误消息是由于您尝试使用尚未初始化的维度寄存器而产生的。这些是
\pgf@xd
和 等等。仅最多\pgf@xc
和\pgf@yc
已被声明。除非您正在做一些非常棘手的事情,否则通常可以简单地重用已经存在的寄存器。不过,这可能需要一点簿记。要重复某些内容,请使用循环。节点旨在根据文本调整大小,因此指定固定数量的条形会带来麻烦。更好的方法是使用循环绘制条形,并在到达底部之前停止。
这里有一些可以实现该功能的代码,以及将绘图移到文本上方。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/71487/86}
\usepackage{tikz}
\makeatletter
\pgfkeys{/pgf/.cd,
fifo offset x/.initial=20pt,
fifo offset y/.initial=20pt,
internal_displacement x/.initial=5pt,
internal_displacement y/.initial=5pt,
fifo height/.initial=20pt,
}
\pgfdeclareshape{fifo}
{
\inheritsavedanchors[from=rectangle] % this is nearly a rectangle
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
\backgroundpath{
% store lower right in xa/ya and upper right in xb/yb
\southwest \pgf@xa=\pgf@x
\northeast \pgf@xb=\pgf@x \pgf@ya=\pgf@y
\pgf@yb=\pgf@ya
\advance\pgf@yb by \pgfkeysvalueof{/pgf/fifo height}%
\pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/pgf/fifo offset x}}%
\pgfmathsetlength\pgfutil@tempdimb{\pgfkeysvalueof{/pgf/fifo offset y}}%
\def\ppd@offset{\pgfpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}%
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}%
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
\pgf@xc=\pgf@xb
\advance\pgf@xc by-\pgfkeysvalueof{/pgf/internal_displacement x}%
\advance\pgf@xa by \pgfkeysvalueof{/pgf/internal_displacement x}%
\advance\pgf@yb by-\pgfkeysvalueof{/pgf/internal_displacement y}%
\advance\pgf@ya by \pgfkeysvalueof{/pgf/internal_displacement y}%
\loop\ifdim\pgf@xc>\pgf@xa\relax
\pgfpathmoveto{\pgfqpoint{\pgf@xc}{\pgf@ya}}
\pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yb}}
\advance\pgf@xc by-\pgfkeysvalueof{/pgf/internal_displacement x}%
\repeat
\pgfpathclose
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[fifo,draw] {Node One};
\end{tikzpicture}
\end{document}
结果:
进一步的工作:
- 边界框计算错误,我认为是因为背景路径没有围绕文本。只需使用一个简单的 即可修复此问题
\pgfpathmoveto
。 - 锚点应该调整,真的
north east
位于整个图表的东北部,而不是文本的东北部。(请注意已保存锚点和锚点用于坐标计算。) - 您可能需要使用更多锚点来指向不同的部分:文本和绘图。
- 对于信号量,我同意多部分节点是可行的方法。