locationtech / locationtech/jts

GeometrySnapper.snapToSelf can produce an incorrect polygonal result when multiple target vertices are within the snap tolerance

Open
#1,231 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
2.2k
Forks
475
Avg merge
14d 10h
Merged PRs (30d)
1

Description

JTS version
JTS 1.20.0

GeometrySnapper.snapToSelf produces an unexpected result for the following valid MultiPolygon when using a snap tolerance of 0.005.

With cleanResult = false, self-snapping can create invalid/local self-intersecting polygon topology.
With cleanResult = true, the subsequent cleanup can then produce a substantially different polygonal result.

`import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.operation.overlay.snap.GeometrySnapper;

public class SnapToSelfReproducer {

private static final String WKT =
        "MULTIPOLYGON (((641868.09 411913.34, " +
                "641884.99 411907.36, " +
                "641917.6671767097 411902.33050147054, " +
                "641901.3852557734 411849.6517192838, " +
                "641853.7924351022 411866.8991175313, " +
                "641868.09 411913.34)), " +
                "((641917.6679652191 411902.33038010733, " +
                "641901.3863761591 411849.65131326165, " +
                "641901.3857792952 411849.65152956214, " +
                "641917.6675451562 411902.3304447612, " +
                "641917.6679652191 411902.33038010733)))";

public static void main(String[] args) throws Exception {
    Geometry input = new WKTReader().read(WKT);

    Geometry snapped =
            GeometrySnapper.snapToSelf(input, 0.005, false);

    Geometry snappedAndCleaned =
            GeometrySnapper.snapToSelf(input, 0.005, true);

    System.out.println("Input valid: " + input.isValid());
    System.out.println("Input area: " + input.getArea());

    System.out.println();
    System.out.println("snapToSelf(cleanResult=false)");
    System.out.println("Valid: " + snapped.isValid());
    System.out.println("Area: " + snapped.getArea());
    System.out.println(snapped);

    System.out.println();
    System.out.println("snapToSelf(cleanResult=true)");
    System.out.println("Valid: " + snappedAndCleaned.isValid());
    System.out.println("Area: " + snappedAndCleaned.getArea());
    System.out.println(snappedAndCleaned);
}

}`

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with GeometrySnapper.snapToSelf and run the SnapToSelfReproducer using the supplied WKT, tolerance, and cleanResult values. Compare validity, area, and polygonal output for both modes; done means self-snapping no longer creates invalid topology or an unexpected cleaned result.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.