1

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.

1
  • Sasu Andrei can you please pass me the script thanks in advance
    – user26792
    Feb 10, 2014 at 19:43

4 Answers 4

1

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

1
  • Is this the final code that you ended up with? If so please mark this as answered, it will help a lot of people. Aug 17, 2016 at 5:51
0

Wouldn't be easier to follow these examples?

http://openlayers.org/dev/examples/getfeature-wfs.html

http://openlayers.org/dev/examples/wfs-states.html

So, when you get this working using your shapefile, just adapt the google basemap layers. When both will be together, probably some projection problems will appear, so check some related posts in this web or in other web sites (there should be hundreds of posts dealing with projection stuff and google basemaps).

For google check here (there are more examples):

http://openlayers.org/dev/examples/google-v3-alloverlays.html

6
  • The shapefile it's working fine in Geoserver. I can get the feature info. The problem appered when I have combined Google Maps and my shapefile. I will check your examples. But I don't think will help from what I saw now. Thanks Nov 16, 2013 at 15:48
  • So you should post your error messages and not only your code to be debugged.
    – Gery
    Nov 16, 2013 at 16:18
  • I have no error message. Just doesn't work when I try to click a polygon. I don't know why, but I think it's because of Google Maps layer. The mouse pointer it's the hand drag tool. It like openlayers.org/dev/examples/wfs-states.html . In this example the GetFeatureInfo it's not activated. But the two layer are working ok. My layers are working ok but the GetFeatureInfo it's not working. I will try to put jpg's Nov 16, 2013 at 20:29
  • img713.imageshack.us/img713/6056/yqsu.png here it is Nov 16, 2013 at 20:45
  • that image is not very clear to me, do you have a live demo?
    – Gery
    Nov 16, 2013 at 21:15
0

After looong reading tutorials, examples I've did it. The examples shown above did'n helped too much. Anyway, I've founded something else, that explained very clear the procedure to GeatFeatureInfo.

If someone wants the script, please let me know.

Now I'm looking to enable filter in my script. For now, it's not working. I will read more about CQL filter. Thanks

3
  • 3
    Why not post what "else" you have found and accept your own answer?
    – Curlew
    Nov 20, 2013 at 10:18
  • I'm sorry but I don't understand what are you saying... Nov 20, 2013 at 19:17
  • Please share the script!
    – chrismarx
    Apr 2, 2014 at 2:10
0

If anyone is still stuck on the same problem, here is the complete solution;


var baseUrl = "http:localhost:8080/geoserver/ows?";
var layerName = "workspace:layer_name";

//GetFeatureInfoURL generator function
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 = 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=application/json';
  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;
};

Here are the two supporting function used in above code,

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;
}

If you want to add the getFeatureInfo request after clicking on the map, you can do something like below,

//Map click event
map.addListener("click", (e) => {
  var url = getFeatureInfoURL(e.latLng)
  fetch(url).then(res => res.json() ).then(data => console.log(data))
});

The response from getFeatureInfoURL will be geojson, from which you can easily extract the required information.

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.