2

I would like to use a to-path, where a node is placed in the middle. This breaks the linejoins between the single segments. Therefore, i added short segments at the end and begin of each path. This works with the following code. Nevertheless, if the target coordinate is a node, there seems to be a problem. Is it possible to fix this within the path-code? Or does anyone has another idea to get proper linejoins in another way?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\tikzset{mypath/.style = {to path={
%Save current path, because (\tikztostart) at the coordinate-command will start a new one
\pgfextra{\pgfsyssoftpath@getcurrentpath{\my@saved@path}
}

(\tikztostart) coordinate (start)%necessary to get correct coordinates in the case of relativ start/end or constructions like ((node1)-|(node2))
(\tikztotarget) coordinate (end)

\pgfextra{
    \pgfmathanglebetweenpoints{\pgfpointanchor{start}{center}}{\pgfpointanchor{end}{center}}
    \edef\path@direction{\pgfmathresult}%Calculate direction(angle) of path
    \pgfsyssoftpath@setcurrentpath{\my@saved@path}%%switch back to old path
}
%Connect to old path for proper linejoin
--($(start)!.5\pgflinewidth!(end)$)

%set middle node
($(start) ! .5 ! (end)$)node[draw,circle,rotate=\path@direction] (node) {}
%connect
(\tikztostart)--(node.west)
(node.east)--(\tikztotarget)

%Draw a short connection at the end for proper linejoin
($(end)!.5\pgflinewidth!(start)$)--(end)
}}}\makeatother

\begin{document}
\tikzset{every picture/.style=thick}
  \begin{tikzpicture}
    \draw (0,1.5)node[right]{Ok}; 
    \draw (0,0) to[mypath](0,1) to[mypath](1,1)to[mypath]++(1,-1);
  \begin{scope}[xshift=2.5cm]
    \draw (0,1.5)node[right]{Ok}; 
    \draw (1,1) coordinate(A);
    \draw (0,0) to[mypath](0,1) to[mypath](A)to[mypath]++(1,-1);
  \end{scope}
  \begin{scope}[xshift=5cm]
    \draw (0,1.5)node[right]{Not Ok};
    \draw (1,1) node(A){};
    \draw (0,0) to[mypath](0,1) to[mypath](A)to[mypath]++(1,-1);
  \end{scope}
  \begin{scope}[xshift=7.5cm]
    \draw (0,1.5)node[right]{Ok};
    \draw (1,1) node(A){};
    \draw (0,0) to[mypath](0,1) to[mypath](A.center)to[mypath]++(1,-1);
  \end{scope}
  \end{tikzpicture} 
\end{document}

enter image description here

EDIT: I have no idea why, but it seems to work, if i change line 11 to:

(\tikztotarget)++(0,0) coordinate (end)

EDIT2/Solution:

Insert within the \pgfextra{...} around line 14:

\let\tikz@moveto@waiting=\relax

Best regards,

Stefan

PS: The shown code is just a MWE to illustrate the problem, the original problem is described here and occurs within the circuitikz package

  • 1
    Your code is unsymmetric. What stops you from writing (start)--($(start)!.5\pgflinewidth!(end)$) instead of --($(start)!.5\pgflinewidth!(end)$)? – Symbol 1 Mar 24 '17 at 20:37
  • This will break the linejoins, because (start) introduces a moveto command which starts a new path – sistlind Mar 25 '17 at 7:40
2

The problem begins at the following line:

(\tikztostart) coordinate (start)%necessary to get correct coordinates in the case of relativ start/end or constructions like ((node1)-|(node2))
(\tikztotarget) coordinate (end)

Here (\tikztostart) is (0,1) and (\tikztotarget) is the node (A).

When TikZ sees (\tikztotarget), it will try to move to (A) because it expects the user to draw something. But it cannot move to (A) immediately because (A) is a node, and it can execute a moveto only if it knows the target and calculates the anchorborder(s).

Therefore, instead of executing a moveto, TikZ will let \tikz@moveto@waiting be A and read the next few characters to see what you want to do. It then sees coordinates, so TiKZ knows that you want to rename the node. It will moveto (A.center) and called it (end), so far so good.

Eight lines later, TikZ encounters

--($(start)!.5\pgflinewidth!(end)$)

The destination of this lineto is not important. The problem is: where is the origin of this lineto? There are two possibilities

  • (2,71) --($(start)!.5\pgflinewidth!(end)$)
  • (some node)--($(start)!.5\pgflinewidth!(end)$)

For the first possibility, TikZ knows that it had executed a moveto so it will simply execute a lineto. For the second case, it knows that the (some node) is pending and it should calculate the anchorborder.

So where is the origin? will... we start this to-path from (0,1), so the origin is (0,1), right?

Unfortunately, TikZ make the decision by checking if \tikz@moveto@waiting is empty. Remember eight lines ago \tikz@moveto@waiting is let to be (A). So TikZ thinks that this lineto starts from (A) instead of (0,1). And then everything goes wrong.


To overcome this problem, you should let \tikz@moveto@waiting be empty again in the \pgfextra.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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