# TikZ: Use --cycle in circuits

Why does the --cycle command doesn’t work in a circuit drawn with the TikZ library circuits.ee.IEC? The problem with manually draw the last connection is that the ends are not joined.

I made the lines very thick to demonstrate the problem of not joining …

Is it possible to fix this or at least join the path manually?

Code

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{circuits.ee.IEC}

\begin{document}
\begin{tikzpicture}[circuit ee IEC, line width=5pt]
\draw (0,0) -- ++(0,2) node [above] {without objects}%
-- ++(4,0) -- ++(0,-2)%
--cycle node [below] {works};

\draw (0,-4.5) to[voltage source] ++(0,2) node [above] {with -\/-cycle}%
-- ++(4,0) to[resistor] ++(0,-2)%
--cycle node [below] {no connection};

\draw (0,-9) to[voltage source] ++(0,2) node [above] {manually}%
-- ++(4,0) to[resistor] ++(0,-2)%
-- ++(-4,0) node [below] {not joined};
\end{tikzpicture}
\end{document}

-
I guess the path is interrupted by the resistor and therefore -- cycle doesn't work any longer. Note that PGF/TikZ passes most vector graphic commands down to the used format, either PDF or PS. If is isn't a single path at this level cycle doesn't work, I guess. –  Martin Scharrer Nov 1 '11 at 10:35
The manual on the --cycle operation: This operation adds a straight line from the current point to the last point speciﬁed by a move-to operation. Note that this need not be the beginning of the path. Furthermore, a smooth join is created. So apparently there is a move-to operation when the voltage source and resistor are added (which makes perfect sense) therefore the cycle is actually made, only it just draws a line back to the end of the resistor in this case over the line that's already there. –  Roelof Spijker Nov 1 '11 at 10:58

The manual on the --cycle operation:

This operation adds a straight line from the current point to the last point speciﬁed by a move-to operation. Note that this need not be the beginning of the path. Furthermore, a smooth join is created.

So apparently there is a move-to operation when the voltage source and resistor are added (which makes perfect sense) therefore the cycle is actually made, only it just draws a line back to the end of the resistor in this case over the line that's already there.

I can't think of any way to fix this behaviour, a move has to be made in the pgf path in order to 'skip' the symbol for the resistor (and voltage source). We can perform a little trick to get a proper join when adding the line manually though. Basically what we do is just draw a short line up over the one already there, this will create a smooth join on top of what's already there.

\documentclass{minimal}

\usepackage{tikz}
\usetikzlibrary{circuits.ee.IEC}

\begin{document}
\begin{tikzpicture}[circuit ee IEC, line width=5pt]
\draw (0,0) -- ++(0,2) node [above] {without objects}%
-- ++(4,0) -- ++(0,-2)%
--cycle node [below] {works};

\draw (0,-4.5) to[voltage source] ++(0,2) node [above] {with -\/-cycle}%
-- ++(4,0) to[resistor] ++(0,-2)%
--cycle node [below] {no connection};

\draw (0,-9) to[voltage source] ++(0,2) node [above] {manually}%
-- ++(4,0) to[resistor] ++(0,-2)%
-- ++(-4,0) node [below] {now joined} -- ++(0,0.1);
\end{tikzpicture}
\end{document}


And the resulting document:

-
Thank for the explanation! I guess I do it with your trick … –  Tobi Nov 1 '11 at 11:24

Martin's comment is on the right lines. The --cycle syntax draws a straight line from the current point on the path to the start of the last component. A component means a continuous path, so is marked by the last moveto. The actual implementation of this is handled either by the driver or the renderer so TikZ doesn't control how the corners are handled in this situation.

The problem with what you are trying to do is that your path is interrupted by moves. The symbols are placed by using nodes and the path has to be broken in order to go around them. This is made clear if we examine the path that is actually defined. If we take your middle example and look at the actual path, we get:

\pgfsyssoftpath@movetotoken {0.0pt}{-128.03734pt}
\pgfsyssoftpath@linetotoken {0.0pt}{-109.08456pt}
\pgfsyssoftpath@movetotoken {0.0pt}{-90.08456pt}
\pgfsyssoftpath@linetotoken {0.0001pt}{-71.13185pt}
\pgfsyssoftpath@linetotoken {0.0001pt}{-71.13185pt}
\pgfsyssoftpath@linetotoken {113.81097pt}{-71.13185pt}
\pgfsyssoftpath@linetotoken {113.81097pt{-83.08463pt}
\pgfsyssoftpath@movetotoken {113.81097pt}{-116.08463pt}
\pgfsyssoftpath@linetotoken {113.81108pt}{-128.03734pt}
\pgfsyssoftpath@linetotoken {113.81108pt}{-128.03734pt}
\pgfsyssoftpath@closepathtoken {113.81097pt}{-116.08463pt}


So we start with a moveto (every path starts with a moveto) then draw a line straight up. This is followed by another moveto: that's the move that skips the voltage source. Then we get a lineto up to the corner. (In fact, we get two linetos, but the second is effectively a NOP. Presumably there's some complicated case where it would come into play.) Our next journey is across the top and then we start the descent. Again, we break our journey to make space for the resistor and then finish the downward part in the corner (again with a double lineto). The last stage is the closepath which closes up the path (must've been a genius who came up with that name). The coordinates of the closepath aren't actually used, but can indicate (to the user) where the closing line should go. In this case, it goes to the bottom of the resistor. As this line is already drawn, we don't notice this.

Drawing just the path produces the red line in the following:

Of course, we can't see the closepath here because it is on top of the path already drawn. If we take out the resistor, then we can see this closepath in action:

It may be hard to see, but the closed path is genuinely closed.

The difficulty here is that --cycle always produces a closed path. But that's not what you want. What you want is to join the end back to the start. Exactly how to do this depends on how automatic and how faithful you want the solution to be. "Automatic" is fairly obvious, "faithful" is perhaps less so. What I mean by that is whether you want the paths to be actually joined, or whether the simulation is enough.

If simulation is enough, and all your corners are at right angles, then a simple line cap=rect ought to suffice. This ensures that line ends protrude by half the line width. Compare:

Unfortunately, on my test run (with your code), the infinitesimal lines interfere with this and I don't get a clean corner in the lower right. (However, I don't get a clean corner there with your code either so I suspect that we have different PGF versions and that this might be an okay solution for you ... Hang on: having now uploaded the picture I see that the fact that I don't see a clean corner in the lower right is due to my PDF viewer!)

Incidentally, note that this also fixes the small white lines in your picture between the "wires" and the "symbols". Normally these wouldn't be visible anyway - they are there because of the extra thick lines and the inaccuracy of placing lines at exactly the right place.

To do this automatically and faithfully what we would have to do is take the path and process it a little. We'd have to take the initial component (being the little upward stretch) and join it to the last component, so that the path now began with the bit emanating out of the resistor. This is perfectly possible with low-level code and I have all the pieces in my spath library, they just need to be put together in a sensible way.

-
Note: wh1t3's solution appeared while I was in the middle of writing this (I got distracted by a bug in my spath library!). The solution presented there is one that I was considering as well, but I saw no point in merely repeating it in mine so just gave the line cap=rect solution. –  Loop Space Nov 1 '11 at 11:30
Thank you very much for the detailed answer. Since it seems to be hard work and needs lot of time (without money …) to make an automatic solution I prefer the fake but faithful solution that wh1t3 presented. –  Tobi Nov 1 '11 at 11:39
@Tobi: Absolutely! Always prefer the simplest solution. I'm going to put this in my spath code anyway since it won't be hard (as I said, I have all the pieces) but that code is somewhat experimental so I wouldn't recommend it for "daily use" anyway. –  Loop Space Nov 1 '11 at 11:45