2

I'm using Leaflet with WMS layers served by GeoServer. The layers are displayed correctly on the map, also over a OSM background.

I want to catch the user click on the map and by using the X-Y coordinates, make a WMS GetFeatureInfo call to get back both the attributes and the geometry data relative to the clicked point.

The attributes are already correctly displayed on a popup.

But I also want to use the geometry data to add a new GeoJSON layer created on the fly, that contains the selected polygon. This is to emulate the selection like it is possible on GeoJSON (or WFS) layers or like it happens on QGIS (or any other GIS software) vectorial layers.

Note: I cannot switch from using WMS to WFS for the specific layer, because the polygons are too many and each one really big and complex.

Code

Here there is the code I'm using to create the GeoJSON layer, but, even if the layer is actually added to the map (checked in debug console), nothing is displayed and also, if I use the map.fitBounds() function, the map goes to the maximum zoom level, so I see the whole world 4 times instead of the small municipality polygon I expect...

let selectedStyle = {
    weight: 1,
    color: '#525252',
    fillColor: '#ff0000',
    fillOpacity: 1,
};
            
// evt is the event variable that I get with the 'click' event on leaflet map.
// evt.target = this.map

var selectionLayer = L.geoJSON(data, { style: selectedStyle });
selectionLayer.addTo(evt.target); // during debug I cannot see anything added to the map

if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
    selectionLayer.bringToFront(); // during debug, nothing happens
}

evt.target.fitBounds(selectionLayer.getBounds()); // the map zoom out to the maximum extent

The whole operation always ends with no errors in the console.

Layers list

During debug, if I stop right after the layer add call and check the layers on the map, I see this:

this.map object debug view

  • 90 and 139 come from GeoServer instance.
  • 198 comes from OSM.
  • 17119 is (should be...) the newly created layer that contains only the corresponding polygon (there's all the coordinates array, the attributes, etc.).
  • 17120 I don't know what it is... but it is always added togheter with the new layer (17119)...

Note: The first 3 layers (id: 90, 139, 198) are the layers set on the map at initialization.

Data from GeoServer

This is the URL that is generated by the code

https://myserver/geoserver/ows?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&FORMAT=image%2Fpng&LAYERS=domain%3Amylayer&QUERY_LAYERS=domain%3Amylayer&INFO_FORMAT=application%2Fjson&HEIGHT=698&WIDTH=1170&CRS=EPSG%3A3857&BBOX=1295569.410919595%2C5670519.161849943%2C1340285.072466423%2C5697195.684721468&I=736&J=285

and if I copy/paste on the browser I get back the correct following data

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "id": "mylayer.3503",
            "geometry": {
                "type": "MultiPolygon",
                "coordinates": [
                    [
                        [
                            [
                                1320453.79775683,
                                5693147.13070444
                            ],
                            [
                                1321195.40982531,
                                5693343.4255014
                            ],
                            ...others...
                        ]
                    ]
                ]
            },
            "geometry_name": "Geom",
            "properties": {
                "CodRip": 2,
                "CodRegione": 1,
                "CodProvincia": 12,
                "CodComune": 0,
                "CodUts": 12,
                "CodProvinciaComune": 12332,
                "CodIstatComune": "12332",
                "Comune": "Town",
                "ComuneAltro": null,
                "Area": 94057377.7116239,
                "Perimetro": 60437.94668668476,
                "ConcentrazioneMedia": 56
            },
            "bbox": [
                1314175.37773451,
                5675209.21680463,
                1333162.00791466,
                5693836.27909766
            ]
        }
    ],
    "totalFeatures": "unknown",
    "numberReturned": 1,
    "timeStamp": "2022-06-16T12:04:33.420Z",
    "crs": {
        "type": "name",
        "properties": {
            "name": "urn:ogc:def:crs:EPSG::3857"
        }
    },
    "bbox": [
        1314175.37773451,
        5675209.21680463,
        1333162.00791466,
        5693836.27909766
    ]
}
2
  • 2
    GeoJSON layer is expected to have coordinates in EPSG:4326 CRS. You seem to have projected coordinates, so you will have to use coordsToLatLng method (and proj4 if those are not EPSG:3857) to unproject them.
    – TomazicM
    Commented Jun 16, 2022 at 15:20
  • @TomazicM I already tried, using your own suggestion taken from here but the final output coordinates were always the same. Commented Jun 20, 2022 at 7:17

1 Answer 1

1

I was finally able to achieve the desired result, using a different approach.

Instead of using the geometry data given back from the WMS GetFeatureInfo call to build up a layer using the L.GeoJSON() function, I used only the ID attribute of the polygon's metadata, to get its geometry by using WFS GetFeature function with a filter by ID.

So yes, there're 2 function calls, the first to get the attributes and the second to get the geometry, but the result its absolutely smooth!

Solution code

This sample code uses the following libraries:

let selectedStyle = {
    weight: 2,
    color: '#525252',
    fill: false,
};
            
var selectedPolygonId = -1;

this.map.on('click', function(e) {
    // The 'wmsLayer' variable contains the reference to the WMS layer already loaded on the map, from which it is possible to make the subsequent call to 'GetFeatureInfo'
    wmsLayer.getFeatureInfo({
        latlng: e.latlng,
        done: function(featureCollection) {
            
            // Check for previous selected polygon layer and possibly remove it
            if (selectedPolygonId > -1)    {
                me.map.removeLayer(me.map._layers[selectedPolygonId]);
                selectedPolygonId = -1;
            }

            // Create the newly selected polygon layer using WFS
            if (featureCollection.features.length > 0) {
                let selectedPolygon = L.Geoserver.wfs("https://myserver.dev/geoserver/wfs", {
                    layers: "domain:mylayer",
                    CQL_FILTER: `ID='${featureCollection.features[0].properties.ID}'`,
                    style: selectedStyle,
                    fitLayer: false,
                });

                selectedPolygonId = L.stamp(selectedPolygon);
                selectedPolygon.addTo(me.map);
            }

            // Info popup
            let content = getMyData(); // HTML content with geometry related attributes values already formatted
            L.popup({ maxWidth: 800})
                .setLatLng(e.latlng)
                .setContent(content)
                .openOn(me.map);
        },
        fail: function(errorThrown) {
            console.log('getFeatureInfo failed: ', errorThrown);
        },
        always: function() {
            console.log('getFeatureInfo finished');
        }
    });
});

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.