# Decoration of (relative) segments of Bézier curves

I would like to modify a bezier curve in tikz, e.g.

\draw (0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);


in such a way, that a part in the middle is draw with dots (instead of a full solid line), while the start and the end remain solid. This problem I could solve in priciple with the following MWE (see below), but the parameters pre length= and post length= have to be defined in absolute coordinates. How can I change this in order to specify relative positions (e.g. from 0.3 to 0.8 of the path's length?

In particular, there is a \pgfdecoratedpathlength variable (Length of curve in TikZ), but I don't know how to include this in my dotted part of curve definition without getting errors. Or is there a different, even better approach?

MWE:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings,calc}
\begin{document}

\begin{tikzpicture}[scale=1] % <- except of line/dot width drawing should be independent of scaling

\tikzset{
dotted part of curve/.style args={between #1 and #2 with color #3}{
#3,
decorate,
decoration={
markings,
mark=between positions 0 and 1 step 3*\pgflinewidth with{\fill[radius=\pgflinewidth,#3] (0,0) circle;},
pre length=#1,
post length=#2,
pre=curveto,
post=curveto,
%post=moveto, % <-- alternate end: no drawing
}
},
dotted part of curve/.default={between 0.5cm and 0.3cm with color red},
% dotted part of curve/.default={between 0.3 and 0.8 with color red}, % <-- desired: relative positions
}

\draw (0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);
\draw[dotted part of curve] (0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);

\end{tikzpicture}
\end{document}


• ps: the solution should also work with the alternate approach post=moveto, instead of post=curveto, such that there is no line drawn after the dotted part. – kromuchi Jun 22 '16 at 9:25
• are you familiar with meta-decorations? – percusse Jun 22 '16 at 9:36

You can use \pgfdecoratedinputsegmentlength:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\tikzset{
dotted part of curve/.style args={between #1 and #2 with color #3}{
postaction={decorate,draw,#3,
decoration={
markings,
mark=between positions 0 and 1 step 3*\pgflinewidth
pre=curveto, pre length=#1*\pgfdecoratedinputsegmentlength,
post=curveto, post length=(1-#2)*\pgfdecoratedinputsegmentlength
}}},
dotted part of curve/.default={between 0.3 and 0.8 with color red}
}

\begin{document}
\begin{tikzpicture}[scale=1]
\draw
[dotted part of curve]
(0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);
\end{tikzpicture}
\end{document}


Result:

If post=curveto is replaced by post=moveto the result changes to

If there should be no black line in the background you can use \path instead \draw in the code above:

\path% <-
[dotted part of curve]
(0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);


or

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\tikzset{
dotted part of curve/.style args={between #1 and #2 with color #3}{
decorate,
#3,
decoration={
markings,
mark=between positions 0 and 1 step 3*\pgflinewidth
pre=curveto, pre length=#1*\pgfdecoratedinputsegmentlength,
post=curveto, post length=(1-#2)*\pgfdecoratedinputsegmentlength
}},
dotted part of curve/.default={between 0.3 and 0.8 with color red}
}

\begin{document}
\begin{tikzpicture}[scale=1]
\draw
[dotted part of curve]
(0,0) .. controls +(87:2.3) and +(50:-0.7) .. (1,1);
\end{tikzpicture}
\end{document}

• Nice result! I would only change the outer decoration declaration back to #3,decorate,decoration={...} as I don't want to see the black line later (this was added only for demonstration purposes). Apparently, I did't specify this correctly in my question. – kromuchi Jun 22 '16 at 11:23
• @kromuchi I have updated my answer. – esdd Jun 22 '16 at 20:43
• using \path instead \draw is even better. thanks! – kromuchi Jun 23 '16 at 7:59

For a single Bézier curve the basic layer \pgfpathcurvebetweentime command may be useful and certainly much more efficient than a decoration. Unfortunately, there is no TikZ interface by default, but a somewhat crude (although serviceable) approach is shown below:

\documentclass[tikz,border=5]{standalone}
\tikzset{part curve/.style args={%
from #1 to #2 curve #3 .. controls #4 and #5 .. #6}{insert path={
#3 coordinate (@1) #4 coordinate (@2)
#5 coordinate (@3) #6 coordinate (@4)
\pgfextra{\pgfpathcurvebetweentime{#1}{#2}%
{\pgfpointanchor{@1}{center}}{\pgfpointanchor{@2}{center}}%
{\pgfpointanchor{@3}{center}}{\pgfpointanchor{@4}{center}}}
}}}
\begin{document}
\begin{tikzpicture}
\path
(0,0) coordinate (P1)
+(87:2.3) coordinate (P2)
(1,1) coordinate (P4)
+(50:-0.7) coordinate (P3);
\draw [help lines] (P1) .. controls (P2) and (P3) .. (P4);
\draw [red, thick,
part curve={from 0.0 to 0.3 curve (P1) .. controls (P2) and (P3) .. (P4)}];
\draw [green!50!black, thick, dotted,
part curve={from 0.3 to 0.8 curve (P1) .. controls (P2) and (P3) .. (P4)}];
\draw [blue, thick, dashed,
part curve={from 0.8 to 1.0 curve (P1) .. controls (P2) and (P3) .. (P4)}];
\end{tikzpicture}
\end{document}