![是否存在一种机制可以提供尺寸或比例作为符号实例的输入?](https://linux22.com/image/271490/%E6%98%AF%E5%90%A6%E5%AD%98%E5%9C%A8%E4%B8%80%E7%A7%8D%E6%9C%BA%E5%88%B6%E5%8F%AF%E4%BB%A5%E6%8F%90%E4%BE%9B%E5%B0%BA%E5%AF%B8%E6%88%96%E6%AF%94%E4%BE%8B%E4%BD%9C%E4%B8%BA%E7%AC%A6%E5%8F%B7%E5%AE%9E%E4%BE%8B%E7%9A%84%E8%BE%93%E5%85%A5%EF%BC%9F.png)
我意识到,符号在设计上主要具有静态特征。注释是例外。符号的特定实例可能具有与其关联的属性值,这些属性值在实例之间是可变的。例如,电阻器在实例之间的背景路径上具有相同的线,但我们可以通过字符串指示不同的值,财产=价值 单元,放置在一个节点上。
我想创建一个类似电阻器的符号,它有两个部分;主体通过垂直线简单地分为两个部分。但是,我希望能够调整垂直线的相对水平位置,以便可以改变隔间的相对宽度。我不知道有什么机制可以允许将比例值传递给符号的特定实例。也许我们可以用调整符号整体大小的相同方式调整垂直线/分隔线的位置。
代码:
\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\usetikzlibrary{circuits,circuits.ee.IEC}
\makeatletter
\pgfdeclareshape{symbol shape}{%
\inheritsavedanchors[from=rectangle ee]
\inheritanchor[from=rectangle ee]{center}
\inheritanchor[from=rectangle ee]{north}
\inheritanchor[from=rectangle ee]{south}
\inheritanchor[from=rectangle ee]{east}
\inheritanchor[from=rectangle ee]{west}
\inheritanchor[from=rectangle ee]{north east}
\inheritanchor[from=rectangle ee]{north west}
\inheritanchor[from=rectangle ee]{south east}
\inheritanchor[from=rectangle ee]{south west}
\inheritanchor[from=rectangle ee]{input}
\inheritanchor[from=rectangle ee]{output}
\inheritanchorborder[from=rectangle ee]
\inheritbackgroundpath[from=rectangle ee]
\behindbackgroundpath{%
\pgf@process{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}%
\pgf@xa\pgf@x\pgf@ya\pgf@y
\pgf@process{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}%
\pgf@xb\pgf@x\pgf@yb\pgf@y
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{0pt}}%
\pgfpathlineto{\pgfqpoint{1.5\pgf@xa}{0pt}}%
\pgfpathmoveto{\pgfqpoint{\pgf@xb}{0pt}}%
\pgfpathlineto{\pgfqpoint{1.5\pgf@xb}{0pt}}%
\pgfpathmoveto{\pgfqpoint{0pt}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{0pt}{\pgf@yb}}%
}
}
\makeatother
\tikzset{
circuit declare symbol=symbol,
set symbol graphic={
shape=symbol shape,
draw,
transform shape,
circuit symbol size=width 8.12936 height 2.03233,
}
}
\begin{document}
\begin{tikzpicture}[circuit ee IEC]
\node[symbol] at (0,0) (thesymbol) {};
\end{tikzpicture}
\end{document}
垂直分隔线目前由以下代码定义:
\pgfpathmoveto{\pgfqpoint{0pt}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{0pt}{\pgf@yb}}%
\pgfqpoint 命令的 x-component/first 参数是我感兴趣的变量。适当的下限和上限是 \pgf@xa 和 \pgf@xb。
请注意,此处的代码主要由论坛用户 Qrrbrbirlbel 编写,用于回答这问题。
欢迎任何建议。
答案1
以下代码使用键的值/pgf/symbol shape ratio
(初始值为.5
)来计算X垂直条的值。进行了额外的校正,以便垂直线以及水平附加线不会越过边界线,而只会接触边界线(如果使用透明度,这将受到赞赏)。我还更改了水平线的定义,使它们始终具有相同的长度(即形状宽度的四分之一)。同样,这实际上只在(可能不存在的)形状与文本一起使用的情况下才重要(如下面的示例),但这并没有真正造成伤害。
.west
我没有改变和锚点的定义.east
。额外的水平线将不会被识别为放置和连接。
作为一个小练习,我添加了三个锚点
bar north
,bar south
, 和bar center
。
它们的位置可以在下面的示例图中观察到。如果你不需要它们,你可以简单地删除命令\anchor
。
通过 定义的锚点\anchor
将在访问时计算,而不是在绘制形状时计算。对于形状rectangle
(以及通过继承我们的形状),只保存\northeast
和\southwest
锚点。其他每个锚点都可以根据这两个计算。因为symbol shape ratio
在我们访问锚点时 可能已经改变,所以bar *
我们将当前值(对于这个形状)保存在 中\savedmacro
。
补充说明一下:可以通过以下代码检查输入比率是否介于0.0
和之间。1.0
\ifdim\barratio pt<0pt\relax
% the ratio is < 0
\else\ifdim\barratio pt>1pt\relax
% the ratio is > 1
\fi
\fi
代码
\documentclass[tikz,convert=false]{standalone}
\usetikzlibrary{circuits,circuits.ee.IEC}
\makeatletter
\pgfkeys{/pgf/symbol shape ratio/.initial=.5}
\pgfdeclareshape{symbol shape}{%
\savedmacro\barratio{%
\pgfmathsetmacro\barratio{\pgfkeysvalueof{/pgf/symbol shape ratio}}%
\ifdim\barratio pt<0pt\relax
% the ratio is < 0
\else\ifdim\barratio pt>1pt\relax
% the ratio is > 1
\fi
\fi
}
\inheritsavedanchors[from=rectangle ee]
\inheritanchor[from=rectangle ee]{center}
\inheritanchor[from=rectangle ee]{north}
\inheritanchor[from=rectangle ee]{south}
\inheritanchor[from=rectangle ee]{east}
\inheritanchor[from=rectangle ee]{west}
\inheritanchor[from=rectangle ee]{north east}
\inheritanchor[from=rectangle ee]{north west}
\inheritanchor[from=rectangle ee]{south east}
\inheritanchor[from=rectangle ee]{south west}
\inheritanchor[from=rectangle ee]{input}
\inheritanchor[from=rectangle ee]{output}
\anchor{bar north}{%
\pgf@process{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}%
\pgf@xa\pgf@x
\pgf@process{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}}%
\advance\pgf@x-\pgf@xa
\advance\pgf@xa\barratio\pgf@x
\pgf@x\pgf@xa
}
\anchor{bar south}{%
\pgfmathsetmacro\pgf@tempa{\pgfkeysvalueof{/pgf/symbol shape ratio}}%
\pgf@process{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}%
\pgf@xa\pgf@x\pgf@ya\pgf@y
\pgf@process{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}}%
\advance\pgf@x-\pgf@xa
\advance\pgf@xa\barratio\pgf@x
\pgf@x\pgf@xa
\pgf@y\pgf@ya
}
\anchor{bar center}{%
\pgfmathsetmacro\pgf@tempa{\pgfkeysvalueof{/pgf/symbol shape ratio}}%
\pgf@process{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}%
\pgf@xa\pgf@x\[email protected]\pgf@y
\pgf@process{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{0pt}}}}%
\advance\pgf@x-\pgf@xa\[email protected]\pgf@y
\advance\pgf@xa\barratio\pgf@x
\pgf@x\pgf@xa
\advance\pgf@y\pgf@ya
}
\inheritanchorborder[from=rectangle ee]
\inheritbackgroundpath[from=rectangle ee]
\behindbackgroundpath{%
\pgf@process{\pgfpointadd{\southwest}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}%
\pgf@xa\pgf@x\pgf@ya\pgf@y
\pgf@process{\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\pgfkeysvalueof{/pgf/outer xsep}}{\pgfkeysvalueof{/pgf/outer ysep}}}}}%
\pgf@xb\pgf@x\pgf@yb\pgf@y
% The center point: c = .5 * (a + b)
\[email protected]\pgf@xb
\advance\pgf@xc+.5\pgf@xa
\[email protected]\pgf@yb
\advance\pgf@yc+.5\pgf@ya
% we don't want to overdraw lines and subtract/add half the line width (not affected by outer seps)
\pgfutil@tempdima\pgf@xa
\advance\[email protected]\pgflinewidth
\[email protected]\pgf@xc
\advance\[email protected]\pgf@xa
\pgfpathmoveto{\pgfqpoint{\pgfutil@tempdima}{\pgf@yc}}%
\pgfpathlineto{\pgfqpoint{\pgfutil@tempdimb}{\pgf@yc}}%
\pgfutil@tempdima\pgf@xb
\advance\pgfutil@tempdima+.5\pgflinewidth
\[email protected]\pgf@xc
\advance\[email protected]\pgf@xb
\pgfpathmoveto{\pgfqpoint{\pgfutil@tempdima}{\pgf@yc}}%
\pgfpathlineto{\pgfqpoint{\pgfutil@tempdimb}{\pgf@yc}}%
%
\advance\pgf@xb-\pgf@xa% \pgf@xb contains the width
\advance\pgf@xa\barratio\pgf@xb% left x value + ratio*width
\advance\[email protected]\pgflinewidth
\advance\[email protected]\pgflinewidth
\pgfpathmoveto{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}%
\pgfsetbuttcap
\pgfusepathqstroke
}%
}
\makeatother
\tikzset{
circuit declare symbol=symbol,
set symbol graphic={
shape=symbol shape,
draw,
transform shape,
circuit symbol size=width 8.12936 height 2.03233,
}
}
\begin{document}
\foreach \Ratio in {0,5,10,...,100,100,95,90,...,0}{% will typeset 42 pages!
\begin{tikzpicture}[circuit ee IEC]
\node[symbol, symbol shape ratio=.01*\Ratio] at (0,0) (thesymbol) {\Ratio};
\path[<-,blue] (thesymbol.bar north) edge node[above,inner sep=+0pt,at end]{\tiny\ttfamily .bar north} ++ (0,.25)
(thesymbol.bar south) edge node[below,inner sep=+0pt,at end]{\tiny\ttfamily .bar south} ++ (0,-.25);
\draw[blue] plot[mark=x,mark size=1pt] (thesymbol.bar center);
\end{tikzpicture}}
\end{document}