I am trying to redefine the plus and minus signs in CircuiTikz
voltage labels to have a user defined thickness. So far I have a solution that works, but it has a few quirks.
The main document:
\documentclass{standalone}
\usepackage{pgfplots}
\usepackage[american]{circuitikz}
\usepgfplotslibrary{external}
\tikzexternalize
\newcommand{\thickplusvm}{
\begin{tikzpicture}[x=0.85ex, y=0.85ex, scale=0.5]
\draw[line cap=round, line width=.95pt] (0,-1) -- (0,1);
\draw[line cap=round, line width=.95pt] (1,0) -- (-1,0);
\end{tikzpicture}
}
\newcommand{\thickminusvm}{
\begin{tikzpicture}[x=0.85ex, y=0.85ex, scale=0.5]
\draw[line cap=round, line width=.95pt, opacity=0] (0,-1) -- (0,1);
\draw[line cap=round, line width=.95pt] (1,0) -- (-1,0);
\end{tikzpicture}
}
\input{./voltagemarkers.tex}
\begin{document}
\tikzset{external/remake next}
\tikzsetnextfilename{MWE}
\begin{tikzpicture}
\draw (0,0) to[L,v=$v$] ++(2,0);
\draw (3,0) to[R, v^=$v$] ++(0,-2);
\draw[very thin, color=red]
(0,-0.2) -- ++(2,0)
(3,0) -| ++(0.2015,-0.263) ++(-.25,0) -- ++(.5,0)
(3,-2) -| ++(0.265,0.263) ++(-.25,0) -- ++(.5,0)
(0.265,0.25) -- ++(0,-1)
(1.8,0.25) -- ++(0,-1)
;
\end{tikzpicture}
\end{document}
and voltagemarkers.tex
:
\def\pgf@circ@drawvoltagegeneric{
\pgfextra{
\edef\pgf@temp{/tikz/circuitikz/bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/straight label distance}
\pgfkeysifdefined{\pgf@temp}
{
\edef\partheight{\ctikzvalof{bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/straight label distance}}
\edef\tmpdistfromline{(\partheight\pgf@circ@Rlen)}
}
{
\pgfkeysifdefined{/tikz/circuitikz/bipoles/voltage/straight label distance}
{
\edef\partheight{\ctikzvalof{bipoles/voltage/straight label distance}}
\edef\tmpdistfromline{(\partheight\pgf@circ@Rlen)}
}
{%calculate default value from part height
\edef\pgf@temp{/tikz/circuitikz/bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/height}
\pgfkeysifdefined{\pgf@temp}
{
\edef\partheight{0.5*\ctikzvalof{bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/height}}
\edef\tmpdistfromline{(\partheight\pgf@circ@Rlen+0.2\pgf@circ@Rlen)}
}
{
\edef\tmpdistfromline{(.5\pgf@circ@Rlen)} %fallback to fixed value
}
}
}
\ifnum \ctikzvalof{mirror value}=-1
\ifpgf@circuit@bipole@inverted
\ifpgf@circuit@bipole@voltage@straight
\def\distfromline{\tmpdistfromline}
\else
\def\distfromline{\ctikzvalof{voltage/distance from line}\pgf@circ@Rlen}
\fi
\else
\ifpgf@circuit@bipole@voltage@straight
\def\distfromline{-\tmpdistfromline}
\else
\def\distfromline{-\ctikzvalof{voltage/distance from line}\pgf@circ@Rlen}
\fi
\fi
\else
\ifpgf@circuit@bipole@inverted
\ifpgf@circuit@bipole@voltage@straight
\def\distfromline{-\tmpdistfromline}
\else
\def\distfromline{-\ctikzvalof{voltage/distance from line}\pgf@circ@Rlen}
\fi
\else
\ifpgf@circuit@bipole@voltage@straight
\def\distfromline{\tmpdistfromline}
\else
\def\distfromline{\ctikzvalof{voltage/distance from line}\pgf@circ@Rlen}
\fi
\fi
\fi
\ifpgf@circuit@bipole@voltage@below
\def\pgf@circ@voltage@angle{90}
\else
\def\pgf@circ@voltage@angle{-90}
\fi
\edef\pgf@temp{/tikz/circuitikz/bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/distance from node}
\pgfkeysifdefined{\pgf@temp}
{ \edef\distacefromnode{\ctikzvalof{bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/distance from node}} }
{ \edef\distacefromnode{\ctikzvalof{voltage/distance from node}} }
\edef\pgf@temp{/tikz/circuitikz/bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/bump b}
\pgfkeysifdefined{\pgf@temp}
{ \edef\bumpb{\ctikzvalof{bipoles/\pgfkeysvalueof{/tikz/circuitikz/bipole/kind}/voltage/bump b}} }
{ \edef\bumpb{\ctikzvalof{voltage/bump b}} }
}
% %\pgf@circ@Rlen/16 is equal to the length of the currarrow
coordinate (pgfcirc@midtmp) at ($(\tikztostart) ! \pgf@circ@Rlen/16 ! (anchorstartnode)$) %absolute move, minimum space is length of arrowhead
coordinate (pgfcirc@midtmp) at ($(pgfcirc@midtmp) ! \distacefromnode ! (anchorstartnode)$)
coordinate (pgfcirc@Vfrom) at ($(pgfcirc@midtmp) ! -\distfromline ! \pgf@circ@voltage@angle:(anchorstartnode)$)
coordinate (pgfcirc@midtmp) at ($(\tikztotarget) ! \pgf@circ@Rlen/16 ! (anchorendnode)$)%absolute move, minimum space is length of arrowhead
coordinate (pgfcirc@midtmp) at ($(pgfcirc@midtmp) ! \distacefromnode ! (anchorendnode)$)
coordinate (pgfcirc@Vto) at ($(pgfcirc@midtmp) ! \distfromline ! \pgf@circ@voltage@angle : (anchorendnode)$)
\ifpgf@circuit@bipole@voltage@below
coordinate (pgfcirc@Vcont1) at ($(\ctikzvalof{bipole/name}.center) ! \bumpb ! (\ctikzvalof{bipole/name}.-110)$)
coordinate (pgfcirc@Vcont2) at ($(\ctikzvalof{bipole/name}.center) ! \bumpb ! (\ctikzvalof{bipole/name}.-70)$)
\else
coordinate (pgfcirc@Vcont1) at ($(\ctikzvalof{bipole/name}.center) ! \bumpb ! (\ctikzvalof{bipole/name}.110)$)
coordinate (pgfcirc@Vcont2) at ($(\ctikzvalof{bipole/name}.center) ! \bumpb ! (\ctikzvalof{bipole/name}.70)$)
\fi
\ifpgf@circuit@europeanvoltage
\ifpgf@circuit@bipole@voltage@straight
\ifpgf@circuit@bipole@voltage@backward
(pgfcirc@Vto) --(pgfcirc@Vfrom) node[currarrow, sloped, allow upside down, pos=1,anchor=tip] {}
\else
(pgfcirc@Vfrom) --(pgfcirc@Vto) node[currarrow, sloped, allow upside down, pos=1,anchor=tip] {}
\fi
\else
\ifpgf@circuit@bipole@voltage@backward
(pgfcirc@Vto) .. controls (pgfcirc@Vcont2) and (pgfcirc@Vcont1) ..
node[currarrow, sloped, allow upside down, pos=1] {}
(pgfcirc@Vfrom)
\else
(pgfcirc@Vfrom) .. controls (pgfcirc@Vcont1) and (pgfcirc@Vcont2) ..
node[currarrow, sloped, allow upside down, pos=1] {}
(pgfcirc@Vto)
\fi
\fi
\else
\ifpgf@circuit@bipole@voltage@backward
\ifpgf@circ@oldvoltagedirection
(pgfcirc@Vfrom) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickplusvm}
(pgfcirc@Vto) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickminusvm}
\else
(pgfcirc@Vfrom) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickminusvm}
(pgfcirc@Vto) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickplusvm}
\fi
\else
\ifpgf@circ@oldvoltagedirection
(pgfcirc@Vfrom) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickminusvm}
(pgfcirc@Vto) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickplusvm}
\else
(pgfcirc@Vfrom) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickplusvm}
(pgfcirc@Vto) node[inner sep=0, anchor=\pgf@circ@bipole@voltage@label@anchor]{\thickminusvm}
\fi
\fi
\fi
}
voltagemarkers.tex
is the same as the definition in the source code with $+$
and $-$
replaced by my macros from the main file.
There are two problems that I have with this solution. The first is that it requires externalization, and specifically it requires \usepgfplotslibrary{external}
Either not externalizing or using \usetikzlibrary{external}
instead both result in the new definitions being ignored. This is not necessarily a problem, but I would at least like to understand why this specific externalization is required.
The second problem is that I need to create an invisible vertical line in the minus symbol to keep the plus and minus inline. I tried using the text height
and text depth
tikz options described in the manual to keep them the same size, but this resulted in the minus sign being higher than the plus sign in the horizontal components. I also tried using the baseline
option, but with it the vertical markers became misaligned.
Is there a better way to do this that does not require the phantom line in the minus sign or externalization? I know this is delving into the depths of CircuitTikz
, but I would certainly appreciate any help you would be able to provide.
Edit:
Attempting to use savebox
es to prevent problems with nesting tikzpicture
environments based on comments from @marmot.
\newsavebox{\thickplusbox}
\newsavebox{\thickminusbox}
\savebox\thickplusbox{
\begin{tikzpicture}[x=0.85ex, y=0.85ex, scale=0.5]
\draw[line cap=round, line width=.95pt] (0,-1) -- (0,1);
\draw[line cap=round, line width=.95pt] (1,0) -- (-1,0);
\end{tikzpicture}
}
\savebox\thickminusbox{
\begin{tikzpicture}[x=0.85ex, y=0.85ex, scale=0.5]
\draw[line cap=round, line width=.95pt, opacity=0] (0,-1) -- (0,1);
\draw[line cap=round, line width=.95pt] (1,0) -- (-1,0);
\end{tikzpicture}
}
Adding the above code to the preamble results in the following error message:
! Undefined control sequence.
\pgf@externalend ... \pgfexternal@originalshipout
\box 0 \gdef \pgfexternal@...
l.36 }
If I move the savebox
definitions into the document (Which I'd like to avoid if I can) and set \tikzset{/tikz/external/optimize=false}
It will compile, but it moves the location of the symbols.
Original:
With SaveBoxes:
Any suggestions on how to keep the correct position while still using the savebox
es and keep the definitions in the preamble?
Edit 2:
Response to Marmot's answer:
Thanks again for your help with this Marmot! I've tried your answer and I think it's also experiencing the weird behavior that I mentioned in the original question regarding externalization.
This is the result of your code with no modifications (the same as you got):
However, this result is identical to the default CircuiTikz
behavior:
If I switch the \usetikzlibrary{external}
line to \usepgfplotslibrary{external}
and include the pgfplots package I get the following error:
! Undefined control sequence.
<argument> \markwidth
If we change the \markwidth
to .95pt
we get the following result:
So we can see now that the thickness is now set by the custom pgfplotmark
, but the spacing is off. I'm still very confused as to why the defaults are used when using \usetikzlibrary{external}
, but \usepgfplotslibrary{external}
allows the customization to take effect.
\savebox
es which, to the best of my knowledge, also avoids the potential problems that arise from nesting TikZ pictures.LaTeX Error: \begin{tikzpicture} on input line 30 ended by \end{scope}.
\begin{scope}.... \end{scope}
. As I said, working with\savebox
es may also be a way to do it.savebox
es. I'll take a look at your answer after dinner, thanks again for your help!