TransWikia.com

Filter geometry based on map extent using OpenLayers

Geographic Information Systems Asked by Massimiliano Moraca on August 3, 2020

I need to summarize an attribute of a geojson based on the map extent. I want to sum values for all features intersecting bbox. I think that I must use the Bbox filter but isn’t clear for me how I can use it.

I’ve a simple GeoJSON with four geometry named test_data.geojson:

{
"type": "FeatureCollection",
"name": "test_data",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 1, "name": "focusarea-id1", "pop": 30 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 10.224194550042373, 41.358221559689788 ], [ 10.224194550042373, 42.154498393805234 ], [ 11.816748218273265, 42.154498393805234 ], [ 11.816748218273265, 41.358221559689788 ], [ 10.224194550042373, 41.358221559689788 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 2, "name": "focusarea-id2", "pop": 20 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 11.960078048414047, 40.779593726899229 ], [ 11.960078048414047, 41.87314724575112 ], [ 13.297823129727995, 41.87314724575112 ], [ 13.297823129727995, 40.779593726899229 ], [ 11.960078048414047, 40.779593726899229 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 3, "name": "focusarea-id1", "pop": 10 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 11.519471533536832, 42.425232517404488 ], [ 11.519471533536832, 43.582488182985607 ], [ 12.8890676882154, 43.582488182985607 ], [ 12.8890676882154, 42.425232517404488 ], [ 11.519471533536832, 42.425232517404488 ] ] ] ] } },
{ "type": "Feature", "properties": { "id": 4, "name": "focusarea-id3", "pop": 40 }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ 13.043014542811051, 42.255360126126526 ], [ 13.043014542811051, 43.465700913981998 ], [ 13.871142450291117, 43.465700913981998 ], [ 13.871142450291117, 42.255360126126526 ], [ 13.043014542811051, 42.255360126126526 ] ] ] ] } }
]
}

I’m be able to put on the map my four rectangles using this code:

var sourceDataUrl = '{% static 'gis-data/vettori/test_data.geojson' %}';
var polygonsSource = new ol.source.Vector({
    url: sourceDataUrl,
    format: new ol.format.GeoJSON(),
});
var vectors = new ol.layer.Vector({
  source: polygonsSource,
});
map.addLayer(vectors);

var fetchFn = fetch(sourceDataUrl)
  .then(function(resp) {
    return resp.json();
  });

/// Summarize pop
fetchFn.then(function(json) {
    var features = new ol.format.GeoJSON().readFeatures(json, {
      dataProjection: 'EPSG:4326',
      featureProjection: map.getView().getProjection(),
    });

    var polygonPop = 0;
    for (var i=0; i<features.length; i++) {
      polygonPop += features[i].values_.pop;
    }
    console.log(polygonPop);

});

/// Compute the bounding box based on map extent
map.getView().on('change', function() {
    var extent3857 = map.getView().calculateExtent(map.getSize())
    var extent4326 = ol.proj.transformExtent(extent3857, 'EPSG:3857', 'EPSG:4326');
    console.log('Boundary Box 4326: '+extent4326);

});

I can compute the bounding box based on map extent but I don’t understand how I can link this feature with polygonSurface.

EDIT 1 with the indications of @Mike

map.getView().on('change', function() {

    var extent = ol.proj.transformExtent(
      map.getView().calculateExtent(map.getSize()),
      'EPSG:3857',
      'EPSG:4326',
    );

    var polygonIntersection = [];

    polygonsSource.forEachFeatureIntersectingExtent(extent, function(feature) {
      console.log(feature);
      polygonIntersection.push(feature);
    });

    console.log(polygonIntersection); // response -> Array []

});

Using the method forEachFeatureIntersectingExtent I’ve an empty array.

One Answer

Since it looks like @Mike is not around, I'm answering this.

When you calculate current view extent, you are transforming GeoJSON source coordinates from EPSG:3857 to EPSG:4326, to use them for checking intersection with GeoJSON features. That's wrong since source coordinates are transformed automatically from original EPSG:4326 to standard view EPSG:3857 when GeoJSON is read into source.

It would be also better to use map's moveend to catch view extent change, since view's change events are called twice at every move/zoom event, once at the beginning and once at the end.

So your code could look something like:

map.on('moveend', function() {
  var extent = map.getView().calculateExtent(map.getSize());
  var polygonIntersection = [];

  polygonsSource.forEachFeatureIntersectingExtent(extent, function(feature) {
    polygonIntersection.push(feature);
  });
  
  console.log(polygonIntersection);
});

Correct answer by TomazicM on August 3, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP