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:

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.
– Andrew StaceyNov 15 '10 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.
– Grigory MNov 15 '10 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...
– Grigory MNov 15 '10 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.
– Andrew StaceyNov 16 '10 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.
– Grigory MNov 16 '10 at 9:36

4 Answers
4

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.

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:

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.

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.

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.
– Andrew StaceyNov 16 '10 at 8:14

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.
– Andrew StaceyNov 16 '10 at 12:17

1

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.
– Andrew StaceyNov 16 '10 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.

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.