23

In the code below I repeat one line (one with opacity=0 and other without it) in order to draw the intersection of 2 lines that are not connected. I am seeking a better way to achieve the same result. Using arc would also be a possible solution.

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,backgrounds}

\begin{document}

\begin{tikzpicture}

\begin{pgfonlayer}{background}
\draw[fill=yellow] (0.25,0.5) rectangle (1.75,1.5);
\end{pgfonlayer}
\draw [name path=a, opacity=0] (0,0) -- (2,2);% line that will be repeated
\draw [name path=b] (0,2) -- (2,0);
\path [name intersections={of=a and b,by=inter}];

\filldraw [yellow] (inter) circle (2pt);
\draw (0,0) -- (2,2);% line repeated

\end{tikzpicture}
\end{document}

Note: I only want to improve the way intersection between two lines is drawn, but keep the current aspect in the intersection of lines and rectangle. Moreover, the rectangle is not empty.

enter image description here

23

OK, quick and dirty, so not sure how robust this is, but by using the calc library (section 13.5 "Coordinate Calculations" in the 2.10 PGF Manual) and tying things up using the style args key handle (section 55.4.4 "Defining Styles"), it at least goes part of the way to showing how it could be done.

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,backgrounds}
\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}
\tikzset{
    connect/.style args={(#1) to (#2) over (#3) by #4}{
        insert path={
            let \p1=($(#1)-(#3)$), \n1={veclen(\x1,\y1)}, 
            \n2={atan2(\y1,\x1)}, \n3={abs(#4)}, \n4={#4>0 ?180:-180}  in 
            (#1) -- ($(#1)!\n1-\n3!(#3)$) 
            arc (\n2:\n2+\n4:\n3) -- (#2)
        }
    },
}
\begin{pgfonlayer}{background}
\draw[fill=yellow] (0.25,0.5) rectangle (1.75,1.5);
\end{pgfonlayer}

\draw [name path=a] (0,0) -- (2,2);
\path [name path=b] (0,2) coordinate (x)  -- (2,0) coordinate (y);
\path [name intersections={of=a and b,by=inter}];

\draw [red, ultra thick, connect=(x) to (y) over (inter) by -6pt];
\draw [connect=(x) to (y) over (inter) by 3pt];

\end{tikzpicture}
\end{document}

enter image description here

In fact, we could go further and tie a lot of stuff up in the connect style. This involves the use of \pgfextra (section 14.18 "The PGF-Extra Operation") and the pgfinterruptpath environment (section 69.3.2 "Graphic Scope Environments").

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,backgrounds}
\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}
\tikzset{
    connect/.style args={(#1) to (#2) over (#3) to (#4) by #5}{
        insert path={
            \pgfextra{
                \pgfinterruptpath
                    \path [name path=a] (#1) -- (#2);
                    \path [name path=b] (#3) -- (#4);
                    \path [name intersections={of=a and b,by=inter}];
                \endpgfinterruptpath                
            }
            let \p1=($(#1)-(inter)$), \n1={veclen(\x1,\y1)}, 
                            \n2={atan2(\y1,\x1)}, \n3={abs(#5)}, \n4={#5>0 ?180:-180}  in 
                            (#1) -- ($(#1)!\n1-\n3!(inter)$) 
                            arc (\n2:\n2+\n4:\n3) -- (#2)
        }
    },
}
\begin{pgfonlayer}{background}
\draw[fill=yellow] (0.25,0.5) rectangle (1.75,1.5);
\end{pgfonlayer}

\draw  (0,0) -- (2,2);

\draw [red, very thick, connect={(0,2) to (2,0) over (0,0) to (2,2) by -5pt}];
\draw [connect={(0,2) to (2,0) over (0,0) to (2,2) by 3pt}];

\end{tikzpicture}
\end{document}

The result is the same as before.

  • Very good answer. – cacamailg May 1 '13 at 12:44
  • This code no longer works with the newer version of TiKZ that comes with TeXLive 2014. Can you please update it? – cacamailg Feb 25 '15 at 18:59
13

Here I keep the Jake's answer to my beginning question, which might be useful for someone. For this to work, the rectangle shall be "empty" and not in background layer.

\documentclass[tikz]{standalone}

\begin{document}
\begin{tikzpicture}

\draw (0,0) -- (2,2);
\draw [draw=white,double=black,double distance=\pgflinewidth,ultra thick] (0,2) -- (2,0);
\draw (0.25,0.5) rectangle (1.75,1.5);

\end{tikzpicture}
\end{document}

enter image description here

8

Although an awesome answer from Mark Wibrow, I like things to be more smooth, so I implemented controls to his code (it ends up reducing a bit of the calculations as well):

\documentclass[tikz, border=5mm]{standalone}
\usetikzlibrary{calc}
\usetikzlibrary{intersections}

%%% Adapted from Mark Wibrow
\tikzset{%
    connect/.style args={(#1) to (#2) over (#3) by #4}{%
        insert path={%
            let \p1=($(#1)-(#3)$), \n1={veclen(\x1,\y1)}, \n2={abs(#4)}  in%
                (#1) --%
                ($(#1)!\n1-\n2!(#3)$) .. controls +(0:\n2/2) and +(180:\n2/2) ..%
                +(\n2,#4)%
                .. controls +(0:\n2/2) and +(180:\n2/2) .. ($(#1)!\n1+\n2!(#3)$) -- (#2)%
        }%
    }%
}

\begin{document}
\begin{tikzpicture}[line join=round]
  \coordinate (a) at (-0.5,0.5);
  \coordinate (b) at (8,-0.5);
  \draw[ultra thick, name path=sine, domain=-1:8, smooth, samples=50] plot (\x,{sin(\x r)});
  \path[name path=line] (a) -- (b);
  \path[name intersections={of=sine and line}];
  \draw[blue, connect={(a) to ($(a)!.5!(intersection-2)$) over (intersection-1) by 12pt},
        connect={($(a)!.5!(intersection-2)$) to ($(intersection-2)!.5!(intersection-3)$) over (intersection-2) by -8pt},
        connect={($(intersection-2)!.5!(intersection-3)$) to (b) over (intersection-3) by 4pt}
        ];
\end{tikzpicture}
\end{document}

enter image description here

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.