0

This Question is directly related to: Correct linejoins at tikz to path Please have a look at this question first.

A second Problem arises if the start coordinate is a node, which is not used with a specific anchor. In this cases the starting point of the 'proper linejoin' is not set correctly.

What could be here the solution? I think i have to trigger the \tikz@moveto@waiting, but i did not have any idea how to do this.

MWE:

\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{
  \let\tikz@moveto@waiting=\relax
  \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}
    \begin{scope}[xshift=2.5cm]
     \draw (0,1.5)node[right]{Ok};
     \draw (0,0) coordinate(A);
     \draw (0,-1) coordinate(B);
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A)to[mypath](B);
  \end{scope}
  \begin{scope}[xshift=5cm]
    \draw (0,1.5)node[right]{Not Ok};
    \draw (0,0) node(A){};
    \draw (0,-1) node(B){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A)to[mypath](B);
  \end{scope}
  \begin{scope}[xshift=7.5cm]
    \draw (0,1.5)node[right]{Ok};
    \draw (0,0) node(A){};
    \draw (0,-1) node(B){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A.center)to[mypath](B);
  \end{scope}
  \end{tikzpicture} 
\end{document}

enter image description here The problem here is the straight horizontal line, which should not appear. The interruption of the vertical line at the right most example can be ignored, this is just due to the inner sep of the node.

Best regards, Stefan

  • You're using coordinate (A) in your first example but node (A) in your other examples. node (A) inserts a default node with some non-zero size. Try using coordinate (A) or node [coordinate] (A) in the 2nd example. – Mark Wibrow May 12 '17 at 13:04
  • Well, this would be the trivial solution, but sometime i WANT to use nodes :) – sistlind May 12 '17 at 13:07
  • A workaround: (A)(A)to[mypath](B). TikZ's path is a mess. – Symbol 1 May 12 '17 at 19:53
  • Is there a possibility to find out if \tikztostart is a node or a coordinate? Or to check if the current position is equal to \tikztostart? I thick i have to force \tikz@moveto@waiting to be executed, is this possible? – sistlind May 14 '17 at 8:48
  • I think i found a solution: \iftikz@shapeborder \pgfpathmoveto{\tikz@last@position}% \fi before the line \pgfsyssoftpath@getcurrentpath{\my@saved@path} seems to work. I will do a few further tests on this.. – sistlind May 14 '17 at 10:15
0

I encountered a second problem, which occurs, if the starting point is a node without an explicit anchor and the target is a relative position. The following solution uses a helper function, which explicitly sets the anchor, if none is defined. This should work in all cases.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\def\set@explicit@anchor#1{
    \pgfutil@ifundefined{pgf@sh@ns@#1}
    {
    %This coordinate is no node(but a relative position or a coordinate), no further handling needed
    }{
    \pgfutil@in@.{#1}
    \ifpgfutil@in@
    % Anchor is used, do nothing!
    \else%
        \let\tikz@moveto@waiting=\relax
        \pgfpathmoveto{\tikz@last@position}%force movement, because tikz@moveto@waiting
        \edef#1{#1.center}%ensure using center anchor
    \fi
    }
}

\tikzset{mypath/.style = {to path={
        %Save current path, because (\tikztostart) at the coordinate-command will start a new one
        \pgfextra{
            \set@explicit@anchor{\tikztostart}
            \set@explicit@anchor{\tikztotarget}
            \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{
        %   \let\tikz@moveto@waiting=\relax
            \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}
\begin{scope}[xshift=0cm]
    \draw (0,1.5)node[right]{Ok};
    \draw (0,0) coordinate(A);
    \draw (-1,-1) coordinate(B);    \draw (-2,-1) node(C){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A)to[mypath](B)to[mypath](C);
\end{scope}
\begin{scope}[xshift=2.5cm]
    \draw (0,1.5)node[right]{Now Ok};
    \draw (0,0) node(A){};
    \draw (-1,-1) node(B){};\draw (-2,-1) node(C){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A)to[mypath](B)to[mypath](C);
\end{scope}
\begin{scope}[xshift=5cm]
    \draw (0,1.5)node[right]{Not Ok};
    \draw (0,0) node(A){};
    \draw (-1,-1) node(B){};\draw (-2,-1) node(C){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A)to[mypath]++(-1,-1)to[mypath](C);
\end{scope}
    \begin{scope}[xshift=7.5cm]
    \draw (0,1.5)node[right]{Ok};
    \draw (0,0) node(A){};
    \draw (-1,-1) node(B){};\draw (-2,-1) node(C){};
    \draw (A) to[mypath](0,1)to[mypath](1,0) (A.center)to[mypath]++(-1,-1)to[mypath](C);
\end{scope}
\end{tikzpicture} 
\end{document}

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.