为了绘制印刷电路板布局,我们定义了一个 DIP 形状(shapes.tex
):
\pgfkeys{/pgf/.cd,
pcbpins/.initial=14,
pcbdipdx/.initial=0.3 in,
pcbdipwidth/.initial=0.4 in,
pcbdipheight/.initial=0.1 in,
pcbdipnudge/.initial=0.05 in,
pcbcircleout/.initial=0.03 in,
pcbcirclein/.initial=0.015 in,
pcbcirclediff/.initial=0.1 in
}
\pgfdeclareshape{pcbbase} {
\savedanchor\centerpoint{
\pgf@x=.5\wd\pgfnodeparttextbox
\pgf@y=.5\ht\pgfnodeparttextbox
\advance\pgf@y by-.5\dp\pgfnodeparttextbox
}
\saveddimen\halfwidth{%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%
\pgf@x=0.5\pgf@xb
}
\saveddimen\halfheight{
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%
\pgf@x=0.5\pgf@yb
}
\saveddimen\radius{%
\pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}%
\pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}%
\pgf@x=.5\pgf@xb%
\pgf@x=.5\pgf@yb%
}
\anchor{center}{\centerpoint}
\anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}}
\anchor{base}{\centerpoint\pgf@y=0pt}
\anchor{north}{\centerpoint\advance\pgf@y by\halfheight}
\anchor{south}{\centerpoint\advance\pgf@y by-\halfheight}
\anchor{west}{\centerpoint\advance\pgf@x by-\halfwidth}
\anchor{east}{\centerpoint\advance\pgf@x by\halfwidth}
\anchor{midwest}{\centerpoint\pgfutil@tempdima=\halfwidth\advance\pgf@x by-0.85\pgfutil@tempdima}
}
\pgfdeclareshape{pcbdip} {
\inheritsavedanchors[from=pcbbase]
\inheritanchor[from=pcbbase]{center}
\inheritanchor[from=pcbbase]{mid}
\inheritanchor[from=pcbbase]{base}
\inheritanchor[from=pcbbase]{north}
\inheritanchor[from=pcbbase]{south}
\inheritanchor[from=pcbbase]{west}
\inheritanchor[from=pcbbase]{east}
\inheritanchor[from=pcbbase]{midwest}
\savedmacro\halfpins{%
\pgfmathdivide{\pgfkeysvalueof{/pgf/pcbpins}}{2}
\let\halfpins\pgfmathresult
}
\saveddimen\circlein{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbcirclein}}}
\saveddimen\circleout{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbcircleout}}}
\saveddimen\circlediff{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbcirclediff}}}
\saveddimen\dipdx{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbdipdx}}}
\saveddimen\dipwidth{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbdipwidth}}}
\saveddimen\dipheight{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbdipheight}}}
\saveddimen\dipnudge{\pgfmathsetlength{\pgf@x}{\pgfkeysvalueof{/pgf/pcbdipnudge}}}
\backgroundpath{
\pgfseteorule
\pgfutil@tempdima=\circlein
\pgfutil@tempdimb=\circleout
\pgfutil@tempdimc=\circlediff
\pgfutil@tempdimd=\dipdx
\pgfutil@tempdime=0.5\pgfutil@tempdimc
\pgfmathloop
\ifnum\pgfmathcounter>\halfpins
\else
\advance\pgfutil@tempdime by -0.5\pgfutil@tempdimc
\repeatpgfmathloop
\fi
\pgfutil@tempdimf=\dipheight
\pgfutil@tempdimg=\dipwidth
\pgfutil@tempdimh=\dipnudge
\pgfmathloop
\ifnum\pgfmathcounter>\halfpins %pins
\else
\centerpoint\advance\pgf@x by-0.5\pgfutil@tempdimd\advance\pgf@y by\pgfutil@tempdime\pgfpathcircle{\pgfpoint{\pgf@x}{\pgf@y}}{\pgfutil@tempdima}
\centerpoint\advance\pgf@x by-0.5\pgfutil@tempdimd\advance\pgf@y by\pgfutil@tempdime\pgfpathcircle{\pgfpoint{\pgf@x}{\pgf@y}}{\pgfutil@tempdimb}
\centerpoint\advance\pgf@x by0.5\pgfutil@tempdimd\advance\pgf@y by\pgfutil@tempdime\pgfpathcircle{\pgfpoint{\pgf@x}{\pgf@y}}{\pgfutil@tempdima}
\centerpoint\advance\pgf@x by0.5\pgfutil@tempdimd\advance\pgf@y by\pgfutil@tempdime\pgfpathcircle{\pgfpoint{\pgf@x}{\pgf@y}}{\pgfutil@tempdimb}
\advance\pgfutil@tempdime by\pgfutil@tempdimc
\repeatpgfmathloop
\fi
\color{gray}
\pgfusepath{fill}
\pgfsetlinewidth{2\pgflinewidth}
\advance\pgfutil@tempdime by-\pgfutil@tempdimc
\advance\pgfutil@tempdime by0.5\pgfutil@tempdimf
\centerpoint\advance\pgf@x by-0.5\pgfutil@tempdimg\advance\pgf@y by\pgfutil@tempdime\pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
\centerpoint\advance\pgf@x by-\pgfutil@tempdimh\advance\pgf@y by\pgfutil@tempdime\pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}\pgfpatharc{-180}{0}{\pgfutil@tempdimh and \pgfutil@tempdimh}
\centerpoint\advance\pgf@x by0.5\pgfutil@tempdimg\advance\pgf@y by\pgfutil@tempdime\pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
\centerpoint\advance\pgf@x by0.5\pgfutil@tempdimg\advance\pgf@y by-\pgfutil@tempdime\pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
\centerpoint\advance\pgf@x by-0.5\pgfutil@tempdimg\advance\pgf@y by-\pgfutil@tempdime\pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}\pgfpathclose
\color{black}
\pgfusepath{stroke}
% Draw port labels
\begingroup
\tikzset{pcb/part labels} % Use font from this style
\tikz@textfont
\centerpoint
\pgftext[at={\pgfpoint{\pgf@x}{\pgf@y}},rotate=-90]{\raisebox{-0.75ex}{\pgfkeysvalueof{/pgf/pcblabel}}}
\endgroup
}
}
与main.tex
文件:
\documentclass{article}
\usepackage{tikz}
\makeatletter
\input{shapes}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[shape=pcbdip,pcbpins=20] (DIP) at (0,0) {};
\draw (DIP.pin0) -- (DIP.pin18);
\end{tikzpicture}
\end{document}
如您所见,可以设置该pcbpins
值以便为任意数量的引脚生成 DIP 封装形状。
我们希望根据此参数定义锚点,这样如果指定20
引脚,就可以访问节点的锚点DIP.pin0
。DIP.pin20
如何定义?我们知道这是可能的,因为这适用于与门。
答案1
各种形状库中都相当多地实现了这种功能。它不一定简单,有些人可能找到了更简单的方法,但下面说明了使用的一般技术。
\documentclass[tikz,border=5]{standalone}
\pgfkeys{/pgf/.cd,
box pins/.initial=1,
}
\makeatletter
% A very simple shape
\pgfdeclareshape{box}{
\nodeparts{}
\saveddimen\halfwidth{%
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/minimum width}/2}%
}
\saveddimen\halfheight{%
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/minimum height}/2}%
}
\savedmacro\boxpins{%
\pgfmathparse{int(\pgfkeysvalueof{/pgf/box pins})}%
\let\boxpins=\pgfmathresult
}
\savedanchor\centerpoint{\pgfpointorigin}
\anchor{center}{\centerpoint}
\backgroundpath{%
\pgfpathrectanglecorners{\pgfqpoint{-\halfwidth}{-\halfheight}}%
{\pgfqpoint{\halfwidth}{\halfheight}}
}
%
% Now add some code which will be executed
% every time a box node is created.
\pgfutil@g@addto@macro\pgf@sh@s@box{%
\pgfmathloop%
% The macro \boxpins will have been defined when code is executed
\ifnum\pgfmathcounter>\boxpins\relax%
\else%
% Only add if anchor not defined yet defined.
\pgfutil@ifundefined{pgf@anchor@box@pin \pgfmathcounter}{%
% Create anchor pin X for the shape box
\expandafter\xdef\csname pgf@anchor@box@pin \pgfmathcounter\endcsname{%
\noexpand\pgf@sh@lib@box@pinanchor{\pgfmathcounter}%
}%
}{}%
\repeatpgfmathloop%
}
}
\def\pgf@sh@lib@box@pinanchor#1{%
% All the saved dimens and macros will be available
% when this macro is called.
\ifnum#1>\boxpins\relax%
% Should issue an error.
\pgfpointorigin%
\else
\pgfpoint{\halfwidth}{\halfheight*2/(\boxpins+1)*#1-\halfheight}%
\fi
}
\begin{document}
\begin{tikzpicture}[minimum size=1cm]
\foreach \b in {1,...,5}{
\node [box, box pins=\b, draw, label=center:\b] at (0,2*\b) (box-\b) {};
\foreach \p in {1,...,\b}
\draw (2,2*\b) -- (box-\b.pin \p);
}
% box-1 does not have a pin 5 anchor
\draw [red] (2,3) -- (box-1.pin 5);
\end{tikzpicture}
\end{document}