Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

problem
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}
share|improve this question
    
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 specified 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
add comment

2 Answers

up vote 8 down vote accepted

The manual on the --cycle operation:

This operation adds a straight line from the current point to the last point specified 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:

Joined lines in circuit

share|improve this answer
    
Thank for the explanation! I guess I do it with your trick … –  Tobi Nov 1 '11 at 11:24
add comment

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:

the path

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:

the whole path

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:

corners with rect line caps

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!)

circuit with rect line caps

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.

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.