6

I realize that a symbol, by design, will have mostly static features. The exceptions are annotations. A particular instance of a symbol may have property values associated with it which are variable between instances. A resistor, for instance, will have the same lines on the background path between instances, but we may indicate different values by a string, property = value unit, placed at a node.

I would like to create a symbol for a resistor-like symbol which has two parts; the body is simply divided into two sections by means of a vertical line. I would, however, like to be able to adjust the relative horizontal position of the vertical line such that the relative widths of the compartments could be varied. I am not aware of a mechanism that would allow one to pass a scale value to the particular instance of the symbol. Maybe the same way we adjust the overall size of the symbol, we can adjust the position of the vertical line/divider.

Code:

\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}

The vertical separating line is currently defined by the code:

\pgfpathmoveto{\pgfqpoint{0pt}{\pgf@ya}}%
\pgfpathlineto{\pgfqpoint{0pt}{\pgf@yb}}%

The x-component/first argument of the \pgfqpoint command is what I'm interested in making variable. Appropriate lower and upper bounds are \pgf@xa and \pgf@xb.

Note that the code here was largely written by forum user Qrrbrbirlbel in an answer to this question.

Any suggestions are welcomed.

2
  • A few notes on this: You are exploiting here something about circuit shapes, namely that they do not have any text. I know, the real use-case won’t have any text, but in the case you add some, things will go wrong. (The coordinate origin in the local node coordinate system will be at the most-left position of the text’s baseline.) This can be fixed very easily. Another thing are the additional lines left and right to the shape. These will not considered part of the shape by TikZ. So if you want to connect the node as in the other question the line will … Jul 3, 2013 at 22:27
  • … simply be ignored: \draw (thesymbol.west) -- ++ (-1,1);. Yes, nit-picking at its best, but then again, I don’t know what you want to do with these shapes but if the lines simply connect to circuits’ lines I wouldn’t add those. That said, let me clarify the actual question here: Do you want to give ratio between 0 (= vertical line is at the left) and 1 (= vertical line is at the right), where .5 would result in the output you (hard-)coded? Jul 3, 2013 at 22:30

1 Answer 1

7

The following code uses the value of the key /pgf/symbol shape ratio (initial value is .5) to calculate the x value of the vertical bar. Additional correction are done so that the vertical line as well as the horizontal additional lines do not cross the border line but only touch it (this will be appreciated if transparency will be used). I also changed the definition of the horizontal lines so that they always are the same length (namely a quarter of the shape’s width). Again, this really only matters in the (probably non-existent) case the shape is used with text (as with my example below) but it doesn’t really hurt.

I have not changed the definition of the .west and .east anchor. The additional horizontal lines will not be recognized for placement and connections.

As a little exercise I have added three anchors

  • bar north,
  • bar south, and
  • bar center.

Their positions can be observed in the example image below. If you do not need them you can simply remove the \anchor commands.

Anchors that are defined via \anchor will be calculated when they are accessed and not when the shape will be drawn. For the rectangle shape (and via inheritance also our shape) only the \northeast and the \southwest anchor are saved. Every other anchor can be calculated from these two. Because the symbol shape ratio may have changed when we access the bar * anchors we save the current value (for this shape) in a \savedmacro.

As an additional note: It is possible to check whether the input ratio is between 0.0 and 1.0 by the following code.

\ifdim\barratio pt<0pt\relax
  % the ratio is < 0
\else\ifdim\barratio pt>1pt\relax
    % the ratio is > 1
  \fi
\fi

Code

\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}

Output

enter image description here

4
  • This is excellent, many thanks. I note that the value of the key /pgf/symbol shape ratio is passed as an option to the tikzpicture environment. If there were multiple instances of the symbol, they would all possess the same configuration (position of vertical bar/relative sizes of compartments). What I tried was this: 1) removed the symbol shape ratio=.01*\Ratio option at the opening of the tikzpicture environment. 2) Added the key = value option at the first node operation e.g. \node[symbol, symbol shape ratio=.01*\Ratio] at (0,0) (thesymbol) {\Ratio};.
    – John Chris
    Jul 4, 2013 at 12:12
  • I observe that the vertical line is accurately positioned, however, the positions of the anchors associated with the vertical line do not change with the value of \Ratio; they remain in the center or at the position expected when \Ratio has a value of 50.
    – John Chris
    Jul 4, 2013 at 12:12
  • I'd like to eventually convert the symbol described/illustrated above into a two-part symbol. Each compartment should have a set of anchors. I'm assuming that I should discuss this in an entirely new question, referencing this question?
    – John Chris
    Jul 4, 2013 at 12:39
  • @JohnChris I have updated my answer that fixes the ratio problem you mentioned. This was indeed a bug. I have added a short explanation why \savedmacro is needed. A two-part symbol? As in two node parts? As in “with text”? Either way, I also think this deserves a new question. Jul 4, 2013 at 14:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .