jts icon indicating copy to clipboard operation
jts copied to clipboard

Unexpected output from OffsetCurve.getCurve() since jts-version 1.20.0

Open Grimnir42 opened this issue 4 months ago • 2 comments

Hi! I recently updated my jts-version from 1.19.0 to 1.20.0 and stumbled across some unexpected output from the OffsetCurve.getCurve() method. I use this method to create lines with a constant distance, but after updating to 1.20.0, the output changed. This code was used to create the images below:

    GeometryFactory geometryFactory1 = new GeometryFactory();

    LineString testLineString = geometryFactory1.createLineString(new Coordinate[]{
            new Coordinate(-477.9727884893793, 726.8346522633758),
            new Coordinate(-278.5761790410716, 469.3177193695431),
            new Coordinate(-79.17956959276393, 211.80078647571045),
            new Coordinate(-74.10825983114643, 205.2512862651522),
            new Coordinate(-61.59032155710979, 183.66416102497575),
            new Coordinate(-56.17516937041343, 177.39645645603244),
            new Coordinate(-45.87664216572637, 163.28009296700202),
            new Coordinate(-32.80606824944878, 140.06145723770865),
            new Coordinate(-26.625732783814613, 132.27313760006422),
            new Coordinate(-20.81619693653508, 123.16499838643774),
            new Coordinate(-15.495636510039938, 116.78652899133516),
            new Coordinate(-9.117773193378609, 108.03384392886659),
            new Coordinate(9.065051143785869, 79.15745454413279),
            new Coordinate(25.818482523651234, 55.05549100891343),
            new Coordinate(211.71012482617877, -212.37351996146882),
            new Coordinate(397.60176712870623, -479.8025309318511)});

    for (int i = 1; i < 100; i++) {
        LineString offsetCurve = (LineString) (OffsetCurve.getCurve(testLineString,
                -i * 0.775).getGeometryN(0));
    }

Using this code with jts-version 1.19.0, I got this image (zoomed in into the "interesting" part):

Image

With 1.20.0, I got this:

Image

Zoomed in:

Image

I hope, you can see the gaps between some of the offset curves. Since I need the output of version 1.19.0, I wanted to ask if this is some kind of bug or if the behaviour of getCurve() changed. Is there a way to get the output of 1.19.0 by calling the method with different parameters?

(Additional note: I checked the output of the code above for older versions and the behaviour changed with the commit "Improve Buffer ring simplfication" (22.11.2023).)

Thanks in advance!

Grimnir42 avatar Sep 03 '25 10:09 Grimnir42

As you suggest, this is a behaviour change between 1.19 and 1.20, due to the code change in #1022. Input line simplification was introduced to improve performance and robustness. For many use cases the slight decrease in accuracy is worth the tradeoff.

The good news is that OffsetCurve can be called with a BufferParameters object, and that exposes the setSimplifyFactor method to specify the simplification factor used. Using a smaller factor will cause less simplification, and increase the accuracy of the result. For this case using a factor of 0.001 works well (the default is 0.01).

Here's how to use the parameter:

BufferParameters params = new BufferParameters();
params.setSimplifyFactor(simplifyFactor);
OffsetCurve oc = new OffsetCurve(geom, distance, params);
Geometry result =  oc.getCurve();

SimplifyFactor = 0.01

Image

SimplifyFactor = 0.001

Image

Some bad news is that there is a bug in 1.20 which means OffsetCurve doesn't respect the simplifyFactor parameter.

More good news is that this is fixed by #1151.

dr-jts avatar Sep 18 '25 03:09 dr-jts

Thank you very much for the explanation and the quick fix! That was very helpful!

Grimnir42 avatar Sep 22 '25 07:09 Grimnir42