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.
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:
- 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.
- The terrain grid will improve. Resampling against a newer grid updates every figure without a data migration over user rows.
- 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.