% 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. \def\pgf@circ@direction{0.0} % swap two coordinates \def\pgfcirc@swap@coordinates#1#2{% coordinate (pgfcirc@tmp@swap) at (#1) coordinate (#1) at (#2) coordinate (#2) at (pgfcirc@tmp@swap) } % Names \ctikzset{name/.style = { n={#1} } } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@@@ \ctikzset{n/.code = { \pgfkeys{/tikz/circuitikz/bipole/name={#1}} }} % Reflect the node along \ctikzset{mirrored/.is choice} \ctikzset{mirror value/.initial=1} \ctikzset{mirrored/true/.code = {\ctikzsetvalof{mirror value}{-1}} } \ctikzset{mirrored/false/.code = {\ctikzsetvalof{mirror value}{1}} } \ctikzset{mirror/.style = {/tikz/circuitikz/mirrored=true}} % Invert node along path \ctikzset{inverted/.is choice} \ctikzset{invert value/.initial=1} \ctikzset{inverted/true/.code = {\ctikzsetvalof{invert value}{-1}\pgf@circuit@bipole@invertedtrue}} \ctikzset{inverted/false/.code = {\ctikzsetvalof{invert value}{1}\pgf@circuit@bipole@invertedfalse}} \ctikzset{invert/.style = {/tikz/circuitikz/inverted=true}} \newif\ifpgf@circuit@bipole@inverted \ctikzset{bipole/inverted/.is if=pgf@circuit@bipole@inverted} \newif\ifpgf@circuit@bipole@voltage@backward \ctikzset{bipole/voltage/direction/.is choice} \ctikzset{bipole/voltage/direction/forward/.code={\pgf@circuit@bipole@voltage@backwardfalse}} \ctikzset{bipole/voltage/direction/backward/.code={\pgf@circuit@bipole@voltage@backwardtrue}} % Initialize paths \def\pgfcircresetpath{ \ctikzset{bipole/name=, bipole/label/name=, bipole/label/position=90, ,bipole/annotation/name=, bipole/annotation/position=-90, bipole/inverted=false, bipole/kind=, bipole/voltage/direction=backward, bipole/voltage/label/name=, bipole/voltage/position=below, bipole/nodes/left=none, bipole/nodes/right=none, bipole/is voltage=false,bipole/is voltageoutsideofsymbol=false,bipole/is strokedsymbol=false, bipole/is current=false, bipole/current/label/name=, bipole/current/x position=after, bipole/current/y position=above, bipole/current/direction=forward, mirrored=false } } % % expandable IF for the extra nodes (thanks to Henri Menke) % see https://chat.stackexchange.com/transcript/message/56560808#56560808 % \def\pgfcirc@if@has@i{% \ifpgfcirc@has@i \expandafter\pgfutil@firstoftwo \else \expandafter\pgfutil@secondoftwo \fi} \def\pgfcirc@if@has@v{% \ifpgfcirc@has@v \expandafter\pgfutil@firstoftwo \else \expandafter\pgfutil@secondoftwo \fi} \def\pgfcirc@if@has@f{% \ifpgfcirc@has@f \expandafter\pgfutil@firstoftwo \else \expandafter\pgfutil@secondoftwo \fi} %% Generic bipole path \def\pgf@circ@bipole@path#1#2{ % Create a bipole path from the shapes defined with \pgfcircdeclarebipole % or \pgfcircdeclarebipolescaled; the node shapes are named with a "shape" % appended to the main (path-style) name % #1 path-style node name % #2 the argument passed from the to-path structure; don't touch % % Example: % \def\pgf@circ@capacitor@path#1{\pgf@circ@bipole@path{capacitor}{#1}} % \pgf@circ@bipole@path@base{shape}{}{#1}{#2} } %% %% ultra-generic bipole path %% I am not sure what the last argument is needed for, but don't touch it or everything explodes %% \def\pgf@circ@bipole@path@base#1#2#3#4{% % % Create a path-style component based on a node-style shape % #1: postfix to be added to the name path to obtain the main shape name % #2: text to be passed as text to the node % #3: name of the bipole component % #4: this will be filled by the argument of the to-path % \pgfextra{ \ctikzset{bipole/kind = #3} \edef\pgf@temp{\ctikzvalof{bipole/name}} \def\pgf@circ@temp{} \ifx\pgf@temp\pgf@circ@temp % if it has not a name \pgfmathrandominteger{\pgf@circ@rand}{1000}{9999} \ctikzset{bipole/name = pgfcirc@#3\pgf@circ@rand} % create it (re-usage should not create problem, but...) \edef\pgfcirc@a@prefix{pgfcirc}% do not pollute the namespace for nothing \else \edef\pgfcirc@a@prefix{\ctikzvalof{bipole/name}}% for exporting v-i-f anchors \fi } % save start and stop values % notice that we DO NOT MOVE the path position at all! coordinate (\ctikzvalof{bipole/name}start) at (\tikztostart) coordinate (\ctikzvalof{bipole/name}end) at (\tikztotarget) \pgfextra{ % find the direction (angle) of the path \pgfmathanglebetweenpoints{\pgfpointanchor{\ctikzvalof{bipole/name}start}{center}} {\pgfpointanchor{\ctikzvalof{bipole/name}end}{center}} \edef\pgf@circ@direction{\pgfmathresult} \expandafter\xdef\csname pgfcirc@\pgfcirc@a@prefix-direction\endcsname{\pgf@circ@direction} } % position the component in the middle of the path. We DO NOT MOVE the current position! node[#3#1, rotate=\pgf@circ@direction, yscale=\ctikzvalof{mirror value}, xscale=\ctikzvalof{invert value}] (\ctikzvalof{bipole/name}) at ($(\tikztostart) ! .5 ! (\tikztotarget)$) {#2} % set start and end labels \ifpgf@circuit@bipole@inverted \ifcsname pgf@anchor@#3#1@pathstart\endcsname%if special path-anchors are defined, use them! coordinate (pgfcirc@anchorstartnode) at (\ctikzvalof{bipole/name}.pathend) coordinate (pgfcirc@anchorendnode) at (\ctikzvalof{bipole/name}.pathstart) \else coordinate (pgfcirc@anchorstartnode) at (\ctikzvalof{bipole/name}.right) coordinate (pgfcirc@anchorendnode) at (\ctikzvalof{bipole/name}.left) \fi \else \ifcsname pgf@anchor@#3#1@pathstart\endcsname%if special path-anchors are defined, use them! coordinate (pgfcirc@anchorstartnode) at (\ctikzvalof{bipole/name}.pathstart) coordinate (pgfcirc@anchorendnode) at (\ctikzvalof{bipole/name}.pathend) \else coordinate (pgfcirc@anchorstartnode) at (\ctikzvalof{bipole/name}.left) coordinate (pgfcirc@anchorendnode) at (\ctikzvalof{bipole/name}.right) \fi \fi % draw the leads unless it's an open circuit % stop at the component \pgfextra{\def\pgf@temp{open}\def\pgf@circ@temp{#3}} \ifx\pgf@temp\pgf@circ@temp % if it is an open do nothing \else % it is important to start the path with -- to have correct line joins! -- (\tikztostart) -- (pgfcirc@anchorstartnode) \fi % Add all the "ornaments": labels, annotations, voltages, currents and flows \drawpoles \pgf@circ@ifkeyempty{bipole/label/name}\else\pgf@circ@drawlabels{label}\fi \pgf@circ@ifkeyempty{bipole/annotation/name}\else\pgf@circ@drawlabels{annotation}\fi % the following must be made in their own path scope to avoid crash in TikZ 3.1.8/3.1.8a % it should be logically safe for older version too --- even if TikZ reverted the change % use explandable ifs too, thanks to Henri Menke {\pgfcirc@if@has@v{\pgf@circ@drawvoltage}{}}% {\pgfcirc@if@has@i{\pgf@circ@drawcurrent}{}}% {\pgfcirc@if@has@f{\pgf@circ@drawflow}{}}% % finish the path from the component to the final target % you never know --- re-set \pgf@temp to detect open \pgfextra{\def\pgf@temp{open}\def\pgf@circ@temp{#3}} \ifx\pgf@temp\pgf@circ@temp % if it is an open do nothing (\tikztotarget) \else (pgfcirc@anchorendnode) -- (\tikztotarget) \fi % reset internal circuit keys \pgfextra{\pgfcircresetpath} %draw pending nodes an path \tikztonodes } %% Macros for path and style activation for bipoles or path-style \def\comnpatname{\ifpgf@circuit@compat *\else\fi} \def\compattikzset#1{% % \typeout{BIPOLEDEF:\space \detokenize{#1}}% \tikzset{\comnpatname#1}} % % this is used for components that are mainly node-style but have a path-style form % \def\pgfcirc@node@to@path#1#2#3{% % add a path-style component based on a node-style one without mangling the name % of the shape. % #1: node-type shape name (existing) % #2: path-type name (to be created) % #3: additional options to add to the path style % \expandafter\def\csname pgf@circ@#1@path\endcsname##1{\pgf@circ@bipole@path@base{}{##1}{#1}{}}% \compattikzset{#2/.style = {\circuitikzbasekey, /tikz/to path=\csname pgf@circ@#1@path\endcsname{##1}, #3}}% \ctikzset{bipoles/#1/height/.initial=1}% } % % this one is for normal definition: path to style, directly % the first parameter (#1) here is l,v,i (l=..., v=..., i=...) % the last parameter are options to be inserted in the "to path" definition % \def\pgfcirc@path@to@style#1#2#3#4{% using #1 as label, assign \pgf@circ@#2@path to style #3 \compattikzset{#3/.style={\circuitikzbasekey, #4, /tikz/to path=\csname pgf@circ@#2@path\endcsname, #1={##1}}}% } % this one create a alias style from a node definition \def\pgfcirc@node@to@style#1#2#3#4{% using #1 as label, assign \pgf@circ@bipole@path{#2} to style #3 \compattikzset{#3/.style={\circuitikzbasekey, #4, /tikz/to path=\pgf@circ@bipole@path{#2}, #1={##1}}}% } % this create an alias style \def\pgfcirc@style@to@style#1#2{% alias style #1 to style #2 \compattikzset{#2/.style={\comnpatname #1={##1}}}% } % this create an alias style, changing the labelling \def\pgfcirc@style@to@style@label#1#2#3{% alias style #1 to style #2 \compattikzset{#2/.style={\comnpatname #1, #3={##1}}}% } % create a bipole \def\pgfcirc@activate@bipole#1#2#3#4{% path name, base node name, style name \expandafter\def\csname pgf@circ@#2@path\endcsname##1{\pgf@circ@bipole@path{#3}{##1}}% \pgfcirc@path@to@style{#1}{#2}{#4}{}% no options here, let's see } \def\pgfcirc@activate@bipole@simple#1#2{\pgfcirc@activate@bipole{#1}{#2}{#2}{#2}} % create a bipole with options \def\pgfcirc@activate@bipole@opt#1#2#3#4#5{% path name, base node name, style name \expandafter\def\csname pgf@circ@#2@path\endcsname##1{\pgf@circ@bipole@path{#3}{##1}}% \pgfcirc@path@to@style{#1}{#2}{#4}{#5}% no options here, let's see } \def\pgfcirc@activate@bipole@simple@opt#1#2#3{\pgfcirc@activate@bipole@opt{#1}{#2}{#2}{#2}{#3}} %% New system, for simple object %% \pgfcirc@activate@bipole@simple{l}{mass} %% New system, different names %% The old system is the following %% 1 - define just the pgf@circ@path@whatever#1 %% (see for example the variable one) %% 2 - set the style %% \compattikzset{resistor/.style= {\circuitikzbasekey, /tikz/to path=\pgf@circ@resistor@path, l={#1}}} %% Path definition with the new mechanism have been moved to where the nodes %% are defined. %% Handling of terminals%<<< \ctikzset{bipole/nodes/.is family} \ctikzset{bipole/nodes/left/.initial=none} \ctikzset{bipole/nodes/right/.initial=none} \tikzset{bipole nodes/.style n args={2}{% \circuitikzbasekey/bipole/nodes/left=#1, \circuitikzbasekey/bipole/nodes/right=#2 } } %% Easily usable styles \ctikzset{o-o/.style = {\circuitikzbasekey/bipole/nodes/left=ocirc, \circuitikzbasekey/bipole/nodes/right=ocirc}} \ctikzset{-o/.style = {\circuitikzbasekey/bipole/nodes/left=none, \circuitikzbasekey/bipole/nodes/right=ocirc}} \ctikzset{o-/.style = {\circuitikzbasekey/bipole/nodes/left=ocirc, \circuitikzbasekey/bipole/nodes/right=none}} \ctikzset{*-o/.style = {\circuitikzbasekey/bipole/nodes/left=circ, \circuitikzbasekey/bipole/nodes/right=ocirc}} \ctikzset{o-*/.style = {\circuitikzbasekey/bipole/nodes/left=ocirc, \circuitikzbasekey/bipole/nodes/right=circ}} \ctikzset{d-o/.style = {\circuitikzbasekey/bipole/nodes/left=diamondpole, \circuitikzbasekey/bipole/nodes/right=ocirc}} \ctikzset{o-d/.style = {\circuitikzbasekey/bipole/nodes/left=ocirc, \circuitikzbasekey/bipole/nodes/right=diamondpole}} \ctikzset{*-/.style = {\circuitikzbasekey/bipole/nodes/left=circ, \circuitikzbasekey/bipole/nodes/right=none}} \ctikzset{-*/.style = {\circuitikzbasekey/bipole/nodes/left=none, \circuitikzbasekey/bipole/nodes/right=circ}} \ctikzset{d-/.style = {\circuitikzbasekey/bipole/nodes/left=diamondpole, \circuitikzbasekey/bipole/nodes/right=none}} \ctikzset{-d/.style = {\circuitikzbasekey/bipole/nodes/left=none, \circuitikzbasekey/bipole/nodes/right=diamondpole}} \ctikzset{*-*/.style = {\circuitikzbasekey/bipole/nodes/left=circ, \circuitikzbasekey/bipole/nodes/right=circ}} \ctikzset{d-*/.style = {\circuitikzbasekey/bipole/nodes/left=diamondpole, \circuitikzbasekey/bipole/nodes/right=circ}} \ctikzset{*-d/.style = {\circuitikzbasekey/bipole/nodes/left=circ, \circuitikzbasekey/bipole/nodes/right=diamondpole}} \ctikzset{d-d/.style = {\circuitikzbasekey/bipole/nodes/left=diamondpole, \circuitikzbasekey/bipole/nodes/right=diamondpole}} % rectjoinfill workarounds \ctikzset{.-/.style = {\circuitikzbasekey/bipole/nodes/left=rectjoinfill, \circuitikzbasekey/bipole/nodes/right=none}} \ctikzset{.-*/.style = {\circuitikzbasekey/bipole/nodes/left=rectjoinfill, \circuitikzbasekey/bipole/nodes/right=circ}} \ctikzset{.-o/.style = {\circuitikzbasekey/bipole/nodes/left=rectjoinfill, \circuitikzbasekey/bipole/nodes/right=ocirc}} \ctikzset{.-d/.style = {\circuitikzbasekey/bipole/nodes/left=rectjoinfill, \circuitikzbasekey/bipole/nodes/right=diamondpole}} \ctikzset{-./.style = {\circuitikzbasekey/bipole/nodes/left=none, \circuitikzbasekey/bipole/nodes/right=rectjoinfill}} \ctikzset{o-./.style = {\circuitikzbasekey/bipole/nodes/left=ocirc, \circuitikzbasekey/bipole/nodes/right=rectjoinfill}} \ctikzset{*-./.style = {\circuitikzbasekey/bipole/nodes/left=circ, \circuitikzbasekey/bipole/nodes/right=rectjoinfill}} \ctikzset{d-./.style = {\circuitikzbasekey/bipole/nodes/left=diamondpole, \circuitikzbasekey/bipole/nodes/right=rectjoinfill}} \ctikzset{.-./.style = {\circuitikzbasekey/bipole/nodes/left=rectjoinfill, \circuitikzbasekey/bipole/nodes/right=rectjoinfill}} \tikzset{reversed/.style = {\circuitikzbasekey/bipole/inverted=true}} \def\drawpoles{ \pgfextra{ \edef\pgf@circ@temp{\ctikzvalof{bipole/nodes/left}} \def\pgf@temp{none}} \ifx\pgf@temp\pgf@circ@temp\else(\tikztostart) node[\pgf@circ@temp] {}\fi \pgfextra{ \edef\pgf@circ@temp{\ctikzvalof{bipole/nodes/right}} } \ifx\pgf@temp\pgf@circ@temp\else(\tikztotarget) node[\pgf@circ@temp] {}\fi } % %>>> %% %% Definition of path for transistors %% % Transistor like bipoles \def\pgf@circ@trans@path#1#2{ \pgfextra{ \edef\pgf@temp{\ctikzvalof{bipole/name}} \def\pgf@circ@temp{#2} \ifx\pgf@temp\pgf@circ@temp % if it has not a name \pgfmathrandominteger{\pgf@circ@rand}{1000}{9999} \ctikzset{bipole/name = trans\pgf@circ@rand} % create it \fi } \ifpgf@circuit@bipole@inverted (\tikztostart) node[coordinate] (\ctikzvalof{bipole/name}end) {} (\tikztotarget) node[coordinate] (\ctikzvalof{bipole/name}start) {} \else (\tikztostart) node[coordinate] (\ctikzvalof{bipole/name}start) {} (\tikztotarget) node[coordinate] (\ctikzvalof{bipole/name}end) {} \fi \pgfextra{ \pgfmathanglebetweenpoints{\pgfpointanchor{\ctikzvalof{bipole/name}start}{center}} {\pgfpointanchor{\ctikzvalof{bipole/name}end}{center}} \pgfmathadd{\pgfmathresult}{-90} \pgfmathround{\pgfmathresult} \edef\pgf@circ@direction{\pgfmathresult} } ($(\tikztostart) ! .5 ! (\tikztotarget)$) node[#1, /tikz/rotate=\pgf@circ@direction, xscale=\ctikzvalof{mirror value}] (\ctikzvalof{bipole/name}) {} node {\ctikzvalof{bipole/label/name}} \ifcsname pgf@anchor@#1@pathstart\endcsname%if special path-anchors are defined, use them! (\ctikzvalof{bipole/name}start.center) --(\ctikzvalof{bipole/name}.pathstart) (\ctikzvalof{bipole/name}.pathend) -- (\ctikzvalof{bipole/name}end.center) \else (\ctikzvalof{bipole/name}start.center) --(\ctikzvalof{bipole/name}.left) (\ctikzvalof{bipole/name}.right) -- (\ctikzvalof{bipole/name}end.center) \fi \drawpoles \pgfextra{ \pgfcircresetpath } (\tikztotarget) \tikztonodes % and go on! } \def\pgf@circ@definetranspath#1{ \compattikzset{T#1/.style = {\circuitikzbasekey, /tikz/to path=\pgf@circ@trans@path{#1}{}, l=##1}} } % % vim: set fdm=marker fmr=%<<<,%>>>: