jts icon indicating copy to clipboard operation
jts copied to clipboard

Specific Small buffer of a polygon returns an empty geometry

Open Tygron opened this issue 4 months ago • 1 comments

Dear Dr JTS,

In our codebase we use erode and dilate buffers (of 0.01) to clean up polygons and multi-polygons.

Recently we have updated our version of JTS and came across the same issues as described in [https://github.com/locationtech/jts/issues/908] Issue 908.

I did some testing on small buffers that previously worked but that are now failing. See the simple code below:

` GeometryFactory sourceFactory = new GeometryFactory(new PrecisionModel(1000d));

    LinearRing linearRing = sourceFactory.createLinearRing(new Coordinate[] { //
            new Coordinate(238.726, 732.955), //
            new Coordinate(229.698, 728.655), //
            new Coordinate(215.57, 758.315), //
            new Coordinate(224.598, 762.615), //
            new Coordinate(238.726, 732.955) });

    Polygon polygon = sourceFactory.createPolygon(linearRing);

    BufferOp bufferOp = new BufferOp(polygon, new BufferParameters());

    Geometry bufferedGeometry = bufferOp.getResultGeometry(-0.009);
    assertFalse(bufferedGeometry.isEmpty()); // Succeeds

    bufferedGeometry = bufferOp.getResultGeometry(-0.011);
    assertFalse(bufferedGeometry.isEmpty()); // Succeeds

    bufferedGeometry = bufferOp.getResultGeometry(-0.01);
    assertFalse(bufferedGeometry.isEmpty()); // Fails

    bufferedGeometry = new BufferOp(bufferOp.getResultGeometry(-0.009), new BufferParameters()).getResultGeometry(-0.001);
    assertFalse(bufferedGeometry.isEmpty()); // Also Fails

    bufferedGeometry = new BufferOp(bufferOp.getResultGeometry(-0.011), new BufferParameters()).getResultGeometry(0.001);
    assertFalse(bufferedGeometry.isEmpty()); // Succeeds

`

I wonder why it fails specifically on the 0.01 buffer and whether this is an issue in the heuristics.

Tygron avatar Aug 25 '25 08:08 Tygron

This is probably caused by the same thing causing #908. And the suggestion for a workaround is the same: compute the buffer using Floating precision, and then round the result to the desired precision.

dr-jts avatar Aug 25 '25 22:08 dr-jts