Sunday 25 September 2016

openstreetmap - How do you get the nodes of an area in Overpass API in the "right" order?


I use the Overpass API to get the boundary of an OSM relation. I then use the result to display the boundary on a leaflet map. My problem is however, that the nodes are not in the "right order".


Leaflet of course expects to get a polygon in which the nodes are in the order in which they should be connected afterwards, like in the following picture:


How it should be


The Overpass API however just gives me the nodes in any order, like for example this:


Nodes in the wrong order



This problem results in the following output:


enter image description here


Is there some way I can get Overpass to give me the nodes in the "right order"? I guess that this is the only alternative, as I guess leaflet isn't able to reorder the nodes on its own (it can't really know which order is right).


It has to be possible to get the data in an automatic way. I only need to generate this data once (or maybe once a year) but for over 100 different areas.




Answer to scai's comment:


After closer inspection of the data, not taking the nodes in the order they appear in the result but taking them in the order they appear in the ways seams like the right approach. However, it is still a little more complicated.


There are two problems: First, who guarantees that the ways belonging to a relation are in the right order (all the boundaries I just queried seemed to be ordered the right way, but I have already found a lot of relations where the ways were not ordered in the right way).


Example: Let's assume I get the following data, and the relation consists of


{

red,
green,
blue,
yellow
}

Problem 1


Secondly, the ways don't all point in the same direction. This problem does definitely happen.


In the example below, the blue way points in the opposite direction than the other ways. Taking the nodes in the order they appear in the ways won't give me the right result.


Problem



A possible solution to all this would be the following algorithm: Start with the first way, add all nodes to an array, then search for a new way whose first or last node has the same id as the last added node, repeat until arriving at the first node ever added. But isn't there a better way to do this?



Answer



(I edited my answer for your follow-up questions)


You have to use the order in which the node IDs are referenced by the corresponding element in the XML file. In contrast, the order in which the elements appear in the XML file is completely irrelevant.


Furthermore, as you already discovered, a relation can contain multiple separate ways forming a single polygon. Here, the relation doesn't necessarily has to reference the ways in the correct order. Consequently the correct order of the ways has to be determined by looking at the first and last node of the way. Consecutive ways will share the same last and first node.


For a neat sorting algorithm you can take a look at the source code of JOSM.


Alternatively you might take a look at overpass turbo which provides a GeoJSON output which Leaflet should be able to handle.


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...