0

All,

When I go to this url: OpenStreetMap, I see a map with a "relation" (I assume this is the term for the trail being displayed) on top.

I am trying to get this trail to also display on my Django website, where I am using django-leaflet.

At the moment my code looks like this:

<script>
    function map_init_basic (map, options) {
        map.setZoom(16);
        map.setView([51.6020, 4.8514]);
    }
</script>
{% leaflet_map "trailmap" callback="window.map_init_basic" %}

This sets the map to the correct area, but how do I add the actual trail?

Highest regards.

Freek
  • 1,097
  • 2
  • 12
  • 30

2 Answers2

1

Adding a trail onto the map is fairly straightforward. You ought to be able to add a line of code to the bottom of your map_init_basic() function like L.polyline(latlngs).addTo(map); (where latlngs is an array of [lat, lng] coordinate pairs that defines the route of your trail); or L.geoJSON(trail).addTo(map); (where trail is a GeoJSON format object that describes the trail). See the Leaflet documentation for Polyline and GeoJSON for more details.

The more complicated part is how to get hold of the lat/lng data for the trail. One way of doing this is to use the Overpass Turbo online API to retrieve the data from OpenStreetMap. Enter the following query in the left-hand side of the Overpass window, hit 'Run', then switch to the 'Data' tab to see the result:

rel(6754945);  // Id number of the OSM Relation to fetch.
(._;>;);
out;

The data tab should show the points that make up the trail encoded as an OSM XML file. You can either copy it and manipulate the text to extract the coordinates, or use the 'Export' menu in Overpass to download the data as GeoGSON or various other formats. The best way of getting the data onto your map depends on the detail of your application, but if data is a string holding the GeoJSON for the trail, then this would add it onto the map:

L.geoJSON(JSON.parse(data)).addTo(map);

Some other options for getting the trail coordinates are described in the answer to How to convert an OSM relation to a list of lat/lng points?

JRI
  • 1,766
  • 13
  • 25
  • Thank you, this is very helpful. I noticed that other sites do it this way (with a list of latitude/longitudes in the code) but I was hoping to avoid that because the relation is already on OpenStreetMap. But perhaps I'm misinterpreting what OSM and Leaflet are meant to be. I was already able to pull data for this relation down via the OSM API using OSMPythonTools, maybe I can get the list of lon/lats dynamically using Django. That feels like a workaround though. – Freek Jul 05 '21 at 14:18
  • Maybe I should just pull all those relations into my local DB and check for updates every now and then. This also protects me from surprises. – Freek Jul 05 '21 at 14:46
  • 1
    Although OSM is based on vectors, it's designed to be rendered server-side and consumed as raster tiles, formatted to show features of interest. Hence I'm not sure there's an especially convenient API for fetching individual features dynamically. However, OSMPythonTools can automate what I've suggested above. I'll add another answer... – JRI Jul 05 '21 at 15:44
1

Using OSMPythonTools you can use the Overpass API to fetch the trail relation from the OSM database, and extract its geometry as an array of coordinates:

from OSMPythonTools.overpass import Overpass
overpass = Overpass()

def fetch_relation_coords(relation): 
    rel = overpass.query('rel(%s); (._;>;); out;' % relation)
    coords = [el.geometry().coordinates for el in rel.elements() if el.type() == 'node']

    # Convert (lng, lat) to (lat, lng)
    latlngs = [[x[1], x[0]] for x in coords]

    return latlngs

latlngs = fetch_relation_coords("6754945")

# [[51.602685, 4.861282], [51.60629, 4.851437], [51.599504, 4.838481], [51.599561, 4.839231], ...]

I'm not familiar enough with Django to understand how to get the resulting coordinate array onto your web page, but once you have it in Javascript, you can add it onto your Leaflet map as a polyline with:

 L.polyline(latlngs).addTo(map);
JRI
  • 1,766
  • 13
  • 25
  • This is great I can definitely take it from here thanx! I’ll implement and accept the answer when it works! – Freek Jul 05 '21 at 17:03
  • I do run into a problem, the nodes are sorted, but per "way", so choosing a random order makes the trail filled with lines criss-crossing it if that makes sense. Sorting the ways by ID and then using the list of nodes in that order reduces the effect, however, there are still two line through the center connecting two opposing nodes. I hope this makes sense, I can't paste any images in here... – Freek Jul 05 '21 at 19:53
  • Ok, I solved this. In the elements object is an object called "relation", this object contains the order by which the way objects should be sorted. When you sort the "way" objects as defined, the nodes can be extracted in order and used for plotting the entire trail without weirdness. I deleted 2 previous answers here because I was confused. How best to add my findings to this page? – Freek Jul 05 '21 at 21:00
  • Well, the relation does not always seem to contain the correct order of the ways. I posted a follow-up question here: https://stackoverflow.com/questions/68375034/plotting-openstreetmap-relations-does-not-generate-continous-lines/ – Freek Jul 14 '21 at 12:41