1

I am trying to show the boundary of relation 4569(Brugge, West Flanders, Flanders, Knokke-Heist) on an OpenLayers 3 type map, like http://nominatim.openstreetmap.org . But I don't know how to proceed.

These are the things I am doing:

  1. I am querying Overpass API with the following parameters:

data=[output:json];relation(4569); out geom; out center;

This query gives me back the information about the relation with the id of 4569 from OpenStreetMaps.

The result set from this query is multiple ways, which have their role set as outer. I am combinining these ways to create a polygon, and storing them in an array.

foreach ($geom['members'] as $_poly) {
        if ($_poly['role'] != 'outer' && $_poly['role'] != 'inner') continue;
        if ($_poly['role'] == 'outer') {
            foreach ($_poly['geometry'] as $latlon) $poly['outer'][]=array($latlon['lon'], $latlon['lat']);
        } else {
            $poly['inner'][]=array();
            foreach ($_poly['geometry'] as $latlon) $poly['inner'][count($poly['inner'])-1][]=array($latlon['lon'], $latlon['lat']);
        }
}
if ($poly['outer'][0] != $poly['outer'][count($poly['outer'])-1]) $poly['outer'][]=$poly['outer'][0];
$out['polygons']=$poly;

Afterwards, this array is sent to javascript, where I process it, and try to add a Polygon object to an OpenLayers 3 map. This is the javascript code I use. (It is wrapped in a JS prototype made by me)

Map.prototype.addPolygon = function(name, data) {

    var _coordinates=[], i;

    for (i=0; i<data.outer.length; i++ ) {
        console.log(data.outer[i]);
        _coordinates.push(ol.proj.transform(data.outer[i], 'EPSG:4326', 'EPSG:3857'));
    }

    console.log("Creating polygon", _coordinates);
    var Polygon = new ol.geom.Polygon([_coordinates]);
    var feature = new ol.Feature({
        name: name+"-outer",
        geometry: Polygon
    });
    this.polygons[name]=Polygon;

  var polyStyle = new ol.style.Style({
    fill: new ol.style.Fill({
      color: [121, 115, 251, .2]
    }),
    stroke: new ol.style.Stroke({
      color: '#051165',
      width: 2
    })
  });

  this.vectorSource.addFeature(feature);
  feature.setStyle(polyStyle);

  this.map.getView().fit(Polygon, this.map.getSize()); 

}

Below you will find two images, the first is the end result which I get, and the second is the end result which Nominatim gets(my desired result). If you observe, you will see that the borders of my polygon are all messy, and there are additional lines in my polygon.

My end result

Nominatim result - the desired result

What am I doing wrong? If I am doing the same thing with boundaries which are represented by a single WAY, everyting works as expected.

1 Answer 1

2

That's quite a common issue. MP relations in OSM don't have to adhere to a specific sequence, i.e. your conversion routine needs to take care to put all single ways into an overall correct sequence. That even applies if you request data via out geom;.

Please see this thread for a more detailed discussion (including the other posts mentioned in there): https://help.openstreetmap.org/questions/50685/overpass-api-wrong-order-of-nodes

2
  • Yes, this did the trick. But what abbout inner rings? For example, relation id 7382, when viewed on nominatim.openstreetmap.org has one inner ring. When fetched with Overpass API, it returns multiple ways which are marked by role->inner. I can connect those ways also, as I am doing right now with the outer ring, but what if a relation has multiple inner rings? How can I be sure that I am connecting the ways correctly? Commented Aug 11, 2016 at 10:20
  • 1
    You could check how this is done in overpass turbo: overpass-turbo.eu/s/hNU ... the respective library osmtogeojson already has this implemented. Maybe you could delegate the coversion from osm to geojson to such a library and only display geojson in your openlayers3 app. Otherwise you would need to implemente some logic similar to this code snippet in osmtogeojson.
    – mmd
    Commented Aug 11, 2016 at 10:28

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.