I have a simple question and hope for a simple answer: why does closing a path with dash pattern not work if the dash length exceeds the length of the path?

\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
 \begin{tikzpicture}
  \draw[dash pattern=on 5cm off 16cm,blue,ultra thick]
   (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
  \begin{scope}[xshift=2cm]
  \draw[blue,ultra thick]
   (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
  \end{scope}
 \end{tikzpicture} 
\end{document}

enter image description here

If you look closely, you'll notice that the left contour does not close, i.e. the bottom left corner is "screwed up". This is despite the fact that the dash exceeds (5cm) the length of the path (4cm). Why is that and how can one fix this?

Notice that I am not interested in a manual fix of the sort \draw[blue,ultra thick] (0,0) -- (1,0) -- (1,1) -- (0,1) -- (0,-\pgflinewidth/2);. I would, however, also be interested in a solution using decorations. This is because the present question is closely related to this nice question and the discussion below it. If you come up with a solution based on decorations that is different from this post in that it is less hacky, more transparent and does not mix decorations and meta decorations in an intricate way, this would be very interesting, but perhaps fit better as an answer to the partner question. (I am, however, not interested in a pure decorations solution in which one has to "quantize" the steps in such a way that the square gets redrawn.) That is, I would prefer answers without decorations to this question.

  • This is a viewer problem. Acrobat and Evince close the path, Okular, Chrome and Firefox do not. TikZ just copies the dash pattern into the PDF graphics stream, then your PDF viewer has to interpret it. This only happens for butt linecaps, so it might be a viewer bug. – Marcel Krüger Aug 21 at 22:15
  • 1
    Correction for my earlier comment: It happens for all linecaps on the affected readers, it is just invisible when round linecaps and linejoins are used – Marcel Krüger Aug 21 at 22:22
  • @MarcelKrüger If Acrobat does it, then that's pretty much the definition of correct behavior. (At least, that was the approach we took when writing our PDF interpreter.) – Derek Aug 21 at 22:40
  • 1
    Anyway I do not use TikZ, so this might not apply there, but in Metapost I would "fix" this with something like subpath(0, length p + eps) of p, so let Metapost loop around and append a minimal start segment of the path after the normal path. Then it is just a normal corner ans everything works. – Marcel Krüger Aug 21 at 23:24
  • 1
    @Cragfelt Sorry, I disagree. These are not closed paths in the question and the correct answer was to draw a single stretch path. I am doing the same here. – marmot Aug 21 at 23:28
up vote 4 down vote accepted

A solution which tries to duplicate the closed path to such that the end is just an ordinary point in the middle: (Inspired by Qrrbrbirlbel's use path TikZ key)

\documentclass[tikz,border=3.14mm]{standalone}
\makeatletter
% This assumes that every closed path starts and ends with these tokens.
% That would make sense, but I do not know if it is true
\def\helpdoublepath\pgfsyssoftpath@movetotoken#1#2#3\pgfsyssoftpath@closepathtoken#4#5{%
  \unexpanded{\pgfsyssoftpath@movetotoken{#1}{#2}#3\pgfsyssoftpath@linetotoken{#1}{#2}#3\pgfsyssoftpath@closepathtoken{#4}{#5}}%
}
\def\doublepath#1{%
  \edef#1{\expandafter\helpdoublepath#1}%
}
\tikzset{double path/.code=\tikz@addmode{\pgfsyssoftpath@getcurrentpath\temp\doublepath\temp\pgfsyssoftpath@setcurrentpath\temp}}
\makeatother
\begin{document}
 \begin{tikzpicture}
   \draw[double path,dash pattern=on 5cm off 100cm,blue,ultra thick]
   (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
  \begin{scope}[xshift=2cm]
  \draw[blue,ultra thick]
   (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
  \end{scope}
 \end{tikzpicture} 
\end{document}

enter image description here

It's been a while since I wrote a PDF interpreter, but I believe you need to specify the line cap:

  \draw[line cap = rect, dash pattern=on 5cm off 16cm,blue,ultra thick]

enter image description here

  • 1
    This only works if the lines meet at an angle of 90°. – Marcel Krüger Aug 21 at 22:20
  • @MarcelKrüger Unfortunately, you are right. – Derek Aug 21 at 22:46
  • Sorry, to me this sounds very much like the \draw[blue,ultra thick] (0,0) -- (1,0) -- (1,1) -- (0,1) -- (0,-\pgflinewidth/2); workaround. Of course, yours is a bit more elegant, but it does not really work for general closed paths. And I do not see why one should have to specify a line cap for a closed path. – marmot Aug 21 at 22:59
  • 1
    @marmot It's not really a closed path. Dashing happens first, then stroking: the path is split into segments specified by the pattern, then each segment is stroked independently of the others. (I believe this behavior dates back to the PostScript days.) So when the path is dash with a long dash pattern, it turns into an unclosed path again. – Derek Aug 21 at 23:09
  • But the first segment is longer than the path, isn't it? And yes, I see that it does not work, at least not for all viewers. Yet I am hoping someone will be able to inject a \pgfpathclose or something of that sort at the right place to cure the problem in a viewer-independent way. – marmot Aug 21 at 23:14

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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