[GIS] creating vector layer from OSM file using OpenLayers

openlayers-2openstreetmap

Using OpenLayers, I am creating a vector layer over a map.
This vector layer is created from an OSM xml file.

My purpose is to do some experiments in Prolog with this data, for example, querying the shortest path (following the declared "ways" in the OSM file) that will visit certain amounts of POIs, given a starting POI.

My problem is that when I load the nodes and ways in my map basically I see a big mess of features, too close to each other and some of them irrelevant.

My first idea was to filter some of these nodes in the original OSM xml file using XSLT, but after doing this filtering the map did not render the vector layer at all anymore. After some experimentation I realized that the problem was that the "way" elements were referencing non-existing node elements (since I filtered them using XSLT).

I could also have deleted the "ways" elements that reference non existing nodes (using XSLT again), but this does not seem to be a good idea since then I would be loosing valuable information for calculating the shortest path and other graph typical problems.

Then I arrived to the conclusion that I do not want to delete certain nodes, but just trying to make some of them non-visible by default in the map.

Then I use XSLT again to change the "visible" attribute to certain nodes. But the problem is that all the nodes in the file are shown in the map anyway, even if they have the attribute "visible" set to false, as in this example:

<osm version="0.6" generator="CGImap 0.0.2">
  <bounds minlat="50.8319000" minlon="4.3355000" maxlat="50.8599000" maxlon="4.3708000"/>
  <node id="125892" lat="50.8500083" lon="4.3553223" user="eMerzh" uid="15399" visible="false" version="6" changeset="9938190" timestamp="2011-11-24T22:05:32Z"/>
...
</osm>

Below the code I am using to create the vector layer from the OSM file:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
  <title>My OpenLayers Map</title>
  <script src="http://maps.google.com/maps/api/js?sensor=false"></script>
  <script type='text/javascript' src='OpenLayers.js'></script>
  <script type='text/javascript'>
    var map;
    var lat=50.8467493;
    var lon=4.3524950;
    var zoom=11;

    function init() {
        map = new OpenLayers.Map('map_element', {
            maxResolution: 156543.0399,
            numZoomLevels: 16,
            units: 'm',
            projection: new OpenLayers.Projection("EPSG:900913"),
            displayProjection: new OpenLayers.Projection("EPSG:4326")});

        var osm_layer = new OpenLayers.Layer.OSM(
            'OpenStreetMap Layer'
        );

        //Initialise the vector layer using OpenLayers.Format.OSM
        var pois_layer = new OpenLayers.Layer.Vector("Brussels POIs", {
            strategies: [new OpenLayers.Strategy.Fixed()],
            protocol: new OpenLayers.Protocol.HTTP({
                url: "brussels_center_filtered.osm",   
                format: new OpenLayers.Format.OSM()
                }),
                projection: new OpenLayers.Projection("EPSG:4326")
            });

        map.addLayers([osm_layer, pois_layer]);
        map.addControls([new OpenLayers.Control.LayerSwitcher({})]);

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

  </script>
</head>

<body onload='init();'>
    <div id='map_element' style='width: 500px; height: 500px;'></div>
</body>
</html>

Best Answer

OpenLayers OSM protocol does not know about 'visible' nodea, but you could easily extend the base class methods with a little bit of code that checks for the visibile attribute before adding the node to the list of nodes like the following (I hope your javascript-fu is strong, alsoe beware that this is untested code so it could not run right the first time):

    //Initialise the vector layer using OpenLayers.Format.OSM
    var pois_layer = new OpenLayers.Layer.Vector("Brussels POIs", {
        strategies: [new OpenLayers.Strategy.Fixed()],
        protocol: new OpenLayers.Protocol.HTTP({
            url: "brussels_center_filtered.osm",   
            format: new OpenLayers.Format.OSM({
                getNodes: function(doc) {
                        var node_list = doc.getElementsByTagName("node");
                        var nodes = {};
                        for (var i = 0; i < node_list.length; i++) {
                            var node = node_list[i];
                            if(node.getAttribute("visible")) {
                                var id = node.getAttribute("id");
                                nodes[id] = {
                                    'lat': node.getAttribute("lat"),
                                    'lon': node.getAttribute("lon"),
                                    'node': node
                                };
                            }
                        }
                        return nodes;
                    },
            })
            }),
            projection: new OpenLayers.Projection("EPSG:4326")
        });