% Copyright 2018-2021 by Romano Giannetti % Copyright 2015-2021 by Stefan Lindner % Copyright 2013-2021 by Stefan Erhardt % Copyright 2007-2021 by Massimo Redaelli % % This file may be distributed and/or modified % % 1. under the LaTeX Project Public License and/or % 2. under the GNU Public License. % % See the files gpl-3.0_license.txt and lppl-1-3c_license.txt for more details. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Bipole label positioning %% bipole labels and annotation extra style \ctikzset{bipole label style/.style={}} \tikzset{bipole label style/.code={ \ctikzset{bipole label style/.style={#1}} }} \tikzset{bipole label append style/.code={ \ctikzset{bipole label style/.append style={#1}} }} \ctikzset{bipole annotation style/.style={}} \tikzset{bipole annotation style/.code={ \ctikzset{bipole annotation style/.style={#1}} }} \tikzset{bipole annotation append style/.code={ \ctikzset{bipole annotation style/.append style={#1}} }} \ctikzset{label distance/.initial={0pt}} \ctikzset{annotation distance/.initial={0pt}} %% Options \ctikzset{label/.style = { l={#1} } } \ctikzset{l/.code = { \pgfkeys{/tikz/circuitikz/bipole/label/name={#1}} \ctikzsetvalof{bipole/label/unit}{} \ifpgf@circ@siunitx \pgf@circ@handleSI{#1} \ifpgf@circ@siunitx@res \edef\pgf@temp{\pgf@circ@handleSI@val} \pgfkeyslet{/tikz/circuitikz/bipole/label/name}{\pgf@temp} \edef\pgf@temp{\pgf@circ@handleSI@unit} \pgfkeyslet{/tikz/circuitikz/bipole/label/unit}{\pgf@temp} \else \fi \else \fi }} \ctikzset{label above/.code = { l={#1}, \circuitikzbasekey/bipole/label/position=90 } } \ctikzset{l^/.style = { l={#1}, \circuitikzbasekey/bipole/label/position=90 } } \ctikzset{label below/.code = { l={#1}, \circuitikzbasekey/bipole/label/position=-90 } } \ctikzset{l_/.style = { l={#1}, \circuitikzbasekey/bipole/label/position=-90 } } \ctikzset{annotation/.style = { a={#1} } } \ctikzset{a/.code = { \pgfkeys{/tikz/circuitikz/bipole/annotation/name={#1}} \ctikzsetvalof{bipole/annotation/unit}{} \ifpgf@circ@siunitx \pgf@circ@handleSI{#1} \ifpgf@circ@siunitx@res \edef\pgf@temp{\pgf@circ@handleSI@val} \pgfkeyslet{/tikz/circuitikz/bipole/annotation/name}{\pgf@temp} \edef\pgf@temp{\pgf@circ@handleSI@unit} \pgfkeyslet{/tikz/circuitikz/bipole/annotation/unit}{\pgf@temp} \else \fi \else \fi }} \ctikzset{annotation above/.code = { a={#1}, \circuitikzbasekey/bipole/annotation/position=90 } } \ctikzset{a^/.style = { a={#1}, \circuitikzbasekey/bipole/annotation/position=90 } } \ctikzset{annotation below/.code = { a={#1}, \circuitikzbasekey/bipole/annotation/position=-90 } } \ctikzset{a_/.style = { a={#1}, \circuitikzbasekey/bipole/annotation/position=-90 } } % This is to adjust spacing for the labels so that they are not cramped on components \def\pgf@circ@ls{.75ex} % labelspace to have just one point to change \def\pgf@circ@drawlabels#1{ \pgfextra{ % This function will be called with argument #1 equal % to "label" or "annotation" form pgfcircpath.tex. % pgf@circ@direction is the direction of the path, % its value is set in pgfcircpath.tex \pgfmathsubtract{\pgf@circ@direction}{90} \pgfmathround{\pgfmathresult} % avoid precision loss errors \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} \edef\pgf@circ@temp{\ctikzvalof{bipole/#1/position}} \ifnum \pgf@circ@temp < 0 \pgfmathadd{\pgf@circ@labanc}{180} \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} \fi % \typeout{INI: TEMP\space\pgf@circ@temp\space LABANC\space\pgf@circ@labanc} % % normalize the angle values % \pgfmathmod{\pgf@circ@labanc}{360} \edef\pgf@circ@labanc{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} % \ifpgf@circuit@bipole@inverted \pgfmathadd{\pgf@circ@temp}{180} %If shape is inverted, use opposite anchor \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} \fi % \ifnum \ctikzvalof{mirror value} = -1 \pgfmathadd{\pgf@circ@temp}{180} %If shape is mirrored, use opposite anchor \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} \fi % \typeout{FIN: TEMP\space\pgf@circ@temp\space LABANC\space\pgf@circ@labanc} } %Firstly, place a coordinate directly at the edge of the shape (\ctikzvalof{bipole/name}.\pgf@circ@temp) coordinate (pgfcirc@labelcoor) %now decide, which labels should be drawn \pgfextra{ \edef\pgf@temp{\ctikzvalof{label/align}} \def\pgf@circ@temp{straight} } \ifx\pgf@temp\pgf@circ@temp %straight \pgf@circ@drawreglabels{#1} \else \pgfextra{\def\pgf@circ@temp{rotate}} \ifx\pgf@temp\pgf@circ@temp %rotate \pgf@circ@drawrotlabels{#1} \else% smart \pgf@circ@drawsmartlabels{#1} \fi \fi } \def\pgf@circ@drawsmartlabels#1{ \pgfextra{ \pgfmathmod{\pgf@circ@direction}{90} \edef\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} } \ifnum \pgfcircmathresult > 20 \ifnum \pgfcircmathresult < 70 \pgf@circ@drawrotlabels{#1} \else \pgf@circ@drawreglabels{#1} \fi \else \pgf@circ@drawreglabels{#1} \fi } \def\pgf@circ@drawrotlabels#1{ \pgfextra{ % scale the distances in function of zoom, so that they are not % dependent on it but on font size. Thanks to @marmot % https://tex.stackexchange.com/a/476018/38080 % the coefficient is adjusted so that the distance is more or less % the same for rotated labels and straight ones (although it will % depend on the font, so it's not exact). \pgfgettransformentries{\tmpa}{\tmpb}{\tmpc}{\tmpd}{\tmp}{\tmp}% \pgfmathsetmacro{\myscale}{sqrt(abs(\tmpa*\tmpd-\tmpb*\tmpc))}% abs should not be needed % \typeout{ROT\tmpa\space\tmpb\space\tmpc\space\tmpd\space\myscale} \pgfmathsetlength\pgf@circ@res@temp{1.5*\pgf@circ@ls/\myscale+\ctikzvalof{#1 distance}/\myscale} \ifnum \ctikzvalof{bipole/#1/position}>0 %we need some more space for placement below, due to mid-anchor \else % we do not have <= in \ifnum... \pgf@circ@res@temp=1.5\pgf@circ@res@temp \fi %Calculate rotation of the label from direction and strip decimals \pgfmathsetmacro{\pgfcirclabrot}{round(\pgf@circ@direction)} \edef\pgfcirclabrot{\expandafter\pgf@circ@stripdecimals\pgfcirclabrot\pgf@nil} % rotate the label at second or third quadrant: \ifnum \pgfcirclabrot > 90 \ifnum \pgfcirclabrot < 270 \pgfmathsubtract{\pgf@circ@direction}{180} \edef\pgfcirclabrot{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} %invert the space relationships due to rotated strings \ifnum \ctikzvalof{bipole/#1/position}>0 \pgf@circ@res@temp=1.5\pgf@circ@res@temp \fi \fi\fi \pgfmathparse{\ctikzvalof{bipole/#1/position}>0?\pgf@circ@direction+90:\pgf@circ@direction-90}% \edef\pgf@circ@labposangle{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil}% \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix#1-direction\endcsname{\pgfcirclabrot}% \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix-#1-anchor\endcsname{mid}% } % reset cm is not working correctly here (pgfcirc@labelcoor)++(\pgf@circ@labposangle:\the\pgf@circ@res@temp) coordinate(pgfcirc@labelcoor) node[anchor=mid, rotate=\pgfcirclabrot, \circuitikzbasekey/bipole #1 style] (\ctikzvalof{bipole/name}#1){\pgf@circ@finallabels{#1}} } \def\pgf@circ@drawreglabels#1{ %Now calculate all shape positions %Use mid-anchor at x-axis and base-anchor at y-axis, respectively. %All points between will be addressed by angled-anchors: \pgfextra{ % scale ex-distance to make it independent on scale % thanks @marmot see https://tex.stackexchange.com/a/476018/38080 \pgfgettransformentries{\tmpa}{\tmpb}{\tmpc}{\tmpd}{\tmp}{\tmp}% \pgfmathsetmacro{\myscale}{sqrt(abs(\tmpa*\tmpd-\tmpb*\tmpc))}% abs should not be needed % \typeout{ROT\tmpa\space\tmpb\space\tmpc\space\tmpd\space\myscale} \pgfmathsetlength\pgf@circ@res@temp{\pgf@circ@ls/\myscale+\ctikzvalof{#1 distance}/\myscale} \pgfmathadd{\pgf@circ@labanc}{90} \pgfmathround{\pgfmathresult} \def\pgf@circ@labanctext{\pgf@circ@labanc} \edef\pgf@circ@temp{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} \pgfmathparse{mod(\pgf@circ@temp,180)>135?mod(\pgf@circ@temp,180)-180:mod(\pgf@circ@temp,180)} \edef\pgfcircmathresult{\expandafter\pgf@circ@stripdecimals\pgfmathresult\pgf@nil} } %Values around 90 are at both y-axis \ifnum \pgfcircmathresult > 84 \ifnum \pgfcircmathresult< 96 \pgfextra{\edef\pgf@circ@labpos{\expandafter\pgf@circ@stripdecimals\pgf@circ@direction\pgf@nil}} \ifnum \pgf@circ@labpos > 180 \ifnum \ctikzvalof{bipole/#1/position} > 0 \pgfextra{\def\pgf@circ@labanctext{mid west}} \else \pgfextra{\def\pgf@circ@labanctext{mid east}} \fi \else \ifnum \ctikzvalof{bipole/#1/position} > 0 \pgfextra{\def\pgf@circ@labanctext{mid east}} \else \pgfextra{\def\pgf@circ@labanctext{mid west}} \fi \fi \fi\fi %Values between -5 and 5 are at pos /neg x-axis \ifnum \pgfcircmathresult <6 \ifnum \pgfcircmathresult > -6 \ifnum \ctikzvalof{bipole/#1/position} < 0 \ifnum \pgf@circ@labanc > 90 % using base coordinate instead of south to naturally align % symbols with descendants; but this invalidate the effect of % the inner sep, so recover it by shifting the anchor % reset cm is not working sometime, use @marmot solution % see https://tex.stackexchange.com/a/476018/38080 (pgfcirc@labelcoor) ++(-\pgf@circ@labanc:\pgf@circ@res@temp) coordinate(pgfcirc@labelcoor) \pgfextra{\def\pgf@circ@labanctext{base}}%base \else \pgfextra{\def\pgf@circ@labanctext{north}}%north \fi \else \ifnum \pgf@circ@labanc < 90 % shift, as above (pgfcirc@labelcoor) ++(-\pgf@circ@labanc:\pgf@circ@res@temp) coordinate(pgfcirc@labelcoor) \pgfextra{\def\pgf@circ@labanctext{base}}%base \else \ifnum \pgf@circ@labanc > 180 % this shouldn't happen, but somehow it does (270 degree anchors) % shift, as above (pgfcirc@labelcoor) ++(-\pgf@circ@labanc:\pgf@circ@res@temp) coordinate(pgfcirc@labelcoor) \pgfextra{\def\pgf@circ@labanctext{base}}%base \else \pgfextra{\def\pgf@circ@labanctext{north}}%north \fi \fi \fi \fi\fi \pgfextra{% \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix#1-direction\endcsname{0}% \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix-#1-anchor\endcsname{\pgf@circ@labanctext}% } (pgfcirc@labelcoor) node[anchor=\pgf@circ@labanctext, inner sep=0.5\pgf@circ@res@temp, outer sep=0pt, \circuitikzbasekey/bipole #1 style, ](\ctikzvalof{bipole/name}#1){\strut\pgf@circ@finallabels{#1}% } } \def\pgf@circ@finallabels#1{% \edef\pgf@temp{}% \edef\pgf@circ@temp{\ctikzvalof{bipole/#1/unit}}% \ifx\pgf@temp\pgf@circ@temp% \ctikzvalof{bipole/#1/name}% \else% $\SI{\ctikzvalof{bipole/#1/name}}{\ctikzvalof{bipole/#1/unit}}$% \fi% } %%%% Stacked labels % % stacked labels by Romano Giannetti romano@rgtti.com % heavily based on Claudo Fiandrinos's https://tex.stackexchange.com/a/65792/38080 % \expandafter trick inspired by Matthew Leingang's https://tex.stackexchange.com/a/12272/38080 % % labels are in a tabular, globally aligned: % vertically with key l2 valign (default c) % c: center t: top b: bottom % horizontally with key l2 align (default l) % l: left c: centered r: right % you can switch sides using l2_=... and l2^=... % syntax is l2_ = line1 and line2 (same for l2^) % \ctikzset{% l2 valign/.store in=\pgfcirc@ltwo@valign, l2 valign=c, l2 halign/.store in=\pgfcirc@ltwo@halign, l2 halign=l, } \ctikzset{l2base/.code n args={2}{ \pgfkeys{/tikz/circuitikz/bipole/label/name=% \bgroup \setlength{\tabcolsep}{2pt}% \def\pgfcirc@ltwo@tabu{\tabular[\pgfcirc@ltwo@valign]}% \expandafter\pgfcirc@ltwo@tabu\expandafter{\pgfcirc@ltwo@halign}% #1\\ #2% \endtabular \egroup }% }} \ctikzset{l2/.style args={#1and#2}{ l2base={#1}{#2}, \circuitikzbasekey/bipole/label/position=90 } } \ctikzset{l2 above/.style args={#1and#2}{ l2base={#1}{#2}, \circuitikzbasekey/bipole/label/position=90 } } \ctikzset{l2^/.style args={#1and#2}{ l2base={#1}{#2}, \circuitikzbasekey/bipole/label/position=90 } } \ctikzset{l2 below/.style args={#1and#2}{ l2base={#1}{#2}, \circuitikzbasekey/bipole/label/position=-90 } } \ctikzset{l2_/.style args={#1and#2}{ l2base={#1}{#2}, \circuitikzbasekey/bipole/label/position=-90 } } % % the same for annotations % \ctikzset{% a2 valign/.store in=\pgfcirc@atwo@valign, a2 valign=c, a2 halign/.store in=\pgfcirc@atwo@halign, a2 halign=r, } \ctikzset{a2base/.code n args={2}{ \pgfkeys{/tikz/circuitikz/bipole/annotation/name=% \bgroup \setlength{\tabcolsep}{2pt}% \def\pgfcirc@atwo@tabu{\tabular[\pgfcirc@atwo@valign]}% \expandafter\pgfcirc@atwo@tabu\expandafter{\pgfcirc@atwo@halign}% #1\\ #2% \endtabular \egroup }% }} \ctikzset{a2/.style args={#1and#2}{ a2base={#1}{#2}, \circuitikzbasekey/bipole/annotation/position=-90 } } \ctikzset{a2 above/.style args={#1and#2}{ a2base={#1}{#2}, \circuitikzbasekey/bipole/annotation/position=-90 } } \ctikzset{a2^/.style args={#1and#2}{ a2base={#1}{#2}, \circuitikzbasekey/bipole/annotation/position=-90 } } \ctikzset{a2 below/.style args={#1and#2}{ a2base={#1}{#2}, \circuitikzbasekey/bipole/annotation/position=90 } } \ctikzset{a2_/.style args={#1and#2}{ a2base={#1}{#2}, \circuitikzbasekey/bipole/annotation/position=90 } } \endinput