【问题标题】:Openlayers WMS getfeatureinfo issue on Google MapsGoogle Maps 上的 Openlayers WMS getfeatureinfo 问题
【发布时间】:2014-05-25 16:35:44
【问题描述】:

我正在尝试在 Google 地图上渲染 WMS 图层,并且除了 getfeatureinfo 事件之外它的工作正常。当我打开 Geoserver 并尝试单击 WMS 功能时,我可以获得功能信息。但是在我的页面中,我可以看到空的弹出窗口。我认为问题出在 Google 地图投影上。

代码:

function init(){
    var gmap = new OpenLayers.Layer.Google("Google Streets", {
    visibility: false});
    var options = {
        controls : [],
        units : "m",
        numZoomLevels : 22,
        maxResolution : 156543.0339,
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG:4326"),
        maxExtent : new OpenLayers.Bounds(-20037508.34, -20037508.34,
                20037508.34, 20037508.34)
    };
    var map = new OpenLayers.Map('map', options);
    var layer1 = new OpenLayers.Layer.WMS("Layer1 - Tiled",      
     "http://localhost:8090/geoserver/Layers/wms", {
                layers : "Layer1",
                transparent : "true",
                format : "image/png",
                srs : 'EPSG:4326', 
                zoomOffset : 3,
            }, {
                isBaseLayer : false
            });
    map.addLayer(gmap);
    map.addLayer(layer1);
    info = new OpenLayers.Control.WMSGetFeatureInfo({
        url: 'http://localhost:8090/geoserver/Layers/wms', 
        title: 'Identify features by clicking',
        layers: [layer1],
        infoFormat: 'text/html',
        queryVisible: true,
        eventListeners: {
            getfeatureinfo: function(event) {
                map.addPopup(new OpenLayers.Popup.FramedCloud(
                    "chicken", 
                    map.getLonLatFromPixel(event.xy),
                    null,
                    event.text,
                    null,
                    true
                ));
            }
        }
    });
    map.addControl(info);
    info.activate();
    map.setCenter(new OpenLayers.LonLat(-104.949, 40.924).transform(
    new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),5);
     map.addControl(new OpenLayers.Control.Navigation());
}

<body onload="init()">
 <div style="visibility: visible; height: 100%;" id="map"></div>
</body>

在谷歌地图 (EPSG:900913) 和 WMS 图层 (EPSG:4326) 的情况下,有什么方法可以获取特征信息?我需要更改我的代码吗?请分享您的宝贵想法。

我们将不胜感激:)

【问题讨论】:

  • getLonLatFrompixel 返回经度/纬度坐标,而您使用的是 900913(以米为单位)。您是否尝试过在 map.getLonLatFromPixel(event.xy) 上用于 map.setCenter 的相同转换?
  • @JohnBarça:是的,我试过了,兄弟。没有运气:(
  • 可能是一个明显的问题,但是 event.text 和 map.getLonLatFromPixel(event.xy); 的一些示例值是什么;
  • 我得到空的回应约翰。我认为当我们点击功能时,OpenLayers getfeatureinfo 无法从地理服务器调用/获取数据。
  • 当您在 geoserver 中设置图层时,它会要求您提供已声明的原生投影,并且还有一个强制声明选项,它将尝试将所有传入查询转换为该投影。我会检查您从 OpenLayers 到 Geoserver 的传出请求在 getFeatureInfo 请求中的样子,并且它的投影与您在 Geoserver 中设置为原生/声明的任何内容相匹配。

标签: javascript google-maps google-maps-api-3 openlayers geoserver


【解决方案1】:
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.1.0';
    url +='&REQUEST=GetFeatureInfo';
    url +='&TRANSPARENT=true';
    url +='&QUERY_LAYERS='+layerName;
    url +='&STYLES';
    url +='&LAYERS='+layerName;
    url +='&INFO_FORMAT=text/html';
    url +='&SRS=EPSG:4326';
    url +='&FEATURE_COUNT=10';
    url +='&WIDTH='+buffer_width_px;
    url +='&HEIGHT='+buffer_height_px;
    url +='&Y='+center_y_px;
    url +='&X='+center_x_px;
    url +='&BBOX='+buffer_sw_x_dd+','+buffer_sw_y_dd+','+buffer_ne_x_dd+','+buffer_ne_y_dd;


    return url;
};

希望这会有所帮助

【讨论】:

    【解决方案2】:

    我刚刚使用指向 geoserver 演示站点的确切代码运行了一个演示,它运行良好。下面的示例显示了国家边界等,因此只需前往美国/加拿大边境即可点击。我怀疑你的问题是 GetFeatureInfo 不能保证总是返回一些东西。可以进行该调用并且 WMS 服务器返回 GetFeatureInfo 对图层不可用的异常。

    另一个可能的问题是您要求 GetFeatureInfo 以 text/html 格式返回信息格式。如果您没有在服务器上定义 HTML 模板,它也可能返回异常,尽管我不确定这里会出现什么错误。您应该切换到最简单的默认选项,即 text/plain。它看起来不漂亮,但它会在您弄清楚其他所有内容时再移除一个可能会损坏的地方。

    我建议您在 Chrome 中尝试此代码示例,以便您可以使用调试工具并检查网络选项卡并查看 WMS 请求的内容来回流动。

    最后,如果您确实看到返回的异常,您可以通过要求以 JSON 格式返回的异常来防御性地编写代码,这样您就有可能捕获错误。

    祝你好运!

    <html>
    <head>
      <script src="lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps/api/js?v=3&amp;sensor=false"></script>
    
      <script type="text/javascript">
      function init() {
        var gmap = new OpenLayers.Layer.Google("Google Streets", {
        visibility: false});
        var options = {
            controls : [],
            units : "m",
            numZoomLevels : 22,
            maxResolution : 156543.0339,
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326"),
            maxExtent : new OpenLayers.Bounds(-20037508.34, -20037508.34,
                    20037508.34, 20037508.34)
        };
        var map = new OpenLayers.Map('map', options);
        var layer1 = new OpenLayers.Layer.WMS("Layer1 - Tiled",      
         "http://demo.opengeo.org/geoserver/ows?", {
                    layers : "osm:admin_01234",
                    transparent : "true",
                    format : "image/png",
                    srs : 'EPSG:4326', 
                    zoomOffset : 3,
                }, {
                    isBaseLayer : false
                });
        map.addLayer(gmap);
        map.addLayer(layer1);
        info = new OpenLayers.Control.WMSGetFeatureInfo({
            url: 'http://demo.opengeo.org/geoserver/ows?', 
            title: 'Identify features by clicking',
            layers: [layer1],
            infoFormat: 'text/html',
            queryVisible: true,
            eventListeners: {
                getfeatureinfo: function(event) {
                    map.addPopup(new OpenLayers.Popup.FramedCloud(
                        "chicken", 
                        map.getLonLatFromPixel(event.xy),
                        null,
                        event.text,
                        null,
                        true
                    ));
                }
            }
        });
        map.addControl(info);
        info.activate();
        map.setCenter(new OpenLayers.LonLat(-104.949, 40.924).transform(
        new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject()),5);
         map.addControl(new OpenLayers.Control.Navigation());
    }
      </script>
    
    <body onload="init()">
     <div style="visibility: visible; height: 100%;" id="map"></div>
    </body>
    

    【讨论】:

      【解决方案3】:

      我没有可用的测试环境(你能设置一个合适的 jsfiddle,使用非 localhost wms 吗?),但也许你在浏览器上点击了 XSS 过滤器。

      看到这个帖子: http://cggis.wordpress.com/2011/05/19/getfeatureinfo/

      使用“--disable-web-security”标志启动 Chrome 应该是排除这种可能性的快速测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多