Reading route heights from the terrain model

This post was written by Claude.

A GPX track's heights come from the recording device's barometric altimeter, which drifts with the weather. On one of our test tracks it was 737 m above the ground within 1.5 km. Snowdesk now takes a route's heights from the terrain model instead.

Routes and trips

A ski tour is usually planned before anyone sets off. The line is drawn in a planning tool such as swisstopo or Skitourenguru, or it is a track that a watch or phone recorded on an earlier outing. Either way it leaves as a GPX file: a list of points, each with a latitude, a longitude and a height.

In Snowdesk you upload that file and it becomes a route. The route is drawn on the map over the day's avalanche bulletin, and Snowdesk works out the ground under it: the slope angle every 25 m, how much of the line is on steep terrain, and the legs the tour splits into, its climbs and descents. A route is for checking a tour before you go.

A trip is a route with a date, a meeting place and a meeting time. It can be shared with the rest of the group.

Most of those figures depend on the route's heights. Until release 2026.09.29 Snowdesk took them from the GPX file, and on some tracks they were hundreds of metres wrong.

Where the heights came from

A GPX file's <ele> values are what the device's barometric altimeter reported, and an altimeter measures air pressure, not height. Over a short span it tracks the shape of the ground well. Over a morning the pressure changes with the weather, and the heights move with it.

Take one of our test tracks, Mont Fort – Backside. The recorded height starts 139 m above the terrain model. By 1.5 km in, it is more than 700 m above the model, and the skier is going down the whole time. Snowdesk cut that stretch into a 215 m climb followed by an 874 m drop. On the terrain model it is one descent. The stored ascent for the whole track was 478.8 m; the model says 337.2 m.

Device height versus terrain-model height along Mont Fort – Backside Over the first 1.5 km the recorded height climbs to about 3,660 m while the terrain model shows the ground descending to about 2,910 m. The two lines converge later in the tour. 2,0002,4002,8003,2003,6000 km2 km4 km6 km8 km10 km12 km 737 m apart at 1.5 km Device altimeter (GPX) Terrain model
Mont Fort – Backside. Recorded ascent 478.8 m, terrain-model ascent 337.2 m.

Every figure built on those heights was wrong in the same way: the profile, the legs, the ascent and descent totals, and the along-track gradient.

Reading heights from the ground

We already had the terrain model's heights to hand. To work out slope angles, the slope sampler visits the 5 m terrain grid every 25 m along a route. The height at each of those points is one more read from a tile that is already in memory. The sampler now keeps that height alongside the angle.

The new part is merging those 25 m sample points into the track, rather than only reading heights at the vertices the file stored. A planned route only has a vertex where its line turns. Read at the vertices alone, a straight 1 km line over a hill reports no climb at all. With the sample points merged in, the line climbs the hill.

Where the terrain model has no data (off the edge of the Swiss grid, for example) the device height is still used, but it is moved onto the model's level first. Each gap is shifted by the difference between device and model measured at the known points either side of it. Otherwise an altimeter that is 600 m out would put a 600 m cliff at the edge of the model's coverage, and the totals would count it. Shifting the gap keeps the shape the device recorded, which altimeters get right, and drops its absolute level, which they get wrong.

Why nothing stored was rewritten

The model's heights are applied when a route is read, not written back over the uploaded track. There are three reasons:

  1. The upload is the user's. Comparing the device heights with the model is also how we detect a recording fault, so the device series has to survive.
  2. The terrain grid will improve. Resampling against a newer grid updates every figure without a data migration over user rows.
  3. The stored track is the fallback. If a slope record can't be matched to the stored points, the route is shown with its stored track rather than pinning a height to the wrong patch of ground. That only works if the stored track is still the one the user uploaded.

One set of figures

One rule, climb_figures, now produces ascent and descent for every surface that shows them: the routes feed, both trip payloads, the route row, the trip page and the past-trip row. They can no longer disagree with each other.

On Mont Fort – Backside the route header now shows an ascent of 337 m, the terrain model's figure, rather than the 478.8 m stored from the device.

Mont Fort – Backside open on the map on a phone. The route header reads Ascend 337 m · descend 1,906 m and 12.9 km · 3.4 km steep terrain above the height profile.
Mont Fort – Backside on a phone, with ascent and descent read from the terrain model.