Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stretchable dash patterns to fit path/segment lengths #629

pgf-tikz-bot opened this issue Jun 22, 2017 · 0 comments


2 participants
Copy link

commented Jun 22, 2017

Migrated from SourceForge
Author: johnsone
Timestamp: 2017-06-22 07:56:25.169000

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 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.)

example image


\usetikzlibrary{decorations.pathreplacing}% for "show path construction"
    cheating dash/.code args={on #1 off #2 ends #3}{%
    	% mostly borrowed from V5 in answer to
        \csname tikz@addoption\endcsname{%Use csname so catcode of @ doesn't have do be changed.
            \csname pgf@decorate@parsesoftpath\endcsname{\currentpath}{\currentpath}%
            \pgfmathparse{\csname pgf@decorate@totalpathlength\endcsname-#1+2*\dashphase}\let\rest=\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);}

\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};


\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};


\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};


@hmenke hmenke removed the open label Apr 2, 2019

hmenke added a commit to hmenke/pgf that referenced this issue Jul 10, 2019

hmenke added a commit to hmenke/pgf that referenced this issue Jul 10, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.