locationtech / jts

The JTS Topology Suite is a Java library for creating and manipulating vector geometry.
Other
1.95k stars 440 forks source link

Calculating difference and intersection between two polygons is resulting in a polygon having incorrect shape #1030

Open s6ch13 opened 8 months ago

s6ch13 commented 8 months ago

Calculating difference and intersection between two polygons is resulting in a polygon having incorrect shape. Could have something to do with PrecisionModel. This is seen with v1.19 and also the latest 1.20 snapshot.

public static void intersectionDifference() throws ParseException {

    GeometryFactory gf = new GeometryFactory();

    Coordinate[] c1 = new Coordinate[] { 
            new Coordinate(3.5,2), 
            new Coordinate(3, 3.5), 
            new Coordinate(5, 2.5),
            new Coordinate(3.5, 2) };
    Geometry polygon1 = gf.createPolygon(gf.createLinearRing(c1), null);

    Coordinate[] c2 = new Coordinate[] { 
            new Coordinate(3, 2.5), 
            new Coordinate(5, 2.5),
            new Coordinate(5,3.5), 
            new Coordinate(3, 3.5), 
            new Coordinate(3, 2.5) };
    Geometry polygon2 = gf.createPolygon(gf.createLinearRing(c2), null);

    System.out.println("input");
    System.out.println(polygon1.toString());
    System.out.println(polygon2.toString());

    Geometry intersection = polygon1.intersection(polygon2);
    System.out.println("Geometry intersection");
    System.out.println(intersection.toString());

    Geometry d1 = polygon1.difference(intersection);
    System.out.println("polygon difference 1");
    System.out.println(d1.toString());
}

Result : input POLYGON ((3.5 2, 3 3.5, 5 2.5, 3.5 2)) POLYGON ((3 2.5, 5 2.5, 5 3.5, 3 3.5, 3 2.5)) Geometry intersection POLYGON ((3.3333333333333335 2.5, 3 3.5, 5 2.5, 3.3333333333333335 2.5)) polygon difference 1 POLYGON ((3.5 2, 3 3.5, 3.3333333333333335 2.5, 5 2.5, 3.5 2))

Expected result : polygon difference 1 should be POLYGON((3.3333333333333335 2.5, 5 2.5, 3.5 2, 3.3333 2.5))

Scan2024-01-18_192927

This may have something to do with precision model. This works correctly If i set the geometry factory to

GeometryFactory gf = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING_SINGLE));

But there are other similar cases which work with default precision model fail with PrecisionModel.FLOATING_SINGLE.

This issue may be related to https://github.com/locationtech/jts/issues/990

dr-jts commented 6 months ago

This is definitely a numerical robustness issue.

This code is using the old overlay implementation, which is more subject to robustness issues. It's better to change to using OverlayNG. You can do this via setting the system property jts.overlayng, or calling OverlayNGRobust directly.