Build a ski trail map using OpenStreetMap and MTS

Guest

Guest

February 16, 2021

Build a ski trail map using OpenStreetMap and MTS

Guest

Guest

February 16, 2021

It’s been a snowy winter so far, and trails are busy with outdoor enthusiasts planning and navigating their trips with tools like Strava, OpenSkiMap, and Traveler Today. Many of these tools use trail data from OpenStreetMap (OSM), a free, community-built, open-source map of the world that forms part of the Mapbox streets basemap, as well as hundreds of other maps

Ski trails and 3D terrain by Traveler Today

Custom extracts of OpenStreetMap data let you add data layers or metadata from OpenStreetMap that isn't included in Mapbox Streets. Extracts can also be helpful if you need expanded styling or data preparation options, such as changing the zoom level at certain data appear.

This post shares examples of builders who are using OpenStreetMap data extracts combined with Mapbox to create ski trail apps. It provides notes for you to do the same, using Overpass Turbo and the Mapbox Tiling Service (MTS).

Open data ski maps

Developer Russell Porter built OpenSkiMap.org to visualize ski areas, runs, and lifts around the world. OpenSkiMap helps outdoor enthusiasts plan their next weekend adventure and also provides template code for developers to adopt their own OpenStreetMap extraction pipelines to produce custom interactive maps.

OpenSkiMap

Another project, Snow Social, is an iOS app built on OpenSkiMap data that allows skiers to see their friends’ location in real-time at different resorts and compare stats.

Snow Social

Export OpenStreetMap data

OpenStreetMap data is made up of nodes, ways, and relations. Features are labeled with tags, which you will use to query a specific type of feature. Learn more about the OpenStreetMap data model here.

Overpass Turbo is a tool for querying and exporting data from OpenStreetMap. To learn how to construct your own query use the Overpass Wizard with this tutorial or use the example query below. To understand how queries work in detail, read the Overpass Query Language documentation

  1. Open Overpass Turbo and pan the map to the area you would like to query.
  2. Enter the query below to return all ski trails (or ‘pistes’ in ski-lingo) within the map bounding box.
  3. Click ‘Run’ to view the result.
  4. Click ‘Export’ then save the result as GeoJSON.


[out:json][timeout:25];
// gather results
(
// query part for: “piste:type”
way["piste:type"]({{bbox}});
relation["piste:type"]({{bbox}});
);
// print results
out body;
>;
out skel qt;

Overpass Turbo query results

Tile the data with MTS 

Once you’ve downloaded your OpenStreetMap data as GeoJSON, use MTS to turn it into tilesets. Tiling your data helps the map zoom seamlessly and load quickly, even with large datasets. MTS can greatly reduce the amount of data preprocessing needed to create tilesets compared to other tiling pipelines. MTS uses custom configuration files called 'recipes' to manipulate your data at the feature and tile level via expressions. Expressions include operations such as filtering, ranking, unioning, converting data types, and removing properties for large-scale data optimization. With MTS, you can generate a tileset and transform your data in a single step.

Below is the recipe we use to transform and tile the OpenStreetMap ski trails extract.

This recipe does three things: 

  1. Sets the tileset zoom extent. 
  2. Removes feature properties that are not needed. 
  3. Sets a default description property for every feature.


{
"version": 1,
"layers": {
"ski_trails": {
"source": "mapbox://tileset-source/username/osm_trails",
"minzoom" : 0,
"maxzoom" : 11
"features" : {
"attributes" : {
"allowed_output" : [
“name”,
“piste:difficulty",
“piste:name”,
“trail_visibility”,
“piste:grooming”,
“piste:type”,
“piste:status”
],
"set": {
"description": [ "coalesce", [ "get", "description" ], "ski trail"]
}
}
}
}
}
}

Recipe options

Any good recipe allows for some customization. Let’s take a look at the settings used for our ski trails recipe and explain how and why you might want to adjust these.

Maxzoom 

The `minzoom` and `maxzoom` describe the ‘zoom extent’ of your tiles. Thanks to overzooming the maxzoom of your tileset does not need to match the highest zoom of your map. However, relying on overzoom may cause a loss in precision if you view a tileset beyond its `maxzoom`. In the example below, we can see the precision loss that happens in the tileset — zoom 5 on the left is jagged and simplified, while zoom 11 contains smooth high-resolution lines that mirror the contours of the ski trails.

Zoom 5 (left) vs Zoom 11 (right)

Attribute shaving

There are over 77 feature attributes associated with ski trails in the example region we downloaded from OpenStreetMap, but not all those metadata are necessary for our trail map. The recipe option `allowed_output` lets you choose which feature properties to keep in your output tileset. 

We chose the following attributes: 

  • "piste:difficulty" - the difficulty of the run 
  • “piste:name” -  the name of the trail 
  • “trail_visibility” - trail visibility 
  • “piste:grooming” - groomed status 
  • “piste:type” - type of ski run, such as nordic, downhill, etc.
  • “piste:status” - status of the run, such as open, closed, etc.

Setting a default feature property 

OpenStreetMap tags are not always consistent. Since the data is user-generated, there may be gaps from resort to resort and trail to trail. Some features may have a `description` tag, but others may not. In our recipe, we set a default value of “ski trail” for the `description` property if it does not exist in the data. The recipe option `set` sets new attributes on features and the Mapbox expression coalesce gets the feature’s description if it exists or, if the property doesn’t exist, it sets the property with the default value, “ski trail”. 

Publish the data into a tileset 

When you publish, MTS applies the recipe instructions to transform the data into a tileset that is hosted in your Mapbox account, where you can view size and property details and also preview the data. 

There are a variety of tools available to publish a tileset with MTS: 

  • MTS Data Sync if you want a quick interface to generate configurations for you. 
  • Tilesets-cli if you want a versatile endpoint-by-endpoint approach. 
  • MTS API endpoints if you want a language-agnostic format to integrate MTS into your own scripts or pipelines. 

We used the tilesets-cli to generate this tileset with three short commands. 

  1. Upload your source data. 

tilesets upload-source username osm_trails

  1. Create your tileset. 

tilesets create username.osm_trails --recipe ~/dev/mts-blog-post/recipe.json --name "osm trail data" 

  1. Publish your tileset.

tilesets publish username.osm_trails

Once the tileset is created, you can use it to add a layer in a map Style in Studio or use it as a vector tile source directly in your applications. 

Below is the Studio style editor with our ski trail tileset added as a new layer.

Build your own maps - for ski trails or otherwise - with OpenStreetMap data layers and share what you've built on Twitter using #builtwithmapbox!

Heading 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Heading 2

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Heading 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Heading 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Heading 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Heading 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

response = requests.get(

  "https://api.mapbox.com/v4/mapbox.temperature-raster-tileset/tilequery/40,-105.json",

    params={

        "layers": "temperature,wind_speed",

        "bands": "1708304400,1708311600",

    },

Optional caption
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque euismod maximus porta. Pellentesque vitae augue elit. Nam semper eros leo, nec hendrerit nunc aliquet quis. Morbi ac sapien tortor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur porta imperdiet lorem, ut aliquet orci pellentesque quis. Donec magna augue, molestie aliquam enim eu, auctor feugiat metus."

Ordered list

  1. Item 1
  2. Item 2
  3. Item 3

Unordered list

  • Item A
  • Item B
  • Item C

Text link

Bold text

Emphasis

Superscript

Subscript

No items found.
No items found.

Related articles