A single-sided buffer is the polygon formed by connecting a LineString to an offset curve generated on one side of the line.
Naturally either side can be specified, by choosing an appropriate sign for the offset distance (positive for the right side, negative for the left).
At the moment there's a bit of a limitation, in that input linework with very narrow concave angles (relative to the buffer distance) create undesirable artifacts in the generated polygon. I'm hoping that some further thinking will come up with a way to avoid this, at least in most normal cases.
This functionality is accessed by setting an appropriate flag in the BufferParameters structure:
BufferParameters bufParams = new BufferParameters();
bufParams.setSingleSided(true);
return BufferOp.bufferOp(geom, distance, bufParams);
Currently this code is in SVN. It will be released in JTS 1.12 (which will hopefully be shipping
Hey interesting!
ReplyDeleteActually, I was looking into doing something similar: offset lines.
However an offset line would have to be allowed to intersect itself.
Applications would be various:
- apply a repeating symbol on one side of a given line (common in certain type of cartography, e.g., depicting fault lines)
- label along a line with perpendicular offset
Would it be hard to derive a "offset line" algorithm from your "single side buffer" one?
Great. Thanks for all Martin.
ReplyDeleteA JTS fan
@Andrea:
ReplyDeleteIn fact my original goal was to develop an offset line algorithm, but it turned out to be quite tricky to implement. The single-sided buffer turned out to be easier to implement (at least in the current limited form), so that's why it got done so quickly.
I'm still thinking about doing offset lines, though. GEOS has an implementation of this, which I might try copying. I think it still has limitations, though.
One thing the GEOS algorithm definitely doesn't do is to create self-intersecting lines. I think I understand why you want this, but I'm not sure if it's truly possible to do this in a consistent way. More thought required!
Yeah, I hear your pain. I've tried to cook my own implementation of an offset line algorith. It works fine as long as the offset distance is less than the segment lengths, but once it goes above all sorts of issues pop up. Could not fix it.. :-(
ReplyDeleteAlso looked at various other implementations, MapServer has one, GRASS too, and in some way or the other they all fail in some case (some create huge spikes on sharp angles, other fail to respect the offset distance in some cases, and so on)
You've said: It will be released in JTS 1.1.2. Is it correct? Or do you mean 1.12?
ReplyDeleteI can't find setSingleSided method in jts 1.11 downloaded from source forge...
;)
Er, yes, I meant 1.12.
ReplyDeleteThat should be released Real Soon Now.
It's a bit of a hack, but one way that I found to get the offset line is to use the single sided offset buffer and remove the original line and the last, closing point. If the original line was well formed and had no duplicates, then removing the original line is easy. This obviously wouldn't work if the original line self-intersected, because in that case the noding may change.
ReplyDeleteA proper implementation would obviiously be much better, but for me this was a useful quick-and-dirty hack. I'll change my code once the full implemtation is done.