There are cases where one would want a dash pattern
to be stretchable/shrinkable to fit (in some way) in the path/segment length. For example, consider the the example https://tex.stackexchange.com/questions/133271/can-tikz-dashed-lines-emulate-pstricks-dashed-lines where the on
part of the dash should both start and end the path (changing the off
length and/or the on
length to make the pattern exactly fit in the path length). A more complicated example is a square with edges that should be symmetric.
These can be accommodated with code, such as the one below, but would be better built into tikz/pgf.
For example, dash pattern
on
/off
lengths could be stretchable/shrinkable like standard TeX lengths, such as on 10pt plus 1pt minus 1pt off 10pt plus 3pt minus 3 pt
. This would signal to the underlying pgf code that the pattern should be stretched or shrunk to fit within a path length or within the length of each segment (whether path or segment could be specified by some option, such as dash path
or dash segment
or similar). (Note: glue such as plus 1fil
or plus 3fill
should be accommodated, which would imply that all of the stretch would happen in the on
/off
phase with that infinite stretchability.)
Further, dash phase
would be stretched/expanded similar to the corresponding part of the dash pattern. For example, dash pattern=on 10pt plus 1pt minus 1pt off 5pt,dash phase=5pt
would stretch/shrink the dash phase by half of whatever the on
part of the pattern is stretched/shrunk; dash pattern=on 5pt plus 1pt minus 1pt off 5pt plus 1pt minus 1pt,dash phase=7.5pt
would be stretched/shrunk by as much as the on
part is stretched/shrunk plus HALF of how much the off
part is stretched/shrunk.
Finally, to ensure being able to match at a path/segment end, a corresponding dash endphase
(or similar) could be used to change the phase at the end of the path/segment. For example, consider the nice symmetry of the blue square in the example below; this could be done by exactly computing the correct dash pattern
and dash phase
based on the exact lengths of the sides of the square, but the user shouldn't have to do this calculation to get a nice layout. A dash endphase
equal to the off
phase length would allow the on
phase end at the end of the path/segment. (So the blue box in the example below would be recreated with dash pattern=on 10pt off 6.5pt plus 3.5pt minus 3.5pt,dash phase=2.5pt,dash endphase=9pt,dash segment
.)
(Note: the example below isn't intended to be perfect, and it is not clear that it is perfectly accurate for complicated curve segments.)
\documentclass[tikz,border=5pt]{standalone} \usetikzlibrary{decorations.pathreplacing}% for "show path construction" \tikzset{ cheating dash/.code args={on #1 off #2 ends #3}{% % mostly borrowed from V5 in answer to https://tex.stackexchange.com/questions/133271/can-tikz-dashed-lines-emulate-pstricks-dashed-lines \csname tikz@addoption\endcsname{%Use csname so catcode of @ doesn't have do be changed. \pgfgetpath\currentpath% \pgfprocessround{\currentpath}{\currentpath}% \csname pgf@decorate@parsesoftpath\endcsname{\currentpath}{\currentpath}% \pgfmathparse{max(#1-#3,0)}\let\dashphase=\pgfmathresult% \pgfmathparse{\csname pgf@decorate@totalpathlength\endcsname-#1+2*\dashphase}\let\rest=\pgfmathresult% \pgfmathparse{#1+#2}\let\onoff=\pgfmathresult% \pgfmathparse{max(floor(\rest/\onoff), 1)}\let\nfullonoff=\pgfmathresult% \pgfmathparse{max((\rest-\onoff*\nfullonoff)/\nfullonoff+#2, #2)}\let\offexpand=\pgfmathresult% \pgfsetdash{{#1}{\offexpand}}{\dashphase pt}}% }, cheating dash per segment/.style args={on #1 off #2 ends #3}{ /utils/exec=\csname tikz@options\endcsname,%inherit options/.code={[\csname tikz@options\endcsname]},inherit options, decoration={show path construction, %moveto code={}, lineto code={\draw [cheating dash=on #1 off #2 ends #3] (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);}, curveto code={\draw [cheating dash=on #1 off #2 ends #3] (\tikzinputsegmentfirst) .. controls (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb) .. (\tikzinputsegmentlast);}, closepath code={\draw [cheating dash=on #1 off #2 ends #3] (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);} }, decorate, }, } \begin{document} \begin{tikzpicture}[every node/.style={above,align=center,font=\tiny},mylines/.style={ultra thick,line cap=rect,line join=square}] \draw[mylines,red,dash pattern=on 10pt off 6.5pt] (0,0) rectangle (2,2); \node[red] at (1,2) {normal dash pattern\\on 10pt off 6.5pt}; \tikzset{xshift=2.5cm} \draw[mylines,green!50!black,cheating dash=on 10pt off 6.5pt ends 7.5pt] (0,0) rectangle (2,2); \node[green!50!black] at (1,2) {expandable dash gaps\\over entire path}; \tikzset{xshift=2.5cm} \draw[mylines,blue,cheating dash per segment=on 10pt off 6.5pt ends 7.5pt] (0,0) rectangle (2,2); \node[blue] at (1,2) {expandable dash gaps\\per segment}; \end{tikzpicture} \end{document}