0

I am using the vue-leaflet and axios plugin in vue.js to make a GetFeatureInfo request to WMS tile layers served by Geoserver/Geowebcache for a certain point on the map, defined as marker. I am getting empty responses for my request and I don't know where I am taking the wrong turn.

I have defined l-map, l-tile-layers (the background maps) and l-wms-tile-layers(the cached WMS tile layers served by GeoServer) as follows:

<l-map
      ref="map"
      v-model="zoom"
      v-model:zoom="zoom"
      :center="center"
      :options="{zoomControl:false, attributionControl:false}"
      :minZoom="minzoom"
      @click="addMarker"
    >

    <!-- Background maps: -->
    <l-tile-layer
      v-for="tileProvider in tileProviders"
      :key="tileProvider.name"
      :name="tileProvider.name"
      :visible="tileProvider.visible"
      :url="tileProvider.url"
      :attribution="tileProvider.attribution"
      layer-type="base"/>

    <!-- Layers from Geoserver as cached tile layers: -->
    <l-wms-tile-layer
      v-for="wmsLayer in getCheckedLayers"
      :key="wmsLayer.path"
      :layers="wmsLayer.path"
      :format="format_tile"
      :transparent="true"
      :tiled="true"
      :zIndex="wmsLayer.zindex"
      :base-url="wmsurl"
      :visible="true"
      :opacity="wmsLayer.opacity"
    >
    </l-wms-tile-layer> 
  
    </l-map>

l-map uses EPSG:3857 by default and so does l-tile-layer. The layers I uploaded to GeoServer are also EPSG:3857. Yet Geowebcache saves the cached layers in the local gwc directory as for example EPSG_900913_11, so I assume it uses EPSG:900913, which I read is a deprecated version of EPSG:3857. I also defined EPSG:3857 as a grid set in Geowebcache standards, so I wonder why it's not using it.

Now my problematic part: The GetFeatureInfo request:


data() {
            return {
                base_URL: 'http://localhost:8600/geoserver/wms?request=GetFeatureInfo&service=WMS&version=1.1.1',
                layers: '',
                srs: 'EPSG%3A3857',
                format: 'image%2Fpng', // alternatively: 'application/json'
                bbox: null,
                width: 256, // width of map output in pixels
                height: 256, // height of map output in pixels
                query_layers: '',
                info_format: 'application/json', // alternatively: 'application/json'
                x: 0, // X ordinate of query point on map, in pixels
                y: 0, // Y ordinate of query point on map, in pixels
                point_info: [],
            }
        },
        methods: {
            // get feature info in defined format (e.g. geojson)
            getFeatureInfo(marker, map) {
                // const map = this.$refs.map.leafletObject

                // First, build the URL depending on which layer has activeTooltips set to true
                
                this.layers = layerPath;
                this.query_layers = layerPath;
                this.bbox =  map.getBounds().toBBoxString();
                this.width = map.getSize().x;
                this.height = map.getSize().y;
                var point = map.latLngToContainerPoint(marker, map.getZoom());
                this.x = point.x;
                this.y = point.y;
           
                const feat_url = this.base_URL+
                    '&layers='+this.layers+
                    '&styles=&srs='+this.srs+
                    '&format='+this.format+
                    '&bbox='+this.bbox+
                    '&width='+this.width+
                    '&height='+this.height+
                    '&query_layers='+this.query_layers+
                    '&info_format='+this.info_format+
                    '&x='+this.x+
                    '&y='+this.y;
                

                // Next, make the get request
                axios.get(feat_url)
                .then((response) => {
                    this.point_info = response.data;
                })
                .catch(error => {
                    console.log(error);
                })
            }
        },

An example: I want to get the Feature Info for a selected WMS tile layer for the coordinates (latlong): (48.804813, 9.166788). The bounding box (bbox) was calculated by the function above as (8.953857421875002,48.66262313606079,9.412536621093752,48.8703607224138)and the width and height in pixels as (1336 918). The latlong coordinates where translated to pixels (620, 290). When running the GetFeatureInfo request for that point I am getting an empty JSON response:

{
    "type": "FeatureCollection",
    "features": [],
    "totalFeatures": "unknown",
    "numberReturned": 0,
    "timeStamp": "2022-03-23T14:19:44.220Z",
    "crs": null
}

When I change the srs in the GetFeatureInfo request from EPSG:3857 to EPSG:4326 I do get responses but they obviously don't match with the actual data point.

Any ideas what could the issue that cause empty responses despite the data being available?

7
  • 1
    You need to decide if you are using tiles (and so want a WMTS endpoint) or WMS where GeoServer will make some guesses and hope for the best that it can work out what you want. You will want to use EPSG:3857 through out though. Also the XY or IJ is in pixels not geographic coordinates.
    – Ian Turton
    Mar 23, 2022 at 14:52
  • Thanks @IanTurton. I am using tiles, see <wms-tile-layer> where I also set tiled=true. The XY I use for the GetFeatureInfo request are in pixels and I am using EPSG:3857 through out, as described in my post. As I understand using tiled maps would not make a difference for the GetFeatureInfo endpoint? The GetMap request that I am sending in <wms-tile-layer> itself works perfectly, it's just the GetFeatureInfo request that's not doing what I want. And the funny thing is that the GetFeatureInfo request works if I use EPSG:4326 but it's not working when I use EPSG:3857. Any suggestions?
    – Naomi
    Mar 24, 2022 at 7:08
  • UPDATE: I think the problem is that the getBounds function returns the bounding box coordinates in latlng and I need them in meters, which is the unit of EPSG:3857. Also, I calculate the bounds for the map object, and I think I rather need them for the tile layer. I have no idea how to get the bounding box in meters for the tile layer from within leaflet/leaflet. I can access them using the Geoserver GUI but I have a large number of tile layers and would like to access the bounding box coordinates from within vue/leaflet. Any ideas?
    – Naomi
    Mar 24, 2022 at 9:12
  • Hence, my suggestion that you use the WMTS end point, then you will know the bounds of the tiles.
    – Ian Turton
    Mar 24, 2022 at 10:14
  • @IanTurton Great, I will try that. Can you tell me the technical difference between the Geoserver+Geowebcache WMS endpoint with tiled=true (I am actually getting tiled layers from the Geoserver GetMap request) and the WMTS endpoint? And does a switch to the WMTS endpoint solve the issue that I need a bounding box in units of meters (since I am using EPSG:3875) instead of latlng?
    – Naomi
    Mar 25, 2022 at 12:41

1 Answer 1

1

In the end I solved it, as @copossum suggested by converting the bounding box from latlng to my CRS's units, in my case meters (I am using EPSG:3857). I did not use proj4js but simply leaflet's CRS.EPSG3857.project() function.

Here's my solution:

data() {
            return {
                base_URL: 'http://localhost:8600/geoserver/wms?request=GetFeatureInfo&service=WMS&version=1.1.1',
                layers: '',
                srs: 'EPSG:3857',
                format: 'image/png', // alternatively: 'application/json'
                bbox: [],
                width: 256, // width of map output in pixels
                height: 256, // height of map output in pixels
                query_layers: '',
                info_format: 'application/json', // alternatively: 'application/json'
                x: 0, // X ordinate of query point on map, in pixels
                y: 0, // Y ordinate of query point on map, in pixels
                point_info: [],
            }
        },
        methods: {
            // get feature info in defined format (e.g. geojson)
            getFeatureInfo(marker, map) {
                // const map = this.$refs.map.leafletObject

                // First, build the URL depending on which layer has activeTooltips set to true
                var layer_selected = this.getCheckedLayers.filter(obj => {
                    return obj.activeTooltips === true
                    });
                var layerPath = layer_selected[0].path;
                
                this.layers = layerPath;
                this.query_layers = layerPath;
                var bounds = map.getBounds();
                var sw = bounds.getSouthWest();
                var ne = bounds.getNorthEast();
              
                // project the latlng bounds to meters (EPSG:3857)
                sw = CRS.EPSG3857.project(sw);
                ne = CRS.EPSG3857.project(ne);
                console.log('sw_pr: '+sw+'ne_pr: '+ne)
               
                this.width = map.getSize().x;
                this.height = map.getSize().y;
                var point = map.latLngToContainerPoint(marker, map.getZoom());
                this.x = point.x;
                this.y = point.y;
           
                const feat_url = this.base_URL+
                    '&layers='+this.layers+
                    '&styles=&srs='+this.srs+
                    '&format='+this.format+
                    '&bbox='+this.bbox+
                    '&width='+this.width+
                    '&height='+this.height+
                    '&query_layers='+this.query_layers+
                    '&info_format='+this.info_format+
                    '&x='+this.x+
                    '&y='+this.y;
    

                // Next, make the get request
                axios.get(feat_url)
                .then((response) => {
                    console.log(response.data)
                    this.point_info = response.data;
                })
                .catch(error => {
                    console.log(error);
                })
            }
        },

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.