0

I'm getting the following error:

Uncaught (in promise) Error: Each LinearRing of a Polygon must have 4 or more Positions.

when trying to use @turf/turf module:

async function selectSubregion(e) {
        e.preventDefault();

        const subRegion = e.target.value;
        const geoJsonData = await GeoJSON();

        subFilterResults(subRegion);

        if (geojsonLayer) {
            map.removeLayer(geojsonLayer);
        }

        console.log(subRegion);
        console.log(geoJsonData);

        geoJsonData.features.forEach((feature) => {
            console.log(feature.properties.COUNTRY);
        });
        // Find corresponding feature in geojsonData
        const feature = geoJsonData.features
            .filter((feature) => {
                if (feature.geometry.type === 'Polygon') {
                    return feature.geometry.coordinates.every((ring) => ring.length >= 4);
                }

                if (feature.geometry.type === 'MultiPolygon') {
                    return feature.geometry.coordinates.every((polygon) =>
                        polygon.every((ring) => ring.length >= 4)
                    );
                }

                return false;
            })
            .find((feature) => feature.properties.COUNTRY === subRegion);
            // .find((feature) => feature.properties.NAME_EN === subRegion);

        console.log('feature:', feature);

        if (feature) {
            // Highlight the feature on the map
            geojsonLayer = L.geoJSON(feature, {
                style: {
                    color: '#06c',
                    weight: 1,
                    fillOpacity: 0.3
                }
            }).addTo(map);

            // Remove markers outside the selected region
            allMarkers.forEach((marker) => {
                // Using turf to check if the marker is outside the selected feature
                const point = turf.point([marker.getLatLng().lng, marker.getLatLng().lat]);
                
                const polygon = turf.polygon(feature.geometry.coordinates);

                console.log('point:', point, 'polygon:', polygon);
                if (!turf.booleanPointInPolygon(point.geometry.coordinates, polygon)) {
                    // Remove marker if it's outside
                    map.removeLayer(marker);
                }
            });
        }
    }
7
  • 2
    SInce the input data is defective, you'd need to provide it in the Question for resolution.
    – Vince
    Dec 3, 2023 at 0:34
  • updated with link to shp files.
    – chovy
    Dec 3, 2023 at 6:45
  • There is no usage of turf in your code. Please add that part.
    – TomazicM
    Dec 3, 2023 at 7:47
  • I suppose your World_Countries_Generalized.shp comes from here: hub.arcgis.com/datasets/esri::world-countries-generalized/about. There's also GeoJSON available for download at this site. Did you try that one?
    – TomazicM
    Dec 3, 2023 at 14:06
  • For me GeoJSON itself, converted with the online Mapshaper from World_Countries_Generalized.shp and displayed in Leaflet works perfectly well. Where did your try to use turf?
    – TomazicM
    Dec 3, 2023 at 16:23

2 Answers 2

1

When you create polygon from selected feature coordinates with turf.polygon function, you have to take into account that selected feature might be polygon or multipolygon.

You have to check geometry type of the feature and then create either polygon with the turf.polygon function or multipolygon with the turf.multiPolygon function.

Relevant part of the code would then look something like this:

allMarkers.forEach((marker) => {
  const point = turf.point([marker.getLatLng().lng, marker.getLatLng().lat]);
  var polygon;
  if (feature.geometry.type == 'MultiPolygon')
    polygon = turf.multiPolygon(feature.geometry.coordinates);
  else {
    polygon = turf.polygon(feature.geometry.coordinates);
  }
  if (!turf.booleanPointInPolygon(point.geometry.coordinates, polygon)) {
    map.removeLayer(marker);
  }
});
11
  • it seems the last forEach isn't doing anything with the data. I'm confused.
    – chovy
    Dec 4, 2023 at 7:04
  • That's not true, it displays polygon to console with console.log('From Polygon', polygon);. You can of course do with polygons whatever you want to do. Code above is just to show that's it's possible to create polygons with turf from your GeoJSON source without any errors.
    – TomazicM
    Dec 4, 2023 at 7:54
  • I don't understand how this fixes the problem.
    – chovy
    Dec 4, 2023 at 16:41
  • I suppose your problem happens at this statement: const polygon = turf.polygon(feature.geometry.coordinates);. If you tell where feature is coming from (include more related code in the question), I might be able help you.
    – TomazicM
    Dec 4, 2023 at 16:48
  • const features = geoJsonData.features
    – chovy
    Dec 4, 2023 at 19:17
0

This is how I fixed it:

            // Remove markers outside the selected region
            allMarkers.forEach((marker, index) => {
                const markerPoint = turf.point([marker.getLatLng().lng, marker.getLatLng().lat]);
                let isInside = false;

                if (feature.geometry.type === 'Polygon') {
                    const regionPolygon = turf.polygon(feature.geometry.coordinates);
                    isInside = turf.booleanPointInPolygon(markerPoint, regionPolygon);
                } else if (feature.geometry.type === 'MultiPolygon') {
                    for (const polygonCoords of feature.geometry.coordinates) {
                        const regionPolygon = turf.polygon(polygonCoords);
                        if (turf.booleanPointInPolygon(markerPoint, regionPolygon)) {
                            isInside = true;
                            break; // Break out of the loop if the marker is inside one of the polygons
                        }
                    }
                }

                if (!isInside) {
                    map.removeLayer(marker);
                }
            });

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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