User Tools

Site Tools


tecnica:gps_cartografia_gis:openlayers_900913

This is an old revision of the document!


OpenStreetMap con OpenLayers

Le mappe di OpenStreetMap (ma anche quelle di Google Maps e di Virtual Earth) utilizzano una proiezione Spherical Mercator. Tale proiezione ha codice EPSG:900913, che purtroppo non è compresa tra le proiezioni di PROJ.

Su un host GNU/Linux è necessario aggiungere una riga al file /usr/share/proj/epsg:

# Spherical Mercator
<900913> +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs

Vedere la FAQ a proposito di PROJ.4 e Virtual Earth.

Mostrare un mark sulla mappa OSM

Fare zoom e pan quanto basta per mettere il punto desiderato al centro della mappa, quindi cliccare su Permalink in basso a destra. A questo punto basta modificare l'URL, sostituendo lat e lon rispettivamente con mlat e mlon. Un esempio:

http://www.openstreetmap.org/?mlat=43.8200&mlon=11.13311&zoom=16&layers=0B00FTF

Questo trucco funziona sul sito di OpenStreetMap, purtroppo non funziona su altri simili che usano sempre OpenLayers, ad esempio http://www.informationfreeway.org/.

Dynamic layer update

We want to refresh the contents of a layer using a timer, every time we want to fetch new data from the server.

OpenLayers.Layer.GeoRSS

This is an example of a GeoRSS layer, updated every 120 seconds. Every point is drawn with the same icon, a pop-up will appear when the icon is clicked.

var friends;
 
function init() {
    ...
    // Add tangoGPS friends layer.
    friends = new OpenLayers.Layer.GeoRSS("Friends", "tangogps-friend.php", {
        projection: map.displayProjection
    });
    friends.icon = new OpenLayers.Icon(
        "icons/tangogps-friend.png");
    map.addLayer(friends);
    ...
    var tim = setInterval ("updateFriends()", 120000);
}
 
function updateFriends() {
    friends.clearMarkers();
    friends.clearFeatures();
    friends.loaded = false;
    friends.loadRSS();
}

The code tangogps-friend.php should return GeoRSS formatted text (like this example), with proper expire and no cache headers:

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Content-Type: text/xml");
...

OpenLayers.Layer.GML

This is a more complex example, using a GML layer in GML format. The GML geometry is drawn with the default style. The layer is reloaded by a timer every 120 seconds. We use a BBOX strategy, so that the layer is reloaded also when the bounding box changes. Layer is loaded via HTTP protocol.

var friends;
 
function init() {
    ...
    // Add tangoGPS friends layer.
    friends = new OpenLayers.Layer.GML("GML", "friends-gml.php", {
        strategies: [new OpenLayers.Strategy.BBOX()],
        projection: map.displayProjection,
        protocol: new OpenLayers.Protocol.HTTP({
            url: "friends-gml.php",
            format: new OpenLayers.Format.GML()
        }),
    });
    map.addLayer(friends);
    ...
    var tim = setInterval ("updateFriends()", 120000);
}
 
function updateFriends() {
    var now = new Date().valueOf();
    var bbox = map.getExtent().toBBOX();
    friends.setUrl("friends-gml.php?bbox=" + bbox + "&time=" + now);
}

The friends-gml.php should return a valid GML file (like this example) and it should be non cacheable (using the same headers of GeoRSS layer above). The script will be called with the following arguments:

friends-gml.php

The first call (without query parameters) is triggered by the second argument of the layer constructor. To optimize memory usage in the browser, the script friends-gml.php should honor the bbox request and return only the relevant features. Called without the parameter, it can return no features.

friends-gml.php?bbox=-10.77,41.32,11.72,52.57

Immediately after the layer creation, a new call is triggered by the BBOX strategy. This time the bbox parameter is automatically appended to the url declared with OpenLayers.Protocol.HTTP. A similar call is performed whenever a bounding box change event is detected.

friends-gml.php?bbox=-15.15,44.13,16.12,49.75&time=1232668479793

Every timer interval, the layer is refreshed. Reading new data is forced by setting a new and unique time parameter. In this case bbox is not automatically added (it was the timer which trigger the call, not the BBOX strategy), so we have to add it programmatically.

OpenLayers.Layer.Text

This is a very versatile example: every point can be represented by a different icon, a pop-up appears when you click an icon. The disadvantage is that all the layer features are loaded at every timer interval, no bounding box limit is enforced.

var friends;
 
function init() {
    ...
    // Add tangoGPS friends layer.
    friends = new OpenLayers.Layer.Text("Friends", {
        location:"friends-text.php",
        projection: map.displayProjection});
    map.addLayer(friends);
    ...
    var tim = setInterval ("updateFriends()", 120000);
}
 
function updateFriends() {
    // Remove markers and features.
    friends.clearMarkers();
    friends.clearFeatures();
    // Pretend the layers is not yet loaded.
    friends.loaded = false;
    friends.location = "friends-text.php";
    friends.loadText();
}

The text returned by friends-text.php should be non cacheable as always and contains a tab separated text, like this example.

This recipe can be improved by adding a bbox parameter (calculated at runtime) to the location of the layer, and forcing a call to updateFriends() whenever the viewport of the map changes.

tecnica/gps_cartografia_gis/openlayers_900913.1288963268.txt.gz · Last modified: 2010/11/05 14:21 by niccolo