Latex Tikz/Pgf 声明带有参数的形状和带有数字的锚点
Latex Tikz/Pgf declaring shapes with parameters and anchors with numbers
我正在用 pgf 写一些形状,我并不是很了解它是如何工作的,但我设法阅读了文档。
\pgfdeclareshape{reg}{
% The 'minimum width' and 'minimum height' keys, not the content, determine
% the size
\savedanchor\northeast{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=0.11\pgf@x
\pgf@y=0.15\pgf@y
}
% This is redundant, but makes some things easier:
\savedanchor\southwest{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=-0.11\pgf@x
\pgf@y=-0.15\pgf@y
}
% Inherit from rectangle
\inheritanchorborder[from=rectangle]
% Define same anchor a normal rectangle has
\anchor{center}{\pgfpointorigin}
\anchor{north}{\northeast \pgf@x=0pt}
\anchor{east}{\northeast \pgf@y=0pt}
\anchor{south}{\southwest \pgf@x=0pt}
\anchor{west}{\southwest \pgf@y=0pt}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast \pgf@x=-\pgf@x}
\anchor{south west}{\southwest}
\anchor{south east}{\southwest \pgf@x=-\pgf@x}
\anchor{text}{
\pgfpointorigin
\advance\pgf@x by -.5\wd\pgfnodeparttextbox%
\advance\pgf@y by -.5\ht\pgfnodeparttextbox%
\advance\pgf@y by +.5\dp\pgfnodeparttextbox%
}
% Define anchors for signal ports
\anchor{CLK}{
\pgf@process{\northeast}%
\pgf@x=0\pgf@x%
\pgf@y=1\pgf@y%
}
\anchor{PC}{
\pgf@process{\northeast}%
\pgf@x=-2.5\pgf@x%
\pgf@y=0\pgf@y%
}
\anchor{PCS}{
\pgf@process{\northeast}%
\pgf@x=2.5\pgf@x%
\pgf@y=0\pgf@y%
}
% Draw the rectangle box and the port labels
\backgroundpath{
% Rectangle box
\pgfpathrectanglecorners{\southwest}{\northeast}
% Drawing Triangle for clock input
% upper left x
\southwest \pgf@xa=\pgf@x
\northeast \pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xb=\pgf@x
\pgf@anchor@reg@CLK
\pgf@xc=\pgf@x \pgf@yc=\pgf@y
\pgfmathsetlength\pgf@x{1.3ex}
\advance\pgf@xa by .15mm
\advance\pgf@xb by -.15mm
\advance\pgf@yc by -\pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
\pgfclosepath
\tikzset{flip flop/port labels} % Use font from this style
\tikz@textfont
%Drawing CLK circuit
\pgf@anchor@reg@CLK
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfmathsetlength\pgf@x{1.8ex}
\advance\pgf@yb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
%Draw clock label
\pgf@anchor@reg@CLK\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{2.5ex}{CLK}}
%Drawing PC circuit
\pgf@anchor@reg@PC
\pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xa=\pgf@x
\pgf@anchor@reg@west
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.7ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PC\pgftext[base,at={\pgfpoint{\pgf@x+0.5ex}{\pgf@y}}]{\raisebox{.5ex}{PC}}
%Drawing PC' circuit
\pgf@anchor@reg@PCS
\pgf@ya=\pgf@y \pgf@yb=\pgf@y\pgf@xa=\pgf@x
\pgf@anchor@reg@east
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.5ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PCS\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{.5ex}{PC'}}
}
}
这里我创建了一个形状,在外面有一些连接点,效果很好。但是我真的很想在创建这个形状时有一个参数,这样我就可以指定端口的数量。
比如像这样
\begin{tikzpicture}
\node [reg,black!50,ports=3] (PC) at (0,0) {};
\end{tikzpicture}
但我在文档中找不到允许自定义参数的内容。我还想将锚点命名为 A1、A2 和 A3,但我似乎无法在名称中添加数字,即使在文档中它明确表示像“1”和“::”这样的名称应该没问题,但仍然 "A1"是。
如果有人知道如何执行此操作,我将不胜感激。也许还有一些关于使用 pgf 创建形状的更好参考。
为了编辑 tex 文件,我使用带有 pdflatex 的 Overleaf。
编辑:
我现在发现您可以使用 \pgfkeys
向形状添加参数,但它们似乎无法正常工作,我真的不知道该怎么做。
\def\microarchbasekey{/tikz/microarch}
\pgfkeys{\microarchbasekey/.is family}
\pgfdeclareshape{mux}{
\pgfkeys{\microarchbasekey,inputs/.initial=2,spacing/.initial=5}
\savedmacro{\numpins}{
\def\numpins{\pgfkeysvalueof{\microarchbasekey/inputs}}
}
\saveddimen{\spacing}{
\pgf@x = \pgfkeysvalueof{\microarchbasekey/spacing}
}
%a lot of code down there
}
但它给了我以下错误
A number should have been here; I inserted `0'.
(If you can't figure out why I needed to see a number,
look up `weird error' in the index to The TeXbook.)
但是我找不到代码的缺失部分。
可能这是一个更适合 TeX/LaTeX site 的问题,但无论如何...
关键的事情如下:
为参数添加键。注意层次结构,node
需要 /tikz
家族下的键:
%
% better to create a family, but as an example...
\tikzset{flip flop/port labels/.initial={\tiny}}
%
% number of ports
\tikzset{ports/.initial=4}
%
% we need a counter
\newcount\tmp@a
添加稳定(链接到特定节点,而不是通用形状)参数,所有这些都需要计算锚点的位置:
% you have to save the relevant parameters as \savedmacro
\savedmacro\numports{
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
}
% and \saveddimen
\saveddimen\pinsdelta{
% you can't use savedmacros nor savedanchors here (bummer!)
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
\pgfmathsetlength\pgf@x{0.22*\pgfshapeminheight/(\numports+1)}%
}
在形状定义中,您必须使用技巧添加锚点——锚点必须添加到形状内部函数中。危险,因为开发人员可以在将来更改它(它已经发生了),但我没有其他办法。
% create input anchors
% this touch internal things, so beware...
% anchors are named pgf@anchor@<name-of-the-shape>@<name of the anchors>
\pgfutil@g@addto@macro\pgf@sh@s@reg{%
\tmp@a=\numports\relax
\pgfmathloop%
\ifnum\pgfmathcounter>\tmp@a%
\else%
% assign the anchor "in \pgfmathcounter" to the macro \reg@port with the number as argument
\expandafter\xdef\csname pgf@anchor@reg@in \pgfmathcounter\endcsname{%
\noexpand\reg@port{\pgfmathcounter}% defined below
}%
% \typeout{YAY\space\pgfmathcounter}
\repeatpgfmathloop%
}
定义计算变量锚点的具体函数。你必须在这里只使用 \saved...
种参数,否则,你的锚点将使用参数的最后一个值,而不是节点指定的正确值。
\def\reg@port#1{%
% this macro has the function to return the position of the anchor
% it must use only \savedanchors and \savedmacros
% the parameter is the number of the anchor (see above)
\northeast
\pgf@x=-\pgf@x
\pgf@ya=\pgf@y
\pgfmathsetlength{\pgf@y}{\pgf@ya-(#1+0.5)*\pinsdelta}%
}
现在,我不明白你是如何画出你的形状的,所以锚点不在它们应该去的地方,但是好吧:
我的完整代码在这里:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\makeatletter
%
% better to create a family, but as an example...
\tikzset{flip flop/port labels/.initial={\tiny}}
%
% number of ports
\tikzset{ports/.initial=4}
%
% we need a counter
\newcount\tmp@a
\pgfdeclareshape{reg}{
% you have to save the relevant parameters as \savedmacro
\savedmacro\numports{
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
}
% and \saveddimen
\saveddimen\pinsdelta{
% you can't use savedmacros nor savedanchors here (bummer!)
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
\pgfmathsetlength\pgf@x{0.22*\pgfshapeminheight/(\numports+1)}%
}
% The 'minimum width' and 'minimum height' keys, not the content, determine
% the size
\savedanchor\northeast{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=0.11\pgf@x
\pgf@y=0.15\pgf@y
}
% This is redundant, but makes some things easier:
\savedanchor\southwest{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=-0.11\pgf@x
\pgf@y=-0.15\pgf@y
}
% Inherit from rectangle
\inheritanchorborder[from=rectangle]
% Define same anchor a normal rectangle has
\anchor{center}{\pgfpointorigin}
\anchor{north}{\northeast \pgf@x=0pt}
\anchor{east}{\northeast \pgf@y=0pt}
\anchor{south}{\southwest \pgf@x=0pt}
\anchor{west}{\southwest \pgf@y=0pt}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast \pgf@x=-\pgf@x}
\anchor{south west}{\southwest}
\anchor{south east}{\southwest \pgf@x=-\pgf@x}
\anchor{text}{
\pgfpointorigin
\advance\pgf@x by -.5\wd\pgfnodeparttextbox%
\advance\pgf@y by -.5\ht\pgfnodeparttextbox%
\advance\pgf@y by +.5\dp\pgfnodeparttextbox%
}
% Define anchors for signal ports
\anchor{CLK}{
\pgf@process{\northeast}%
\pgf@x=0\pgf@x%
\pgf@y=1\pgf@y%
}
\anchor{PC}{
\pgf@process{\northeast}%
\pgf@x=-2.5\pgf@x%
\pgf@y=0\pgf@y%
}
\anchor{PCS}{
\pgf@process{\northeast}%
\pgf@x=2.5\pgf@x%
\pgf@y=0\pgf@y%
}
% Draw the rectangle box and the port labels
\backgroundpath{
% Rectangle box
\pgfpathrectanglecorners{\southwest}{\northeast}
% Drawing Triangle for clock input
% upper left x
\southwest \pgf@xa=\pgf@x
\northeast \pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xb=\pgf@x
\pgf@anchor@reg@CLK
\pgf@xc=\pgf@x \pgf@yc=\pgf@y
\pgfmathsetlength\pgf@x{1.3ex}
\advance\pgf@xa by .15mm
\advance\pgf@xb by -.15mm
\advance\pgf@yc by -\pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
\pgfclosepath
\tikzset{flip flop/port labels} % Use font from this style
\tikz@textfont
%Drawing CLK circuit
\pgf@anchor@reg@CLK
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfmathsetlength\pgf@x{1.8ex}
\advance\pgf@yb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
%Draw clock label
\pgf@anchor@reg@CLK\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{2.5ex}{CLK}}
%Drawing PC circuit
\pgf@anchor@reg@PC
\pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xa=\pgf@x
\pgf@anchor@reg@west
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.7ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PC\pgftext[base,at={\pgfpoint{\pgf@x+0.5ex}{\pgf@y}}]{\raisebox{.5ex}{PC}}
%Drawing PC' circuit
\pgf@anchor@reg@PCS
\pgf@ya=\pgf@y \pgf@yb=\pgf@y\pgf@xa=\pgf@x
\pgf@anchor@reg@east
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.5ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PCS\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{.5ex}{PC'}}
}
% create input anchors
% this touch internal things, so beware...
% anchors are named pgf@anchor@<name-of-the-shape>@<name of the anchors>
\pgfutil@g@addto@macro\pgf@sh@s@reg{%
\tmp@a=\numports\relax
\pgfmathloop%
\ifnum\pgfmathcounter>\tmp@a%
\else%
% assign the anchor "in \pgfmathcounter" to the macro \reg@port with the number as argument
\expandafter\xdef\csname pgf@anchor@reg@in \pgfmathcounter\endcsname{%
\noexpand\reg@port{\pgfmathcounter}% defined below
}%
% \typeout{YAY\space\pgfmathcounter}
\repeatpgfmathloop%
}
}
%
\def\reg@port#1{%
% this macro has the function to return the position of the anchor
% it must use only \savedanchors and \savedmacros
% the parameter is the number of the anchor (see above)
\northeast
\pgf@x=-\pgf@x
\pgf@ya=\pgf@y
\pgfmathsetlength{\pgf@y}{\pgf@ya-(#1+0.5)*\pinsdelta}%
}
\makeatother
%%% handy macro to show the anchors
\def\showcoord(#1)<#2:#3>{%
node[circle, red, draw, inner sep=1pt,pin={%
[red, inner sep=0.5pt, font=\small,
pin distance=#3cm, pin edge={red, }%
]#2:#1}](#1){}}
\begin{document}
\begin{tikzpicture}
\node [draw,reg,minimum width=3cm, minimum height=3cm, black!50] (PC1) at (0,0) {};
\path (PC1.north west) \showcoord(NW)<45:0.2>;
\node [draw, reg,black!50,minimum width=3cm, minimum height=5cm, ports=6, blue] (PC2) at (3,0) {};
\foreach \p in {1,...,4} \path(PC1.in \p) \showcoord(in \p)<145:0.3>;
\foreach \p in {1,...,6} \path(PC2.in \p) \showcoord(in \p)<145:0.3>;
\end{tikzpicture}
\end{document}
我正在用 pgf 写一些形状,我并不是很了解它是如何工作的,但我设法阅读了文档。
\pgfdeclareshape{reg}{
% The 'minimum width' and 'minimum height' keys, not the content, determine
% the size
\savedanchor\northeast{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=0.11\pgf@x
\pgf@y=0.15\pgf@y
}
% This is redundant, but makes some things easier:
\savedanchor\southwest{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=-0.11\pgf@x
\pgf@y=-0.15\pgf@y
}
% Inherit from rectangle
\inheritanchorborder[from=rectangle]
% Define same anchor a normal rectangle has
\anchor{center}{\pgfpointorigin}
\anchor{north}{\northeast \pgf@x=0pt}
\anchor{east}{\northeast \pgf@y=0pt}
\anchor{south}{\southwest \pgf@x=0pt}
\anchor{west}{\southwest \pgf@y=0pt}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast \pgf@x=-\pgf@x}
\anchor{south west}{\southwest}
\anchor{south east}{\southwest \pgf@x=-\pgf@x}
\anchor{text}{
\pgfpointorigin
\advance\pgf@x by -.5\wd\pgfnodeparttextbox%
\advance\pgf@y by -.5\ht\pgfnodeparttextbox%
\advance\pgf@y by +.5\dp\pgfnodeparttextbox%
}
% Define anchors for signal ports
\anchor{CLK}{
\pgf@process{\northeast}%
\pgf@x=0\pgf@x%
\pgf@y=1\pgf@y%
}
\anchor{PC}{
\pgf@process{\northeast}%
\pgf@x=-2.5\pgf@x%
\pgf@y=0\pgf@y%
}
\anchor{PCS}{
\pgf@process{\northeast}%
\pgf@x=2.5\pgf@x%
\pgf@y=0\pgf@y%
}
% Draw the rectangle box and the port labels
\backgroundpath{
% Rectangle box
\pgfpathrectanglecorners{\southwest}{\northeast}
% Drawing Triangle for clock input
% upper left x
\southwest \pgf@xa=\pgf@x
\northeast \pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xb=\pgf@x
\pgf@anchor@reg@CLK
\pgf@xc=\pgf@x \pgf@yc=\pgf@y
\pgfmathsetlength\pgf@x{1.3ex}
\advance\pgf@xa by .15mm
\advance\pgf@xb by -.15mm
\advance\pgf@yc by -\pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
\pgfclosepath
\tikzset{flip flop/port labels} % Use font from this style
\tikz@textfont
%Drawing CLK circuit
\pgf@anchor@reg@CLK
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfmathsetlength\pgf@x{1.8ex}
\advance\pgf@yb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
%Draw clock label
\pgf@anchor@reg@CLK\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{2.5ex}{CLK}}
%Drawing PC circuit
\pgf@anchor@reg@PC
\pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xa=\pgf@x
\pgf@anchor@reg@west
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.7ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PC\pgftext[base,at={\pgfpoint{\pgf@x+0.5ex}{\pgf@y}}]{\raisebox{.5ex}{PC}}
%Drawing PC' circuit
\pgf@anchor@reg@PCS
\pgf@ya=\pgf@y \pgf@yb=\pgf@y\pgf@xa=\pgf@x
\pgf@anchor@reg@east
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.5ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PCS\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{.5ex}{PC'}}
}
}
这里我创建了一个形状,在外面有一些连接点,效果很好。但是我真的很想在创建这个形状时有一个参数,这样我就可以指定端口的数量。
比如像这样
\begin{tikzpicture}
\node [reg,black!50,ports=3] (PC) at (0,0) {};
\end{tikzpicture}
但我在文档中找不到允许自定义参数的内容。我还想将锚点命名为 A1、A2 和 A3,但我似乎无法在名称中添加数字,即使在文档中它明确表示像“1”和“::”这样的名称应该没问题,但仍然 "A1"是。
如果有人知道如何执行此操作,我将不胜感激。也许还有一些关于使用 pgf 创建形状的更好参考。
为了编辑 tex 文件,我使用带有 pdflatex 的 Overleaf。
编辑:
我现在发现您可以使用 \pgfkeys
向形状添加参数,但它们似乎无法正常工作,我真的不知道该怎么做。
\def\microarchbasekey{/tikz/microarch}
\pgfkeys{\microarchbasekey/.is family}
\pgfdeclareshape{mux}{
\pgfkeys{\microarchbasekey,inputs/.initial=2,spacing/.initial=5}
\savedmacro{\numpins}{
\def\numpins{\pgfkeysvalueof{\microarchbasekey/inputs}}
}
\saveddimen{\spacing}{
\pgf@x = \pgfkeysvalueof{\microarchbasekey/spacing}
}
%a lot of code down there
}
但它给了我以下错误
A number should have been here; I inserted `0'.
(If you can't figure out why I needed to see a number,
look up `weird error' in the index to The TeXbook.)
但是我找不到代码的缺失部分。
可能这是一个更适合 TeX/LaTeX site 的问题,但无论如何...
关键的事情如下:
为参数添加键。注意层次结构,
node
需要/tikz
家族下的键:% % better to create a family, but as an example... \tikzset{flip flop/port labels/.initial={\tiny}} % % number of ports \tikzset{ports/.initial=4} % % we need a counter \newcount\tmp@a
添加稳定(链接到特定节点,而不是通用形状)参数,所有这些都需要计算锚点的位置:
% you have to save the relevant parameters as \savedmacro \savedmacro\numports{ \edef\numports{\pgfkeysvalueof{/tikz/ports}}% } % and \saveddimen \saveddimen\pinsdelta{ % you can't use savedmacros nor savedanchors here (bummer!) \edef\numports{\pgfkeysvalueof{/tikz/ports}}% \pgfmathsetlength\pgf@x{0.22*\pgfshapeminheight/(\numports+1)}% }
在形状定义中,您必须使用技巧添加锚点——锚点必须添加到形状内部函数中。危险,因为开发人员可以在将来更改它(它已经发生了),但我没有其他办法。
% create input anchors % this touch internal things, so beware... % anchors are named pgf@anchor@<name-of-the-shape>@<name of the anchors> \pgfutil@g@addto@macro\pgf@sh@s@reg{% \tmp@a=\numports\relax \pgfmathloop% \ifnum\pgfmathcounter>\tmp@a% \else% % assign the anchor "in \pgfmathcounter" to the macro \reg@port with the number as argument \expandafter\xdef\csname pgf@anchor@reg@in \pgfmathcounter\endcsname{% \noexpand\reg@port{\pgfmathcounter}% defined below }% % \typeout{YAY\space\pgfmathcounter} \repeatpgfmathloop% }
定义计算变量锚点的具体函数。你必须在这里只使用
\saved...
种参数,否则,你的锚点将使用参数的最后一个值,而不是节点指定的正确值。\def\reg@port#1{% % this macro has the function to return the position of the anchor % it must use only \savedanchors and \savedmacros % the parameter is the number of the anchor (see above) \northeast \pgf@x=-\pgf@x \pgf@ya=\pgf@y \pgfmathsetlength{\pgf@y}{\pgf@ya-(#1+0.5)*\pinsdelta}% }
现在,我不明白你是如何画出你的形状的,所以锚点不在它们应该去的地方,但是好吧:
我的完整代码在这里:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\makeatletter
%
% better to create a family, but as an example...
\tikzset{flip flop/port labels/.initial={\tiny}}
%
% number of ports
\tikzset{ports/.initial=4}
%
% we need a counter
\newcount\tmp@a
\pgfdeclareshape{reg}{
% you have to save the relevant parameters as \savedmacro
\savedmacro\numports{
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
}
% and \saveddimen
\saveddimen\pinsdelta{
% you can't use savedmacros nor savedanchors here (bummer!)
\edef\numports{\pgfkeysvalueof{/tikz/ports}}%
\pgfmathsetlength\pgf@x{0.22*\pgfshapeminheight/(\numports+1)}%
}
% The 'minimum width' and 'minimum height' keys, not the content, determine
% the size
\savedanchor\northeast{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=0.11\pgf@x
\pgf@y=0.15\pgf@y
}
% This is redundant, but makes some things easier:
\savedanchor\southwest{%
\pgfmathsetlength\pgf@x{\pgfshapeminwidth}%
\pgfmathsetlength\pgf@y{\pgfshapeminheight}%
\pgf@x=-0.11\pgf@x
\pgf@y=-0.15\pgf@y
}
% Inherit from rectangle
\inheritanchorborder[from=rectangle]
% Define same anchor a normal rectangle has
\anchor{center}{\pgfpointorigin}
\anchor{north}{\northeast \pgf@x=0pt}
\anchor{east}{\northeast \pgf@y=0pt}
\anchor{south}{\southwest \pgf@x=0pt}
\anchor{west}{\southwest \pgf@y=0pt}
\anchor{north east}{\northeast}
\anchor{north west}{\northeast \pgf@x=-\pgf@x}
\anchor{south west}{\southwest}
\anchor{south east}{\southwest \pgf@x=-\pgf@x}
\anchor{text}{
\pgfpointorigin
\advance\pgf@x by -.5\wd\pgfnodeparttextbox%
\advance\pgf@y by -.5\ht\pgfnodeparttextbox%
\advance\pgf@y by +.5\dp\pgfnodeparttextbox%
}
% Define anchors for signal ports
\anchor{CLK}{
\pgf@process{\northeast}%
\pgf@x=0\pgf@x%
\pgf@y=1\pgf@y%
}
\anchor{PC}{
\pgf@process{\northeast}%
\pgf@x=-2.5\pgf@x%
\pgf@y=0\pgf@y%
}
\anchor{PCS}{
\pgf@process{\northeast}%
\pgf@x=2.5\pgf@x%
\pgf@y=0\pgf@y%
}
% Draw the rectangle box and the port labels
\backgroundpath{
% Rectangle box
\pgfpathrectanglecorners{\southwest}{\northeast}
% Drawing Triangle for clock input
% upper left x
\southwest \pgf@xa=\pgf@x
\northeast \pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xb=\pgf@x
\pgf@anchor@reg@CLK
\pgf@xc=\pgf@x \pgf@yc=\pgf@y
\pgfmathsetlength\pgf@x{1.3ex}
\advance\pgf@xa by .15mm
\advance\pgf@xb by -.15mm
\advance\pgf@yc by -\pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
\pgfclosepath
\tikzset{flip flop/port labels} % Use font from this style
\tikz@textfont
%Drawing CLK circuit
\pgf@anchor@reg@CLK
\pgf@xa=\pgf@x \pgf@ya=\pgf@y
\pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfmathsetlength\pgf@x{1.8ex}
\advance\pgf@yb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
%Draw clock label
\pgf@anchor@reg@CLK\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{2.5ex}{CLK}}
%Drawing PC circuit
\pgf@anchor@reg@PC
\pgf@ya=\pgf@y \pgf@yb=\pgf@y \pgf@xa=\pgf@x
\pgf@anchor@reg@west
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.7ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PC\pgftext[base,at={\pgfpoint{\pgf@x+0.5ex}{\pgf@y}}]{\raisebox{.5ex}{PC}}
%Drawing PC' circuit
\pgf@anchor@reg@PCS
\pgf@ya=\pgf@y \pgf@yb=\pgf@y\pgf@xa=\pgf@x
\pgf@anchor@reg@east
\pgf@xb=\pgf@x
%\pgfmathsetlength\pgf@x{2.5ex}
%\advance\pgf@xb by \pgf@x
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
\pgf@anchor@reg@PCS\pgftext[base,at={\pgfpoint{\pgf@x}{\pgf@y}}]{\raisebox{.5ex}{PC'}}
}
% create input anchors
% this touch internal things, so beware...
% anchors are named pgf@anchor@<name-of-the-shape>@<name of the anchors>
\pgfutil@g@addto@macro\pgf@sh@s@reg{%
\tmp@a=\numports\relax
\pgfmathloop%
\ifnum\pgfmathcounter>\tmp@a%
\else%
% assign the anchor "in \pgfmathcounter" to the macro \reg@port with the number as argument
\expandafter\xdef\csname pgf@anchor@reg@in \pgfmathcounter\endcsname{%
\noexpand\reg@port{\pgfmathcounter}% defined below
}%
% \typeout{YAY\space\pgfmathcounter}
\repeatpgfmathloop%
}
}
%
\def\reg@port#1{%
% this macro has the function to return the position of the anchor
% it must use only \savedanchors and \savedmacros
% the parameter is the number of the anchor (see above)
\northeast
\pgf@x=-\pgf@x
\pgf@ya=\pgf@y
\pgfmathsetlength{\pgf@y}{\pgf@ya-(#1+0.5)*\pinsdelta}%
}
\makeatother
%%% handy macro to show the anchors
\def\showcoord(#1)<#2:#3>{%
node[circle, red, draw, inner sep=1pt,pin={%
[red, inner sep=0.5pt, font=\small,
pin distance=#3cm, pin edge={red, }%
]#2:#1}](#1){}}
\begin{document}
\begin{tikzpicture}
\node [draw,reg,minimum width=3cm, minimum height=3cm, black!50] (PC1) at (0,0) {};
\path (PC1.north west) \showcoord(NW)<45:0.2>;
\node [draw, reg,black!50,minimum width=3cm, minimum height=5cm, ports=6, blue] (PC2) at (3,0) {};
\foreach \p in {1,...,4} \path(PC1.in \p) \showcoord(in \p)<145:0.3>;
\foreach \p in {1,...,6} \path(PC2.in \p) \showcoord(in \p)<145:0.3>;
\end{tikzpicture}
\end{document}