1
votes

This is on the frontend side. I'm using turf.js.

Scenario: Get all warnings and incidents within 10km of my current location.

I'm getting live geojson feed that contains warnings or incidents with lots of features some having their geometry.type='Point' || geometry.type='MultiPolygon' || geometry.type='GeometryCollection'.

What I have done so far:

Create a buffer feature area with my current coordinates and comparing if an incident has occurred near me(10km).

If geometry.type='Point' I'm comparing using turf.inside(point, bufferPolygon), and this is working fine.

The challenge is when it's not a point, say a MultiPolygon or a GeometryCollection which has MultiPolygons in it.

The only other method that I can use to find that accepts polygon in both parameter is turf.intersect(polygon, bufferPolygon).

Here, I don't get geometry.type ='Polygon' in my feed but it is a MultiPolygon or GeometryCollection (having MultiPolygons).

if(feature.geometry.type === 'Point') {
    if(turf.inside(feature, bufferPolygon)) {
        console.log("inside");
        feature.properties.feedType === 'warning' ? warningsNearBy++ : incidentsNearBy++;
    }
} else {
    if(feature.geometry.type === 'GeometryCollection') {
        $.each(feature.geometry.geometries, function(index, geo) {
            if(geo.type === 'MultiPolygon') {
                //console.log('MP:', geo.coordinates[0]);
                var convertToPolygon = turf.polygon(geo.coordinates[0]);
                console.log('convertToPolygon:',convertToPolygon);
                //console.log('MP:intersect',turf.intersect(polygon, bufferPolygon));
                var isIntersecting = turf.intersect(convertToPolygon, bufferPolygon);
                if(isIntersecting) {
                    feature.properties.feedType === 'warning' ? warningsNearBy++ : incidentsNearBy++;
                }
            } else if(geo.type === 'GeometryCollection') {
                console.log('GC:', geo);
            }
        });
    } else {
        console.log('not geo collection:', feature.geometry.type);
    }
}

Also, tried to convert a multiPolygon to a Polygon, didn't work that well.

Can any one please suggest a way to compare a bufferFeature with a set of feature collection having point, multipolygon and GeometryCollection?

2

2 Answers

1
votes

One thing you could do if you don't mind comparing the buffer to multiple points is use turf.explode() on the polygons / multipolygons. Here is a link to the documentation.

http://turfjs.org/examples/turf-explode/

Turf explode will turn polygons or multipolygons into a feature collection of points that represent the vertices of the shape. Once you have run turf.explode() on the polygons / multipolygons, you will then need to iterate over each feature (point) in the results and compare it with the buffer using turf.inside(). It would probably be easier to use turf.within() for this part, but you can use turf.inside() instead if you would like.

This works because if one of the points is inside of the buffer, then at least some part of the polygon that the points represent would also have been within the buffer area.

Another way to go about this would be to use a point instead of a buffer to compare distances with. Then if you had a point you could just use turf.distance() with the two points to see the distance between them. If you had polygons / multipolygons then you could turf.explode() those and compare the distances with your original point.

As for the geometry collections, I don't think you will be able to work with those using turf unless you separate the different parts of the geometry collection into separate feature collections by type.

0
votes

Also, tried to convert a multiPolygon to a Polygon, didn't work that well.

Why didn't that work? Could you explain that further?

A multipolygon or polygon is nothing else than a collection of points. You should be able to convert it to an array of points or an array containing features of points.

You could do it something like this:

function unpackMultiPolCoords(features) {
  var data = [];
  featureEach(features, function(feature) {
    var coordCollection = feature.geometry.coordinates;
    coordCollection.forEach(function(coords) {
      coords.forEach(function(coord) {
        data.push(coord);
      });
    });
  });
  return data;
};

var unpacked = unpackMultiPolCoords(multiPoly);

let toPoints = function(fc) {
  let points = [];
  fc.forEach((coord) => {
    points.push(turf.point(coord));
  });
  return points;
};

var points = toPoints(unpacked);

See full code @ http://codepen.io/bitHugger/pen/mOxwME

Then you could compare every point with turfs distance function to your buffer.