Drawing normally open switch with connectors

I'm using CircuiTikZ and want to draw a SPST switch that has the same style as the included SPDT switch. Something like the following:

I've experimented with a few things:

\documentclass{article}
\usepackage{circuitikz}

\begin{document}
\begin{enumerate}
\item \tikz\draw (0,0) to[nos,o-o] (5,0);
\item \tikz\draw (0,0) -- (2.25,0) to[nos,o-o] (2.75,0) -- (5,0);
\item \tikz\draw (2.5,0) node[nosshape](sw2){} (0,0) -- (sw2) -- (5,0);
\item \tikz\draw (2.5,0) node[nosshape](sw1){} (0,0) to[short,-o] (sw1) to[short,o-] (5,0);
\end{enumerate}
\end{document}


The default behavior of nos is seen in item 1; it has no connectors, and adding connectors in the to just puts them at the end of the path, as with all such components.

I was able to produce the look I wanted with the code for item 2, but that requires manually specifying the left and right sides of the switch to be exactly 0.5 units apart (the default width of the nos component). I can use it, but it is not always that straightforward and I would like a simpler method if possible.

I thought I could simplify it by drawing the nos as a node using node[nosshape], which looked like it was going to work when I used the code for item 3. Unfortunately, once I changed to to[short,-o] in order to add the connectors, the lines no longer stopped at the sides of the component, but went to its center point instead, as can be seen in item 4.

How can I simply draw a nos with connectors that doesn't require specifying the sides? And why doesn't the method in item 4 work?

This solution adds ocirc nodes to the switch anchors.

\documentclass{standalone}
\usepackage{circuitikz}

\begin{document}
\begin{circuitikz}
\draw (0,0) to[nos,o-o,n=S1] (5,0)
node[ocirc] at (S1.e) {}
node[ocirc] at (S1.w) {};
\end{circuitikz}
\end{document}


• Aha! I had tried to do something like that, but was using .east/.west and .left/.right, which don't exist. This is a bit more code in the drawing, but doesn't require any extra setup, and you don't have to define the coordinates of the sides of the switch. I played around with it and found you can also draw the same thing like this: \tikz\draw (2.5,0) node[nosshape] (S1) {} (0,0) to[short,o-o] (S1.w) (S1.e) to[short,o-o] (5,0); Mar 30, 2019 at 19:23

This may not be a full-fledged answer but more a recipe to construct such elements. What I am proposing to do is to

1. Look in the manual for a similar-looking shape. (I found that the push button has some common elements.
2. Copy the definitions from the relevant files (here they were circuitikz/pgfcircbipoles.tex, pgfcirc.defines.tex and pgfcircpath.tex, which I concluded from grep -r "pushbutton" /usr/local/texlive/2018/texmf-dist/tex/generic/*) to the preamble of your document, enclosed by \makeatletter and \makeatother.
3. Modify it.

This brought me to

\documentclass{article}
\usepackage{circuitikz}
\makeatletter
\ctikzset{bipoles/my switch/height/.initial=.5}
\ctikzset{bipoles/my switch/width/.initial=.50}
\pgfcircdeclarebipole{}{}{myswitch}{%
\ctikzvalof{bipoles/my switch/height}}{\ctikzvalof{bipoles/my switch/width}}{
\pgfsetlinewidth{\pgfkeysvalueof{/tikz/circuitikz/bipoles/thickness}\pgfstartlinewidth}
\pgfpathmoveto{\pgfpoint{\pgf@circ@res@left}{0pt}}
\pgfpathlineto{\pgfpoint{\pgf@circ@res@right}{.75\pgf@circ@res@up}}
\pgfusepath{draw}
%
\pgfsetlinewidth{\pgfstartlinewidth}
\pgftransformshift{\pgfpoint{\pgf@circ@res@left}{0pt}}
\pgfnode{ocirc}{center}{}{}{\pgfusepath{draw}}
\pgftransformshift{\pgfpoint{2\pgf@circ@res@right}{0pt}}
\pgfnode{ocirc}{center}{}{}{\pgfusepath{draw}}
}
\def\pgf@circ@myswitch@path#1{\pgf@circ@bipole@path{myswitch}{#1}}
\compattikzset{my switch/.style = {\circuitikzbasekey,
/tikz/to path=\pgf@circ@myswitch@path}}

\makeatother
\begin{document}
\begin{enumerate}
\item \tikz\draw (0,0) to[my switch] (5,0);
\end{enumerate}
\end{document}


• maybe it is worth to see new version of circuitikz available on github (not yet on ctan). few days ago here was a question about it. as i remember, it has defined such switches. Mar 29, 2019 at 22:23
• @Zarko As long as it does not come with an analog of arrows.meta for switches and the like you will probably still have to be able to customize shapes in the hard core way,
– user121799
Mar 29, 2019 at 22:25
• That definitely results in the simplest drawing code once you do the more complex part creation. It looks like the current code on GitHub has "cute" versions of the switches that have connectors like I want, but they also draw the switch bar extremely thick and some other things that look ugly, IMO. It might work as a good starting point for this method and I can just reduce the line width back to normal. Mar 30, 2019 at 19:18
• Be warned, not all components are the same size. Mar 31, 2019 at 1:19
• @Herohtar yes, the "cute switches" I added have the bar thickness at the same size of the ocirc shape. I can look at making it configurable... please open an issue on the github page! github.com/circuitikz/circuitikz/issues Apr 22, 2019 at 14:35

In the end, adding the option to configure thickness was quite easy, so I did it. In the unreleased version that will be up on line later today (just the times to build the thing by the CI system), you'll be able to do a thing like this:

\documentclass[border=10pt]{standalone}
\usepackage[siunitx, RPvoltages]{circuitikzgit}
\begin{document}
\begin{circuitikz}
\begin{scope}[xshift=-1cm]
\ctikzset{bipoles/cuteswitch/thickness=1.5}
\draw (0,1.4) node[cute spdt up](S1){};
\draw (0,0)   node[cute spdt up](S2){};
\draw (0,-1)  node[cuteclosedswitchshape, yscale=-1](S3){};
\draw [densely dashed] (S1.mid)--(S2.mid)--(S3.mid);
\end{scope}
\begin{scope}
\draw (0,1.4) node[cute spdt up](S1){};
\draw (0,0)   node[cute spdt up](S2){};
\draw (0,-1)  node[cuteclosedswitchshape, yscale=-1](S3){};
\draw [densely dashed] (S1.mid)--(S2.mid)--(S3.mid);
\end{scope}
\begin{scope}[xshift=1cm]
\ctikzset{bipoles/cuteswitch/thickness=0.5}
\draw (0,1.4) node[cute spdt up](S1){};
\draw (0,0)   node[cute spdt up](S2){};
\draw (0,-1)  node[cuteclosedswitchshape, yscale=-1](S3){};
\draw [densely dashed] (S1.mid)--(S2.mid)--(S3.mid);
\end{scope}
\begin{scope}[xshift=2cm]
\ctikzset{bipoles/cuteswitch/thickness=0.25}
\draw (0,1.4) node[cute spdt up](S1){};
\draw (0,0)   node[cute spdt up](S2){};
\draw (0,-1)  node[cuteclosedswitchshape, yscale=-1](S3){};
\draw [densely dashed] (S1.mid)--(S2.mid)--(S3.mid);
\end{scope}
\end{circuitikz}
\end{document}


to obtain

...and you can use the various kind of switches, obviously...

Although I reckon that the solution proposed by @marmot is more general. I have added a (admittedly small) chapter to the manual explaining how to define new shapes.