# Draw only some segments of a path in TikZ?

Is there a good way to create a path in TikZ only some segments of which are stroked? I want to create the whole path in a single command so that it can be filled, but I also want to stroke some parts of the boundary of the filled region, but not all of them. The best solution I've thought of so far is to use edge operations in the middle of the path to do the stroking; for instance here is a green-filled square with one edge stroked:

\path[fill=green] (0,0) -- (1,0) edge (1,1) -- (1,1) -- (0,1) -- cycle;


This is a little better than

\path[fill=green] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
\draw (1,0) -- (1,1);


but it still requires giving the command that draws the segment from (1,0) to (1,1) twice, which is annoying and error-prone if it's a more complicated command like a Bézier curve, and impossible if it's something like a circular arc that can't be drawn by a edge command (at least, not without writing a custom "to path"). Any suggestions?

• I should add that I wondered if some variant of the solution of the postaction question would work here. Specifying a postaction that split the path up into segments and then drew only part of it. Also, one of the "path replacing" decorations replaces pieces of paths by other things, so I'm sure that something is possible. Commented Nov 15, 2010 at 21:38
• @Andrew \pgfusepath fills and/or draws the current path and then destroys it (and AFAIK there can be only one path at any moment). So it's not hard to define a decoration that just draws a path and apply it to a subpath -- but it won't leave any path that can be filled. Commented Nov 15, 2010 at 23:22
• the only thing I can think about is that one can define a decoration that saves all path-constructing commands into some variable that can be used latter... Commented Nov 15, 2010 at 23:24
• @Grigory: couldn't that be combined with a post/pre action? That effectively duplicates the path, so do it once with the \pgfusepath and once with the fill. Commented Nov 16, 2010 at 8:10
• @Andrew Probably. The problem is, I don't know how to combine "\path .. decorate" (that allows to apply a decoration to a subpath) with "postaction={decorate}". Anyway, I really wonder, how postaction is implemented -- if it stores the path somehow it's just what we need here. Commented Nov 16, 2010 at 9:36

This is a reworking of Jan's code to make it a little more TikZ-like. It still does the same thing: repeats the path, once as a fill and once as a draw, but with certain parts of the path removed for the draw stage. The main modification is that (hopefully) it now looks exactly like a standard TikZ command.

\documentclass{article}

\usepackage{tikz}
\makeatletter
\long\def\my@drawfill#1#2;{%
\@skipfalse
\fill[#1,draw=none] #2;
\@skiptrue
\draw[#1,fill=none] #2;
}

\newif\if@skip

\newcommand{\skipit}[1]{%
\if@skip
\else
#1
\fi
}

\newcommand{\drawfill}[1][]{%
\my@drawfill{#1}}
\makeatother

\begin{document}
\begin{tikzpicture}
\drawfill[fill=green,draw=blue,ultra thick] (0,0) -- (0,1) \skipit{--} (1,1) -- (1,0) \skipit{.. controls +(0,-1) and +(0,-1) ..} (0,0);
\end{tikzpicture}
\end{document}


This produces:

I'm sure that there are additional improvements to be made, which is one reason why I'm making this community wiki (the other being that it is really Jan's answer). In particular:

1. I couldn't make the \skipit command take an optional argument and still work. I think that it doesn't get expanded properly before the genuine TikZ commands see it and they don't like having macros as part of their path specification.

2. The assignment of key-value pairs is a bit of a hack: basically, we turn off the drawing on the fill command and turn off the filling on the draw command. It might be useful to be able to specify a set of keys that only get put on the draw command and a set for the fill command, so something like \drawfill[options for both, fillopt={options for fill}, drawopt={options for draw}] but I don't know enough (anything) about pgfkeys so don't have a clue how to go about that.

• Can arcs also be skipped? Commented Jul 24, 2014 at 14:14

If I understand correctly, what you want to do is to only have to enter the path once. Would something like this work (it does not follow usual tikz syntax, but that should not be that hard to fix)?

\documentclass[]{article}
\usepackage{tikz}

\def\drawfill#1#2#3{{\def\skip{--}\fill[#1]#3;}{\def\skip{}\draw[#2]#3;}}
\begin{document}
\begin{tikzpicture}
\drawfill{fill=green}{very thick}{(0,0) -- (0,1) \skip (1,1) -- (1,0)\skip (0,0)}
\end{tikzpicture}
\end{document}

• I would modify it a little so that the \skip takes an argument which is the piece of the path to typeset. That way, you could say \skip{ .. controls +(1,0) and +(1,0) .. } and have it do the Right Thing. Commented Nov 16, 2010 at 8:14
• @Andrew: Even better, have an optional argument, defaulting to --. Commented Nov 16, 2010 at 8:39
• Nice. Being a perfectionist, I wish one could specify the \skip as part of an actual path, but it doesn't seem that TikZ likes to have macros expand to path components. So \draw (0,0) \mypath (1,0); doesn't work. Commented Nov 16, 2010 at 12:17
• I'm beginning to think that this is the only reasonable way to do it. After experimenting a little, I find that it comes down to wanting to construct two different paths that are related. Once the paths are constructed internally as pgf paths (however that is represented), they can't be split up or have stuff applied to just a segment. So the only time to change Big Stuff is when the paths are defined, and that means that, TeXnically, you have to enter it twice. Of course, you don't actually have to enter it twice, but you have to convince TikZ that you did so - which is what this does. Commented Nov 16, 2010 at 16:54

I've found a new answer to this using the decorations library. We use the show path construction decoration to split the path up in to sections. We only render the pieces if a certain flag is set. The trick is to figure out a way to input the path in such a way that we can specify the flag switching without significantly disturbing the path. The method I settled on was to use a line of zero length as a toggle.

\documentclass{standalone}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing}

\newbool{partpath}
\pgfkeys{/tikz/partial rendering/.style={
postaction={
decorate,
decoration={
show path construction,
moveto code={
\global\booltrue{partpath}
},
lineto code={
\ifx\tikzinputsegmentfirst\tikzinputsegmentlast
\ifbool{partpath}{\global\boolfalse{partpath}}{\global\booltrue{partpath}}
\fi
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
}{}
},
curveto code={
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) .. controls (\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb) .. (\tikzinputsegmentlast);
}{}
},
closepath code={
\ifbool{partpath}{
\draw (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);
}{}
}
}
}
}
}

\begin{document}

\begin{tikzpicture}
\path[fill=green,partial rendering]
(0,0) -- (0,1) -- +(0,0) -- (1,1) -- +(0,0) -- (1,0) -- +(0,0) .. controls +(0,-1) and +(0,-1) .. (0,0);
\end{tikzpicture}

\end{document}


All those -- +(0,0)s are there to toggle the rendering when the path is drawn for the second time. (I tried using empty movetos: just +(0,0), but having those there messed up the fill routine.) Result:

I'd like to be proven wrong, but I think this is impossible without drawing the path twice. Section 12.3.3 of the TikZ manual (v2.10) states:

Note that many options apply only to the path as a whole and cannot be scoped in this way. For example, it is not possible to scope the color of the path. See the explanations in the section on paths for more details.

And section 14.16:

When TikZ encounters and opening or a closing brace ({ or }) at some point where a path operation should come, it will open or close a scope. All options that can be applied “locally” will be scoped inside the scope. For example, if you apply a transformation like [xshift=1cm] inside the scoped area, the shifting only applies to the scope. On the other hand, an option like color=red does not have any effect inside a scope since it can only be applied to the path as a whole.

The problem seems to be that the dash pattern is applied to the path as a whole. Most of the time this is a good thing because it means that dashes work nicely across corners.

So I'd break the this up into several commands:

\begin{tikzpicture}
\path[fill=green] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;
\draw (1,1) -- (0,1) -- (0,0) -- (1,0);
\draw[dashed] (1,0) -- (1,1);
\end{tikzpicture}


For more complicated paths, you might want to store some parts of the path into TeX macros.