Search code examples
d3.jstopojsonturfjs

D3.js with Turf.js error: "Uncaught (in promise) Error: Each LinearRing of a Polygon must have 4 or more Positions."


I'm trying to loop through a series of polygons to see if my single point exists in one of those polygons. From what I've read I need to import the topojson, convert it to a geojson object, and loop through each polygon checking the point. Here's what I have using D3, Topojson and Turf...

const point = turf.point([long, lat]);
d3.json('data/myAreas.json').then((myAreas) => {
    const keys = Object.keys(myAreas.objects);
    const geo = topojson.feature(myAreas, myAreas.objects[keys[0]]);
    geo.features.forEach((area) => {
      const searchWithin = turf.polygon([[area.geometry.coordinates[0]]]);
      const ptsWithin = turf.pointsWithinPolygon(point, searchWithin);
      console.log('ptsWithin?', ptsWithin);
    });
});

When it gets to const searchWithin = turf.polygon([[area.geometry.coordinates[0]]]); it throws the following error...

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

I've tried D3's d3.geoContain() but it threw false every time. I'm open to alternative solutions that will check to see if a lat/lng coordinate is within a topojson shape. Thanks.


Solution

  • So this is what ended up working for me, replacing turf.polygon() with turf.multiPolygon

    const point = turf.point([long, lat]);
    d3.json('data/myAreas.json').then((areas) => {
      const keys = Object.keys(areas.objects);
      const geo = topojson.feature(areas, areas.objects[keys[0]]);
      geo.features.forEach((k, i) => {
        const searchWithin = turf.multiPolygon([[k.geometry.coordinates[0]]]);
        const ptsWithin = turf.pointsWithinPolygon(point, searchWithin);
        if (ptsWithin.features.length > 0) {
          console.log('ptsWithin?', i, ptsWithin); // The index of the containing polygon
          console.log(geo.features[i]); // The features for the corresponding polygon
        }
      });
    });