[GIS] Google Maps with shapefile/WMS – GetFeatureInfo problem

getfeatureinfogooglewms

I've just created my first GeoServer "portal". For this I created two JavaScript files. In the first file I have Google Maps API and in the second file I have my shapefile.

Directly from GeoServer I can get the feature info by clicking the feature. But in my page I can't do that. I think the problem is Google Maps. Is there a way to put the shapefile "on top" of Google Maps? I think this is the solutions.

For GetFeatureInfo I have copied the code from GeoServer page.

The code for the first JavaScript file is:

var Maps = (function() {
    var filterList = {};

    return {
        loadGoogle: function() {         
            var myLatlng = new google.maps.LatLng(45, 25);
            var myOptions = {
                zoom: 6,
                center: myLatlng,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            }
            var map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);

            var customParams = [
                "FORMAT=image/png8",
                "LAYERS=adi:intabulat_vladaia"
            ];

            //Add query string params to custom params
            var pairs = location.search.substring(1).split('&');
            for (var i = 0; i < pairs.length; i++) {
                customParams.push(pairs[i]);
            }
            loadWMS(map, "http://localhost:8080/geoserver/adi/wms?", customParams);
        }

    } // return: public methods 
})();

// Jquery Document.onLoad equivalent
$(document).ready(function() {
    Maps.loadGoogle(); 
}); // end JQuery document ready

And for the second file is:

function bound(value, opt_min, opt_max) {
    if (opt_min != null) value = Math.max(value, opt_min);
    if (opt_max != null) value = Math.min(value, opt_max);
    return value;
}

function degreesToRadians(deg) {
    return deg * (Math.PI / 180);
}

function radiansToDegrees(rad) {
    return rad / (Math.PI / 180);
}

function MercatorProjection() {
    var MERCATOR_RANGE = 256;
    this.pixelOrigin_ = new google.maps.Point(
        MERCATOR_RANGE / 2, MERCATOR_RANGE / 2);
    this.pixelsPerLonDegree_ = MERCATOR_RANGE / 360;
    this.pixelsPerLonRadian_ = MERCATOR_RANGE / (2 * Math.PI);
};

MercatorProjection.prototype.fromLatLngToPoint = function(latLng, opt_point) {
    var me = this;

    var point = opt_point || new google.maps.Point(0, 0);

    var origin = me.pixelOrigin_;
    point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;
    // NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
    // 89.189.  This is about a third of a tile past the edge of the world tile.
    var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999, 0.9999);
    point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) * -me.pixelsPerLonRadian_;
    return point;
};

MercatorProjection.prototype.fromDivPixelToLatLng = function(pixel, zoom) {
    var me = this;    
    var origin = me.pixelOrigin_;
    var scale = Math.pow(2, zoom);
    var lng = (pixel.x / scale - origin.x) / me.pixelsPerLonDegree_;
    var latRadians = (pixel.y / scale - origin.y) / -me.pixelsPerLonRadian_;
    var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2);
    return new google.maps.LatLng(lat, lng);
};

MercatorProjection.prototype.fromDivPixelToSphericalMercator = function(pixel, zoom) {
    var me = this;
    var coord = me.fromDivPixelToLatLng(pixel, zoom);
    var r= 6378137.0;
    var x = r* degreesToRadians(coord.lng());
    var latRad = degreesToRadians(coord.lat());
    var y = (r/2) * Math.log((1+Math.sin(latRad))/ (1-Math.sin(latRad)));

    return new google.maps.Point(x,y);
};

function loadWMS(map, baseURL, customParams){
    var tileHeight = 256;
    var tileWidth = 256;
    var opacityLevel = 0.60;
    var isPng = true;
    var isbaselayer=true;
    var minZoomLevel = 2;
    var maxZoomLevel = 28;

    //var baseURL = "";
    var wmsParams = [
    "REQUEST=GetMap",
    "SERVICE=WMS",
    "VERSION=1.1.1",
    "BGCOLOR=0xFFFFFF",
    "TRANSPARENT=TRUE",
    "SRS=EPSG:900913", // 3395?
    "WIDTH="+ tileWidth,
    "HEIGHT="+ tileHeight
    ];

    //add additional parameters
    var wmsParams = wmsParams.concat(customParams);

    var overlayOptions =
    {
        getTileUrl: function(coord, zoom)
        {
            var lULP = new google.maps.Point(coord.x*256,(coord.y+1)*256);
            var lLRP = new google.maps.Point((coord.x+1)*256,coord.y*256);

            var projectionMap = new MercatorProjection();

            var lULg = projectionMap.fromDivPixelToSphericalMercator(lULP, zoom);
            var lLRg  = projectionMap.fromDivPixelToSphericalMercator(lLRP, zoom);

            var lUL_Latitude = lULg.y;
            var lUL_Longitude = lULg.x;
            var lLR_Latitude = lLRg.y;
            var lLR_Longitude = lLRg.x;
            //GJ: there is a bug when crossing the -180 longitude border (tile does not render) - this check seems to fix it
            if (lLR_Longitude < lUL_Longitude){
              lLR_Longitude = Math.abs(lLR_Longitude);
            }
            var urlResult = baseURL + wmsParams.join("&") + "&bbox=" + lUL_Longitude + "," + lUL_Latitude + "," + lLR_Longitude + "," + lLR_Latitude;

            return urlResult;
        },

        tileSize: new google.maps.Size(tileHeight, tileWidth),
        minZoom: minZoomLevel,
        maxZoom: maxZoomLevel,
        opacity: opacityLevel,
        isPng: isPng
    };

    overlayWMS = new google.maps.ImageMapType(overlayOptions);
    map.overlayMapTypes.insertAt(0, overlayWMS);

    map.setOptions({
        mapTypeControlOptions: {
            mapTypeIds: [
            google.maps.MapTypeId.ROADMAP,
            google.maps.MapTypeId.TERRAIN,
            google.maps.MapTypeId.SATELLITE,
            google.maps.MapTypeId.HYBRID
            ],
            style: google.maps.MapTypeControlStyle.DROPDOWN_MENU
        }
    });
}


  // support GetFeatureInfo
                map.events.register('click', map, function (e) {
                    document.getElementById('nodelist').innerHTML = "Loading... please wait...";
                    var params = {
                        REQUEST: "GetFeatureInfo",
                        EXCEPTIONS: "application/vnd.ogc.se_xml",
                        BBOX: map.getExtent().toBBOX(),
                        SERVICE: "WMS",
                        INFO_FORMAT: 'text/html',
                        QUERY_LAYERS: map.layers[0].params.LAYERS,
                        FEATURE_COUNT: 50,
                        Layers: 'adi:intabulat_vladaia',
                        WIDTH: map.size.w,
                        HEIGHT: map.size.h,
                        format: format,
                        styles: map.layers[0].params.STYLES,
                        srs: map.layers[0].params.SRS};

                    // handle the wms 1.3 vs wms 1.1 madness
                    if(map.layers[0].params.VERSION == "1.3.0") {
                        params.version = "1.3.0";
                        params.j = parseInt(e.xy.x);
                        params.i = parseInt(e.xy.y);
                    } else {
                        params.version = "1.1.1";
                        params.x = parseInt(e.xy.x);
                        params.y = parseInt(e.xy.y);
                    }

                    // merge filters
                    if(map.layers[0].params.CQL_FILTER != null) {
                        params.cql_filter = map.layers[0].params.CQL_FILTER;
                    } 
                    if(map.layers[0].params.FILTER != null) {
                        params.filter = map.layers[0].params.FILTER;
                    }
                    if(map.layers[0].params.FEATUREID) {
                        params.featureid = map.layers[0].params.FEATUREID;
                    }
                    OpenLayers.loadURL("http://localhost:8080/geoserver/adi/wms", params, this, setHTML, setHTML);
                    OpenLayers.Event.stop(e);
                });


            // sets the HTML provided into the nodelist element
            function setHTML(response){
                document.getElementById('nodelist').innerHTML = response.responseText;
            };


 // build up all controls
                map.addControl(new OpenLayers.Control.PanZoomBar({
                    position: new OpenLayers.Pixel(2, 15)
                }));
                map.addControl(new OpenLayers.Control.Navigation());
                map.addControl(new OpenLayers.Control.Scale($('scale')));
                map.addControl(new OpenLayers.Control.MousePosition({element: $('location')}));
                map.zoomToExtent(bounds);
                map.events.on;
                     function setWidth(size){
                var mapDiv = document.getElementById('map');
                var wrapper = document.getElementById('wrapper');

                if (size == "auto") {
                    // reset back to the default value
                    mapDiv.style.width = null;
                    wrapper.style.width = null;
                }
                else {
                    mapDiv.style.width = size + "px";
                    wrapper.style.width = size + "px";
                }
                // notify OL that we changed the size of the map div
                map.updateSize();
            }

And I have an HTML file which calls the two JavaScript files. In the second file the part from "GetFeatureInfo" is from the GeoServer OpenLayers page.

I am new in this and I don't understand why it's not working. It's not working because of Google Maps or is something else wrong?

The problem is when my mouse pointer is over a feature it is the hand drag tool. I can drag the Google Maps from left to right, top to bottom. I think where my pointer is over a feature it should transform to a marker pointer.

Best Answer

Ok Here is the code for getfeatureinfo and CQL Filter for a layer with EPSG 4326 and Google Maps behind:

 <html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>OpenLayers WMS Feature Info Example (GeoServer)</title>
    <script src='http://maps.google.com/maps/api/js?v=3.2&sensor=false'></script>
    <script src="http://openlayers.org/api/OpenLayers.js"></script>
    <link rel="stylesheet" href="http://openlayers.org/api/theme/default/style.css" type="text/css" />
    <link rel="stylesheet" href="http://openlayers.org/dev/examples/style.css" type="text/css" />
    <style type="text/css">
     #map {
                clear: both;
                position: relative;
                width: 100%;
                height: 90%;
                border: 1px solid black;
            }
            #wrapper {
                width: 619px;
            }

            #location {
                float: right;
            }

            #cql {
                width: 400px;
            }


    </style>

    <script type="text/javascript">
    var map;
        var harta;
        var gh;
        var xx;
    function load() {
     map = new OpenLayers.Map('map', {
     projection: new OpenLayers.Projection("EPSG:900913"),
    displayProjection: new OpenLayers.Projection("EPSG:4326")

        });

    gh=  new OpenLayers.Layer.Google(
                "Google Hybrid",
                {type: google.maps.MapTypeId.HYBRID, numZoomLevels:50});
    harta = new OpenLayers.Layer.WMS("adi",
            "http://localhost:8080/geoserver/adi/wms", 
            {'layers': 'adi:vladaia4326', transparent: true, format: 'image/gif'},
            {isBaseLayer: false}
        );

map.addLayers([gh, harta]);

// var lonLat = new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());
   //         map.setCenter (lonLat, zoom);

map.events.register("mousemove", map, function(e) {
          var position = this.events.getMousePosition(e);
         OpenLayers.Util.getElement("coords2").innerHTML = position;}); 


map.addControl(new OpenLayers.Control.Permalink());             
map.addControl(new OpenLayers.Control.MousePosition({div:document.getElementById("coords")}));              




            // Tie click event to WMS GetFeatureInfo call        
map.events.register('click', map, function (e) {
     document.getElementById('nodelist').innerHTML = "Loading... please wait...";
     wmsurl="http://localhost:8080/geoserver/adi/wms"
    var url = wmsurl
    + "?REQUEST=GetFeatureInfo"
    + "&EXCEPTIONS=application/vnd.ogc.se_xml"
    + "&BBOX=" + map.getExtent().toBBOX()
    + "&X=" + parseInt(e.xy.x)
    + "&Y=" + parseInt(e.xy.y)
    + "&INFO_FORMAT=text/html"
    + "&QUERY_LAYERS=adi:vladaia4326"
    + "&LAYERS=adi:vladaia4326"
    + "&FEATURE_COUNT=50"
    + "&SRS=EPSG:900913"
    + "&STYLES="
    + "&WIDTH=" + map.size.w
    + "&HEIGHT=" + map.size.h;



    window.open(url,
    "getfeatureinfo",
   "location=0,status=0,scrollbars=1,width=800,height=300");




  }); //getfeatureinfo s-a terminat. trecem la urmatorul

 }



 function updateFilter(){
       var filter = document.getElementById('filter').value;
       if (filter =="")  
       {
       harta.mergeNewParams({'CQL_FILTER': null});
       }
       else
       {
    harta.mergeNewParams({'CQL_FILTER': filter});
    }
    }

function resetFilter() {
        document.getElementById('filter').value = "";
   updateFilter();
    }   


    </script>
    </head>
    <body onLoad="load()">
    <div id="map" class="smallmap"></div>
    Test
     <div id="wrapper">
            <div id="location">location</div>

        </div>


                    <input id="filter" type="text">
                    <input type="button" value="update" onClick="updateFilter()">
                    <input type="button" value="reset" onClick="resetFilter()">
                    <input type="button" value="mesaj" onClick="evasdaent()">
             <div id="location">location</div>
              <div id="coords" style="height: 1.5em;"></div>  
               <div id="coords2" style="height: 1.5em;"></div> 
                <div id="coords3" style="height: 1.5em;"></div> 
                <div id="nodelist" style="height: 1.5em;"></div> 
   </body>
 </html>

Now i'm working to put labels on polygons. Wish me luck