Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I'm a beginner with programming, and javascript. I went to the FOSS4G-NA conference and was very inspired to learn more. I'm trying to learn PostGIS, and have come across a very useful tutorial for using PostGIS with Openlayers and geoserver: http://workshops.opengeo.org/postgis-spatialdbtips/

I've followed through all of the examples, but one of many things I don't understand: The examples show how to retrieve data from the postgis database and display on the map, or show how to calculate something within a distance of the map click. What about retrieving the clicked taxlot, then using the id of that taxlot to perform other spatial queries?

For example, I'm trying to build up an example based on the concepts for the tutorial. I want the user to click a watershed (a polygon layer), and have the map return the outline of the clicked watershed, as well as highlight/send to the map any withdrawal point data contained within that watershed, and produce some summary output (such as the total number and withdrawal amounts) and place that into the iframe on the page.

My strategy would be:

  • Have one function retrieve the clicked watershed, output the selected watershed vector to the map, and return the ID of that watershed and store it as a variable.

  • That variable would then be passed to a second function where the spatial query using st_contains is performed to select all of the points within the taxlot, and then output those selected building vectors to the map.

  • A third function would perform a similar query to the second function, except output the result of a summary calculation to the iframe.

Right now I'm stuck on whether this strategy is right, as I'm a bit lost on the code to both retrieve clicked attribute data and store it as a variable, as well as display it using geojson. Clicking in my map page gets me the error that my clicked_shed variable is null, in my getWatershed function. Right now I've only created a function to retrieve the ID of the clicked watershed, and a function to display those withdrawal points within that clicked watershed. I'm so inspired by all of this I think my first task after I understand this better will be to write some easy tutorials following on to this existing tutorial for others in my position. There can never be enough examples and tutorials in my opinion.

Can anyone provide a lowly beginner with any thoughts?

    var x = -8684372;
    var y = 4765431;
    var zoom = 10;
    var map, json_layer;

function init(){

    initMap();
    var wwms = new OpenLayers.Layer.WMS( "Opequon Sub-watersheds","/geoserver/wms?",
               {
                transparent:'true',
                layers: 'medford:subshed2',
                'format':'image/png'},
               {'reproject': true});
    var swms = new OpenLayers.Layer.WMS( "Opequon Streams",
                    "/geoserver/wms?",
               {
                transparent:'true',
                layers: 'medford:OpequonStreams',
                'format':'image/png'},
               {'reproject': true});
    map.addLayer(wwms);
    map.addLayer(swms);

    map.events.register("click", map, getWatershed);
    map.events.register("click", map, getFeatures );

    }

    function initMap() {

        // Initialize our map using Mercator as the internal units.
        // That means our bounds, center, resolution, all have to be in Mercator.
        var options = {
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326"),
            units: "m",
            numZoomLevels:20,
            maxResolution: 156543.0339,
            maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508,
            20037508.34),
            controls:[new OpenLayers.Control.MouseDefaults(),
                      new OpenLayers.Control.LayerSwitcher(),
                      new OpenLayers.Control.PanZoomBar()]
        };

        map = new OpenLayers.Map( 'map' , options );

        var gmap = new OpenLayers.Layer.Google(
            "Google Physical", // the default
            {type: G_PHYSICAL_MAP, 'sphericalMercator': true}
        );
        var gsat = new OpenLayers.Layer.Google(
            "Google Satellite",
            {type: G_SATELLITE_MAP, 'sphericalMercator': true}
        );
        map.addLayers([gmap, gsat]); 
        map.setCenter(new OpenLayers.LonLat(x, y), zoom);
    }

    function getWatershed(e) {
        var geojson = new OpenLayers.Format.GeoJSON();
        // Get the mercator coordinates from the viewport
        var xy = map.getLonLatFromViewPortPx(e.xy);
        // Find the watershed ID.
        var sql  = "select st_asgeojson(the_geom), id ";
            sql += "from medford.subshed2 ";
            sql += "where st_contains(the_geom,st_transform(st_setsrid(";
            sql += "st_makepoint(" + xy.lon + "," + xy.lat + ")";
            sql += ",900913),26918))";
        var config = { 
              "method":"GET",
              "url":"04-sql-to-json.jsp",
              "async":false,
              "params":{"sql":sql}
              };
        var xmlhttp = OpenLayers.Request.issue(config);
        var clicked_shed = geojson.read(xmlhttp.responseText, "FeatureCollection");
            var id = clicked_shed.attributes.id;
            getFeatures(id);
        }

    function getFeatures(id) {
        var json_url = "04-sql-to-json.jsp?sql=";
        var sql = "select st_asgeojson(st_transform(withdraw.the_geom,900913)),
            shed.id
            from medford.subshed2 shed, medford.withdrawals6_opequonUTM withdraw
            where st_contains(shed.the_geom,withdraw.the_geom)
            AND shed.id = '" + id + "'";
        json_url += escape(sql);
        if (json_layer) {
        json_layer.destroy();
            }
        jsonlayer = new OpenLayers.Layer.Vector("GeoJSON", {
                strategies: [new OpenLayers.Strategy.Fixed()],
                protocol: new OpenLayers.Protocol.HTTP({
                url: json_url,
                format: new OpenLayers.Format.GeoJSON()
                })
            });
        map.addLayer(json_layer);

    }
share|improve this question
    
Passing a variable between functions that results in Null sounds like an issue of scope. You'd have to make your xy variable global to access it between different functions I believe. –  Roy May 11 '12 at 11:32
add comment

2 Answers 2

Without knowing the exact workings of your 04-sql-to-json.jsp file, it seems as though you are building the SQL in javascript, and using the jsp to execute the query.

This is somewhat of a security hole, see SQL injection on wikipedia

share|improve this answer
add comment

You should parse response inside success function:

OpenLayers.Request.GET({
  async: false,
  url: "./04-sql-to-json.jsp",
  params: {sql: sql},
  success: function(e){
    features = geojson.read(e.responseText, "FeatureCollection");
  }
});
id = features[0].attributes.id; 
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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