[GIS] Turf intersect doesn’t always work with polygons

geojsonintersectionleafletpolygonturf

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?

Best Answer

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.