Search code examples
openlayers

Openlayer - filter layer by another one (intersect?)


I have two point on a map, one red, one blue. On this map is also a grey area.

Of my two point, I would like to display only the blue one, which inside the area.

To sum things up, I would like to filter the geometry of a layer (point) by the geometry of another layer (area)

what is the proper way to do this, with intersect?

Here is a working example :

//Point layer Json
var GeoJSON = {
    "type": "FeatureCollection",
    "totalFeatures": 2,
    "features": [{
            "type": "Feature",
            "id": "1",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    294958.91163697134,
                    6246510.814409403
                ]
            },
            "geometry_name": "GEOMETRY",
            "properties": {
                "ID": 1,
                "color": "blue"
            }
        },
        {
            "type": "Feature",
            "id": "2",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    255020.37350418963,
                    6246791.991868377
                ]
            },
            "geometry_name": "GEOMETRY",
            "properties": {
                "ID": 2,
                "color": "red"
            }
        }
    ],
    "crs": {
        "type": "name",
        "properties": {
            "name": "urn:ogc:def:crs:EPSG::3857"
        }
    }
};

//Base layer
var osm = new ol.layer.Tile({
    source: new ol.source.OSM()
});

//Areal layer
let areal = new ol.layer.Vector({
    source: new ol.source.Vector({
        url: "https://wxs.ign.fr/administratif/geoportail/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&srsName=EPSG:3857&typenames=ADMINEXPRESS-COG-CARTO.LATEST:departement&outputformat=application/json&CQL_FILTER=insee_dep=77",
        format: new ol.format.GeoJSON()
    }),
    style: new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: 'grey',
            width: 2
        }),
        fill: new ol.style.Fill({
            color: 'darkgrey'
        })
    })
});

//Point layer
var point =
    new ol.layer.Vector({
        source: new ol.source.Vector({
            features: (new ol.format.GeoJSON()).readFeatures(GeoJSON, {
                featureProjection: 'EPSG:3857'
            })
        }),
        style: (feature) => {
            return new ol.style.Style({
                image: new ol.style.Circle({
                    radius: 8,
                    fill: new ol.style.Fill({
                        color: feature.get("color")
                    }),
                    stroke: new ol.style.Stroke({
                        color: 'white',
                        width: 2
                    })
                })
            })
        }
    })

// The map
var map = new ol.Map({
    target: 'map',
    view: new ol.View({
        zoom: 8,
        center: [255000, 6266791]
    }),
    layers: [
        osm,
        areal,
        point
    ]
});
<head>
    <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css">
    <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
</head>

<div id="map" style="width:100%; height:600px;">


Solution

  • If you have a single polygon or multipolygon feature you could use the intersectsCoordinate method to test if the geometry contains the point coordinate when styling the point.

    //Point layer Json
    var GeoJSON = {
        "type": "FeatureCollection",
        "totalFeatures": 2,
        "features": [{
                "type": "Feature",
                "id": "1",
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        294958.91163697134,
                        6246510.814409403
                    ]
                },
                "geometry_name": "GEOMETRY",
                "properties": {
                    "ID": 1,
                    "color": "blue"
                }
            },
            {
                "type": "Feature",
                "id": "2",
                "geometry": {
                    "type": "Point",
                    "coordinates": [
                        255020.37350418963,
                        6246791.991868377
                    ]
                },
                "geometry_name": "GEOMETRY",
                "properties": {
                    "ID": 2,
                    "color": "red"
                }
            }
        ],
        "crs": {
            "type": "name",
            "properties": {
                "name": "urn:ogc:def:crs:EPSG::3857"
            }
        }
    };
    
    //Base layer
    var osm = new ol.layer.Tile({
        source: new ol.source.OSM()
    });
    
    //Areal layer
    let areal = new ol.layer.Vector({
        source: new ol.source.Vector({
            url: "https://wxs.ign.fr/administratif/geoportail/wfs?SERVICE=WFS&VERSION=2.0.0&REQUEST=GetFeature&srsName=EPSG:3857&typenames=ADMINEXPRESS-COG-CARTO.LATEST:departement&outputformat=application/json&CQL_FILTER=insee_dep=77",
            format: new ol.format.GeoJSON()
        }),
        style: new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: 'grey',
                width: 2
            }),
            fill: new ol.style.Fill({
                color: 'darkgrey'
            })
        })
    });
    
    let areaGeometry;
    
    //Point layer
    var point =
        new ol.layer.Vector({
            source: new ol.source.Vector({
                features: (new ol.format.GeoJSON()).readFeatures(GeoJSON, {
                    featureProjection: 'EPSG:3857'
                })
            }),
            style: (feature) => {
              if (areaGeometry && 
                  areaGeometry.intersectsCoordinate(
                      feature.getGeometry().getCoordinates()
                  )
              ) {
                return new ol.style.Style({
                    image: new ol.style.Circle({
                        radius: 8,
                        fill: new ol.style.Fill({
                            color: feature.get("color")
                        }),
                        stroke: new ol.style.Stroke({
                            color: 'white',
                            width: 2
                        })
                    })
                })
              }
            }
        })
    
        areal.getSource().on('featuresloadend', function(){
            areaGeometry = areal.getSource().getFeatures()[0].getGeometry();
            point.changed();
        });
    
    // The map
    var map = new ol.Map({
        target: 'map',
        view: new ol.View({
            zoom: 8,
            center: [255000, 6266791]
        }),
        layers: [
            osm,
            areal,
            point
        ]
    });
    <head>
        <link rel="stylesheet" href="https://openlayers.org/en/latest/css/ol.css">
        <script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
    </head>
    
    <div id="map" style="width:100%; height:600px;">