3

I am very new to OSM. I have to build an Java App for my MSc project. In this project, my app need to download raw data from OSM (XML format), parse to display it on my app. After that, I have to deploy routing service on my app. To be honest, I have never done it before so I am very confused now. Do you guys have any ideas or source code that can help me? Could you please help me?

Thank a lot.

NinjaCoder
  • 83
  • 1
  • 8

2 Answers2

17

You could use a 2d drawing framework like piccolo2d to render the map. And for the routing, you will need to build a graph describing the roads/ways on the maps, how they join and the distances represented. Having chosen a start point and an end point on the map an algorithm such as A star will then help you find the shortest path between the points.

Some more detail:

OSM XML dumps consist (it's more complicated than this: see the official docs for the full detail) of three classes of entities:

  • Nodes: representing single points on the map, defined by longitude and latitude. These either represent notable features (a huge variety, but, for example: a shop, an ancient monument, a gate on a path etc) or are part of a way.
  • Ways: representing polygons on the map. These are built up of an ordered list of nodes (referenced by id) and can represent linear things such as roads and paths (relevant to your routing problem) but also bounded areas such as field or forest boundaries, the shapes of urban areas, lakes, rivers etc.
  • Relations: which I won't address here, but you can find more about these in the official docs.

Each of the above three node types will have additional data associated with them in the form of 'tags' which are key-value (string) pairs specifying the type of entity represented by the node/way. A general list can be found here and a list for routing here. An example drawn from the OSM website representing a small local road (in this case in Germany):

<!-- The nodes representing points along the way -->
<node id="298884269" lat="54.0901746" lon="12.2482632" ... />
<node id="261728686" lat="54.0906309" lon="12.2441924" ... />
...
<node id="298884272" lat="54.0901447" lon="12.2516513" ... />

<!-- A way, built of the points above, with a tag
     declaring it to be an unclassified road -->
<way id="26659127" ...>
    <nd ref="292403538"/>
    <nd ref="298884289"/>
    ...
    <nd ref="261728686"/>
    <tag k="highway" v="unclassified"/>
</way>

Where two ways intersect (e.g. when two roads cross) they will share a node in common at the crossing point.

To filter down to the data required to generate a routing graph, you need to:

  • Read the XML for the area of interest, reading at least the nodes and ways.
  • Filter out, leaving only the ways you want based on their tags (for instance where k="highway" etc).
  • Filter out all nodes but the ones referenced by the remaining relevant ways.

Having isolated only the information you require, you then need to transform from the OSM format to something more suitable for routing. Although the OSM graph as described can be used for routing, it is more efficient to represent the map as a set of nodes for the start and end of each way, and any intersection points between ways and a set of edges representing the path between intersections, along with their lengths.

For example, you might want to transform the following (with intersecting ways a-b, c-d, e-f):

OSM nodes and ways

to something more like:

Routing graph

Where only the end nodes and the intersecting nodes remain. In this representation you would have transformed from 3 ways to 8 edges in your routing graph (a-x, c-x, x-e, e-d, x-y, e-y, y-f, y-b) each edge with an associated distance that you calculated by stepping along the nodes in the way, accumulating distance as you go: (e.g. a-x: 200m, e-y: 350m etc). Note that you will be needing to calculate distances between adjacent points in longitude/latitude space for which you can find a formula here.

You could represent this data using your own datastructure or using a third-part graph library such as JGraphT or Jung. From here, routing is (crudely, and assuming for simplicity that the set of nodes you have remaining are adequately fine-grained to represent all required start/end points) a matter of choosing the node representing the start of your journey, the node representing the end and using an algorithm such as A-star (as mentioned above) to calculate the shortest path.

The only catch is that, as far as I can remember, neither of the two libraries I mention have an implementation of A-star. But you can get the correct result by running Dijkstra's shortest path (present in both libraries) at lower speed - and then implement A-star yourself when you're more confident with the concepts.

To make all of this more interesting: instead of using distances you could route on estimated travel time (taking the average speed on the road into account). Or you could modify the distance based on the desirability of the route: e.g. for cycling, down-weight the distance on roads with less traffic in order to select longer but safer routes. Alternatively for hiking, downweight the distance for paths that pass through particularly scenic areas or near a landmark such as an ancient monument or a pub.

Given that there are decent existing routing services for OSM data (e.g from Cloudmade) the main reason you would want to do something like this is in order to use your own custom distance metric...

Community
  • 1
  • 1
Alex Wilson
  • 6,690
  • 27
  • 44
  • Thank Alex, I will try picolo2d as your suggestion. At this time I am trying to use JXMapKit, but I just have slippy map so I cant use them to build a routable data. Could you give me any ideas? Cheers. – NinjaCoder Jun 23 '12 at 18:53
  • Thank Alex alot :) I am trying to implement my app. It is based on your ideas mostly :). – NinjaCoder Jun 26 '12 at 23:47
  • @Thanh No problem, and if the answer is helpful, would you mind up voting it and accepting it? Thanks, Alex – Alex Wilson Jun 27 '12 at 06:12
  • Oh,I am sorry about that. Your answer is really helpful. At this time, I am wondering how I can translate real coordinate to screen coordinate. My ideas are that I will download slippy map by using JXMapkit. After that, I load OSM data, parse OSM data into nodes and ways that is useful for routing services. Next, I will draw a graph indicate ways and nodes, and repaint on the slippy map. Finally, I will apply routing algorithms to calculate shortest path. Therefore, I think I need to transform real coordinate to screen coordinate in order to draw map. What do you think? Thank a lot – NinjaCoder Jun 27 '12 at 11:15
  • You need to project from longitude and latitude into a difference coordinate reference system. The longitude and latitude is probably in WGS84 and the 2d projection scheme used for the slippy map tiles for OSM and Google is a modified spherical mercator. See here for some details on what to do: http://docs.openlayers.org/library/spherical_mercator.html. – Alex Wilson Jun 27 '12 at 11:52
  • @ThanhDoan Could you accept this answer (click the tick), and upvote (click the up arrow) if it's been helpful. Thanks. Alex – Alex Wilson Jun 27 '12 at 21:31
  • Nice answer, there should +5 buttons! – Karussell Jun 29 '12 at 12:50
  • Dear Alex: I am developing my app, it seems fine, and I hope I can give you my result next week. Sorry about upvote, I did not have enough credits for this, so I could not vote it for you. To be honest, your answer is really useful and nice. Best of wishes. – NinjaCoder Jul 06 '12 at 12:19
  • Glad to be of help, and let me know how you got on. Is the app on github? – Alex Wilson Jul 06 '12 at 12:22
  • Hi Alex, I have finished map app with routing services. It is very good. Thank you so much. Now, my supervisor required my app to have a multiple start points and end points. Also, it will route exactly for each pair of them. Moreover, I have to demonstrate a car running on each route. It is very interesting. Could you give me any ideas for this task? Thank you so much. – NinjaCoder Aug 02 '12 at 19:35
8

Alex answer contains the important parts. Especially to reduce the nodes to only the necessary ones!!

If you are interested: I've developed all this stuff in Java in my GraphHopper project, with a very rough Swing UI.

Also Dijkstra, bidirectional dijkstra and astar are implemented. In my tests a star is 30% slower than the dijkstra when forcing it to return no approximation for the route. In the future I'll experiment to allow approximation, but in the mean time you can use the bidirectional dijkstra which is ~50% faster than the normal dijkstra ;) and works like this:

enter image description here

Karussell
  • 17,085
  • 16
  • 97
  • 197
  • Nice explanation and very clear animated GIF - although it's slightly hurting my eyes! – Alex Wilson Jun 29 '12 at 12:53
  • thanks. yeah I hate animated GIFs (also this one with its ugly colors ;)) but I didn't want to make a video only because of this ;) also you can hit ESC to stop it – Karussell Jun 29 '12 at 12:54
  • It's all good though - there's nothing quite as powerful as an animation like this to help people understand an algo. – Alex Wilson Jun 29 '12 at 12:57