3

I have a GeoJSON of two obvious colliding polygons but turf.intersect doesn't seem to detect it. Here the GeoJSON:

{
    "type": "FeatureCollection",
    "name": "invalid_import",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "date": 1590602058.0,
                "id": "7",
                "source": "import"
            },
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [
                            2.44017442,
                            48.85857136
                        ],
                        [
                            2.44009857,
                            48.85852694
                        ],
                        [
                            2.44008622,
                            48.85853408
                        ],
                        [
                            2.44002591,
                            48.85856617
                        ],
                        [
                            2.44002998,
                            48.85856799
                        ],
                        [
                            2.44004488,
                            48.85857615
                        ],
                        [
                            2.44007471,
                            48.85859068
                        ],
                        [
                            2.44012622,
                            48.858617
                        ],
                        [
                            2.44020755,
                            48.85865875
                        ],
                        [
                            2.44028046,
                            48.85859614
                        ],
                        [
                            2.4402805,
                            48.85859254
                        ],
                        [
                            2.44029317,
                            48.85855483
                        ],
                        [
                            2.44027994,
                            48.8585179
                        ],
                        [
                            2.44027865,
                            48.8585116
                        ],
                        [
                            2.44023072,
                            48.85853206
                        ],
                        [
                            2.44022114,
                            48.85853561
                        ],
                        [
                            2.44019503,
                            48.85855527
                        ],
                        [
                            2.44017442,
                            48.85857136
                        ]
                    ]
                ]
            }
        },
        {
            "type": "Feature",
            "properties": {
                "date": 1590602058.0,
                "id": "9",
                "source": "import"
            },
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [
                            2.440162118818979,
                            48.858685195947597
                        ],
                        [
                            2.440114118818979,
                            48.858712855947597
                        ],
                        [
                            2.440031568818979,
                            48.85865760594759
                        ],
                        [
                            2.44006308881898,
                            48.85864156594759
                        ],
                        [
                            2.440130268818979,
                            48.858605005947598
                        ],
                        [
                            2.440228978818979,
                            48.858551505947598
                        ],
                        [
                            2.440270858818979,
                            48.85858588594759
                        ],
                        [
                            2.44012556881898,
                            48.85866164594759
                        ],
                        [
                            2.440162118818979,
                            48.858685195947597
                        ]
                    ]
                ]
            }
        }
    ]
}

I use leaflet for loading these datas into layers and then use turf this way:

layer1Turf = turf.polygon(layer1.toGeoJSON().geometry.coordinates);
layer2Turf = turf.polygon(layer2.toGeoJSON().geometry.coordinates);
turfIntersect = turf.intersect(layer1Turf, layer2Turf);

but turfIntersect is just null.

Do you know what could be the wrong part of my process?

  • Very interesting, since turf.difference gives a result. Couldn't yet figure out what's wrong. – TomazicM May 27 at 22:00
  • I made a REPL for this and I must say I'm puzzled as well. – IvanSanchez May 28 at 4:25
2

TurfJS just fails to calculate intersections with highly-detailed geometries - internally, it will truncate the precision of the geometries' coordinates to about 6 decimal digits.

A bit of digging uncovers that there's some discussion about the issue at https://github.com/Turfjs/turf/issues/1118 . There are deeper concerns here because the underlying code struggles to detect thin sliver-like intersections.

The code has already been changed to use a different algorithm (i.e. the Martínez-Rueda algorithm instead of the JSTS suite), but the distributed files for Turf version 5.1.6 (the latest at the time of this writing) still use JSTS with truncated coordinates.

A possible approach at the time of this writing is to use the experimental, not-fully-tested, probably-fails-in-some-weird-scenario turf version 6. This can be done by replacing

<script src='https://unpkg.com/@turf/turf/turf.min.js'></script>

with

<script src='https://unpkg.com/@turf/turf@6.2.0-alpha.1/dist/turf.min.js'></script>

That seems to work fine, as can be seen in this working example.

Another alternative is to use the implementation of the Martínez-Rueda algorithm directly, but that might require a little bit of extra plumbing on your part.

| improve this answer | |
  • Thanks for detective work! Good to know, since I use turf.intersect quite a lot. – TomazicM May 28 at 5:28
  • Thank you for your answer. However in my case, 6 digits seem to be precised enough to detect the collision. The leaflet toGeoJSON use 6 digits too by default. However, I will try what you are suggesting and use the 6.2.0 version ! – ArKham May 28 at 7:21
  • Yeah, 6 digits seems to be precise enough, but reducing the precision in your data makes Turf fail a sanity check for self-intersecting polygons and then panic, as far as I could see. (Your raw data looks non-self-intersecting to a Turf subroutine, but the truncated-precision data does look self-intersecting and thus invalid) – IvanSanchez May 28 at 11:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.