2

I'm sending a WMS GetFeatureInfo() request, but there is something wrong because the returned info does not appropriate a clicked point.

I suspect that the error is in the BBOX parameter of the request because I'm not sure that bounds are in the correct EPSG.

How can I convert Google Maps Bounds to the EPSG:6706?

This is what I tried to do:

google.maps.event.addListener(map, "dblclick", function (e) { 
  if ($('#wms').is(":checked")) {
  var scale = Math.pow(2, map.getZoom());
  var proj = map.getProjection();
  var bounds = map.getBounds();
  var nw = proj.fromLatLngToPoint(
      new google.maps.LatLng(
      bounds.getNorthEast().lat(),
      bounds.getSouthWest().lng()
  ));
  var so = proj.fromLatLngToPoint(
      new google.maps.LatLng(
         bounds.getNorthEast().lng(),
         bounds.getSouthWest().lat()
  ));
  var point = proj.fromLatLngToPoint(e.latLng);
  var i = Math.floor((point.x - nw.x) * scale);
  var j = Math.floor((point.y - nw.y) * scale);
  var w = $('#map').width();
  var h = $('#map').height();
  i = Math.round(i*256/w);
  j = Math.round(j*256/h);
  var url = "https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?";
  url += "SERVICE=WMS";    //WMS service
  url += "&VERSION=1.3.0";  //WMS version  
  url += "&REQUEST=GetFeatureInfo"; //WMS operation
  url += "&FORMAT=image/png" ; //WMS format
  url += "&TRANSPARENT=TRUE";
  url += "&QUERY_LAYERS=CP.CadastralParcel"; //,CP.CadastralZoning"; 
  url += "&LAYERS=CP.CadastralParcel"; //,CP.CadastralZoning"; 
  url += "&TILED=true";
  url += "&INFO_FORMAT=text/html";
  url += "&I="+i;
  url += "&J="+j;      
  url += "&WIDTH=256";         //tile size in google
  url += "&HEIGHT=256";
  url += "&CRS=EPSG:6706";     //set WGS84 
  url += "&BBOX=" + bbox;      // set bounding box
  window.open(url);
}
});

This is an example of the WMS call: it works but the returned info are not correct for the point clicked.

https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&FORMAT=image/png&TRANSPARENT=TRUE&QUERY_LAYERS=CP.CadastralParcel&LAYERS=CP.CadastralParcel&TILED=true&INFO_FORMAT=text/html&I=65&J=88&WIDTH=256&HEIGHT=256&CRS=EPSG:6706&BBOX=10.510482788085938,44.35429627478576,10.51116943359375,44.35478724525106
  • 1
    please add an example of the fill URL being requested so we can see what the bbox etc look like – Ian Turton Jan 10 at 11:57
  • @IanTurton I've added the URL generated, you can try it: it works but it is not correct for the point clicked – kiks73 Jan 10 at 13:13
  • 1
    So the corresponding Map request is: wms.cartografia.agenziaentrate.gov.it/inspire/wms/… and you are requesting pixel row (j) 88 so approx 1/3 down and column (i) 65, so approx 1/4 across, which puts it in the yelllow portion. What value are you expecting? – nmtoken Jan 10 at 14:39
  • @nmtoken I think that you catch my issue: I'm expecting to get the entire window tiles, while if I run the same getMap I get only one 256x256 tile. But how can I get the tile where I exactly click? There is something that I'm missing – kiks73 Jan 10 at 14:54
  • You need to capture the GetMap request that the client made and click is at the pixel coordinates in that map ~ just like @IanTurton says the GetFeautureInfo and the GetMap request are related operations. – nmtoken Jan 10 at 15:20
1

I've found the solution in this SO answer.

The function to call is getFeatureInfoURL(latLng) and there is only to insert the correct WMS baseURL and layerName.

I past here the JS code, updated to the 1.3.0 WMS:

function fromLatLngToPoint(latLng, map) {
    var topRight = map.getProjection().fromLatLngToPoint(map.getBounds().getNorthEast());
    var bottomLeft = map.getProjection().fromLatLngToPoint(map.getBounds().getSouthWest());
    var scale = Math.pow(2, map.getZoom());
    var worldPoint = map.getProjection().fromLatLngToPoint(latLng);
    return new google.maps.Point((worldPoint.x - bottomLeft.x) * scale, (worldPoint.y - topRight.y) * scale);
}


function getRadius(zoom) {
    var radius_px = 0.40/2
    var constMetersDegress = 1000; // TODO Verifiy

    //zoom <-> m/px = http://timwhitlock.info/blog/2010/04/google-maps-zoom-scales/
    var scaled_zooms = { 
        22: 0.02,
        21: 0.04,
        20: 0.09,
        19: 0.19,
        18: 0.37,
        17: 0.74,
        16: 1.48,
        15: 3,
        14: 6,
        13: 12,
        12: 24,
        11: 48,
        10: 95,
        9: 190,
        8: 378,
        7: 752,
        6: 1485,
        5: 2909,
        4: 5540,
        3: 10064,
        2: 16355,
        1: 21282,
        0: 30000
    }

    var radius_meters = radius_px * scaled_zooms[zoom];
    var radius_degrees = radius_meters / constMetersDegress;
    return radius_degrees;
}



function getFeatureInfoURL(latLng){
    var lat = parseFloat(latLng.lat());
    var lng = parseFloat(latLng.lng());

    //console.info('------------------------------')
    var radius_degrees = getRadius(map.getZoom());
    var buffer_sw_y_dd = lat-radius_degrees
    var buffer_sw_x_dd = lng-radius_degrees
    var buffer_ne_y_dd = lat+radius_degrees
    var buffer_ne_x_dd = lng+radius_degrees
    //console.info('bbox dd',buffer_sw_x_dd+','+buffer_sw_y_dd+','+buffer_ne_x_dd+','+buffer_ne_y_dd)

    var buffer_sw_dd = new google.maps.LatLng( buffer_sw_y_dd, buffer_sw_x_dd )//decimal degrees
    var buffer_ne_dd = new google.maps.LatLng( buffer_ne_y_dd, buffer_ne_x_dd )//decimal degrees

    var buffer_sw_px = fromLatLngToPoint(buffer_sw_dd, map);//pixels
    var buffer_ne_px = fromLatLngToPoint(buffer_ne_dd, map);//pixels
    //console.info('buffer_sw_px',buffer_sw_px,'buffer_ne_px',buffer_ne_px)

    var buffer_width_px = ( Math.abs( buffer_ne_px.x - buffer_sw_px.x ) ).toFixed(0);
    var buffer_height_px = ( Math.abs( buffer_ne_px.y - buffer_sw_px.y ) ).toFixed(0);
    //console.info('buffer_width_px',buffer_width_px, 'buffer_height_px',buffer_height_px)

    var center_x_px = (buffer_width_px / 2).toFixed(0);
    var center_y_px = (buffer_height_px / 2).toFixed(0);
    //console.info('center_x_px',center_x_px,'center_y_px',center_y_px)
    //console.info('------------------------------')


    var url = this.baseUrl;
    url +='&SERVICE=WMS';
    url +='&VERSION=1.3.0';
    url +='&REQUEST=GetFeatureInfo';
    url +='&TRANSPARENT=true';
    url +='&QUERY_LAYERS='+layerName;
    url +='&STYLES';
    url +='&LAYERS='+layerName;
    url +='&INFO_FORMAT=text/html';
    url +='&SRS=EPSG:6706';
    url +='&WIDTH='+buffer_width_px;
    url +='&HEIGHT='+buffer_height_px;
    url +='&J='+center_y_px;
    url +='&I='+center_x_px;
    url +='&BBOX='+buffer_sw_x_dd+','+buffer_sw_y_dd+','+buffer_ne_x_dd+','+buffer_ne_y_dd;


    return url;
};
0

A WMS getFeatureInfo request works by passing a complete copy of the map request with an X/Y (or I/J in WMS 1.3) pair to tell the server where you clicked.

In your case you are forcing the SRS to be EPSG:6706 while the bounding box seems to be in EPSG:4326 (at least it looks like that and the comment supports that view). So your click location will be calculated to be somewhere different by the server and you will get no answer (if you are lucky) or the wrong answer.

Instead of creating the request by hand use the one the client is making and simply add the I/J pixel coords to it.

  • What do you mean for "use the one the client is making"? I'm using google maps API, I'm not sure that there is a WMS support. Isn't it? – kiks73 Jan 10 at 13:32
  • 1
    if you aren't requesting a WMS then there is no way to make a getFeatureInfo request – Ian Turton Jan 10 at 13:40
  • Shoud I use proj4.js to convert EPSG:4326 to EPSG:6706? – kiks73 Jan 10 at 13:54
  • 1
    No you should never mention epsg:6706 to the server at all. – Ian Turton Jan 10 at 14:06
  • I'm sorry but I can't understand nothing about what you are suggesting to do – kiks73 Jan 10 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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