15

I want to create a straight line between two nodes in a tikzpicture interrupted in the middle by a dotted portion. This should work whatever the orientation of the line.

Here is an expected output:

enter image description here

The best would be to have a line style defined for this instead of each time using clip to remove the straight line and then tweak a dotted one to fit the hole. A minimal code for the solution would look like

\documentclass[a4paper, 12pt]{report}

\usepackage{tikz}

\tikzset{
    middle dotted line/.style={
        thick, 
        % YOUR HELP HERE
    }
}% end of tikzset


\begin{document}

\begin{tikzpicture}
    \node (A) at (0, 3) {};
    \node (B) at (5, 3) {};
    \node (C) at (0, 2) {};
    \node (D) at (5, 0) {};
    \draw[middle dotted line] (A) -- (B);
    \draw[middle dotted line] (C) -- (D);
\end{tikzpicture}

\end{document}
2
  • 1
    Welcome to TeX.SE!
    – Mensch
    Apr 5 at 13:13
  • 1
    I take it \draw (A) -- (B) node[midpoint, fill=white, sloped]{$\cdots$};` won't do? Apr 5 at 15:26

5 Answers 5

12

Inspired by Mark Wibrow

\documentclass[tikz, border=5]{standalone}
\usetikzlibrary{decorations.pathreplacing,calc}
\tikzset{%
  middle dotted line/.style={
    decoration={show path construction, 
      lineto code={
          \draw[#1] (\tikzinputsegmentfirst) --($(\tikzinputsegmentfirst)!.3333!(\tikzinputsegmentlast)$);,
          \draw[dotted,#1] ($(\tikzinputsegmentfirst)!.3333!(\tikzinputsegmentlast)$)--($(\tikzinputsegmentfirst)!.6666!(\tikzinputsegmentlast)$);,
          \draw[#1] ($(\tikzinputsegmentfirst)!.6666!(\tikzinputsegmentlast)$)--(\tikzinputsegmentlast);,
      }
    },
    decorate
  },
}
\begin{document}

\begin{tikzpicture}
\draw[middle dotted line] (0,0)--(4,1);
\draw[middle dotted line={line width=1.5pt}] (1,1)--(3,4);
\end{tikzpicture}

\end{document}

enter image description here

6

Using the spath3 library (at time of writing, needs the development version from github).

\documentclass{article}
%\url{https://tex.stackexchange.com/q/639726/86}
\usepackage{tikz}
\usetikzlibrary{spath3}

\begin{document}

\begin{tikzpicture}
\draw[spath/save=path,ultra thick, red] (0,0) -- +(3,0);
\draw[spath/split at keep start={path}{1/3},spath/use=path];
\draw[spath/split at keep end={path}{2/3},spath/use=path];
\draw[spath/split at keep middle={path}{1/3}{2/3},spath/use=path,dotted];

\draw[spath/save=path,ultra thick, red] (0,-1) .. controls +(6,-1) and +(-6,-1) .. +(3,0);
\draw[spath/split at keep start={path}{1/3},spath/use=path];
\draw[spath/split at keep end={path}{2/3},spath/use=path];
\draw[spath/split at keep middle={path}{1/3}{2/3},spath/use=path,dotted];

\end{tikzpicture}
\end{document}

It works by splitting the path into three components and then rendering each component with a different style. As Henri mentions in the comments, to have a genuine solid and dotted line requires (at least) two draw commands - one for each style. I use one for each segment since combining the first and last segments would actually lead to slightly more complicated code.

As it uses the spath3 library, it works on arbitrary paths.

Here's the result:

solid and dotted lines

2
  • This should be the accepted answer, because it works on arbitrarily curved paths. The currently accepted answer only works on straight paths. Apr 6 at 13:01
  • 1
    It's a forlorn hope, I know, but it would be useful if the downvoter explained what they felt was bad about this answer. I try to be helpful on this site and when I miss the mark then the only way I'll improve is if I know what went wrong. Apr 7 at 5:52
4

Without guru's tricks try this:

\documentclass[tikz, border=1cm]{standalone}
\begin{document}
\begin{tikzpicture}
    \path (0,0) coordinate (A) (3,5) coordinate (B);
    \path (A)--(B) node [inner sep=0pt,pos=.333] (C) {};
    \path (A)--(B) node [inner sep=0pt,pos=.666] (D) {};
    \draw (A)--(C);
    \draw (D)--(B);
    \draw[dotted] (C)--(D);
\end{tikzpicture}
\end{document}

Output:

enter image description here

4
  • If you use the calc library then you can do your coordinate calculations all in one go without creating extra nodes. (It feels sufficiently close to this answer that I don't want to post a separate answer just for that, but you could add an example using calc) Apr 5 at 17:40
  • @AndrewStacey Thanks for your suggestion. But I post my answer just for its simplicity, without the help of others packages or libraries. I know that I can calculate the coordinates of my intermediates points C(1,5/3) and D(2,10/3): the parameter pos of Tikz make the job! Apr 5 at 21:55
  • Fair enough. I've added a separate calc answer then as I think it's a useful example to show how the calc library can shorten the code. Apr 5 at 22:57
  • 1
    an code-cleaning suggestion: using coordinate is more suitable than node. \documentclass[tikz, border=1cm]{standalone} \begin{document} \begin{tikzpicture} \path (0,0) coordinate (A) --(3,5) coordinate (B) coordinate[pos=1/3] (C) coordinate[pos=2/3] (D); \draw (A)--(C) (D)--(B); \draw[dotted] (C)--(D); \end{tikzpicture} \end{document}
    – Black Mild
    Apr 6 at 9:44
3

With the subpath function and time along a path, Asymptote handles this task very easy, for any curve.

enter image description here

unitsize(1cm);

// for curvy curves
path p=(0,-1) .. controls (0,-1)+(6,-1) and (3,-1)+(-6,-1) .. (3,-1);
real t1=.4,t2=.6;   // times on path
path q1=subpath(p,0,t1);
path q2=subpath(p,t1,t2);
path q3=subpath(p,t2,1);
draw(q1^^q3,magenta);
draw(q2,magenta+dotted);

// of course it works for straight lines
path pline=(0,0)--(3,1);
real s1=.3,s2=.7;   // times on path

path q1line=subpath(pline,0,s1);
path q2line=subpath(pline,s1,s2);
path q3line=subpath(pline,s2,1);
draw(q1line^^q3line,blue);
draw(q2line,blue+dotted);

shipout(bbox(5mm,invisible));
1
  • 1
    It's great seeing how other technologies approach problems. Now all we need is a pstricks solution to complete the set! Apr 6 at 13:39
2

A minor variation of Raffaele Santoro's answer using the calc library to shorten the code. It produces the same output.

\documentclass[tikz, border=1cm]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
    \path (0,0) coordinate (A) (3,5) coordinate (B);
    \draw (A)--($(A)!1/3!(B)$) ($(A)!2/3!(B)$) -- (B);
    \draw[dotted] ($(A)!1/3!(B)$) -- ($(A)!2/3!(B)$);
\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.