Visualizing ski resorts
/ 8 min read
Table of Contents
For Day 3 of the #30DayMapChallenge, the theme is Polygons.
After two lines from home, I stayed in the Alps. This time I wanted to compare ski resorts that touch Tirol: which have the most downhill kilometers in the available mapping data, and what can their outlines tell us? Getting the numbers and polygons into the same view meant being careful about what each source actually describes.
The comparison
Open the standalone map · Download the ranking as CSV
Ski Arlberg leads this comparison with 272.1 mapped downhill kilometers, followed by Saalbach–Hinterglemm–Leogang–Fieberbrunn at 267.1 km and SkiWelt Wilder Kaiser–Brixental at 234.0 km.
I’ve kept one decimal place to show the calculated values, but that isn’t a claim of survey-level accuracy. The numbers are only as good as the mapping behind them.
What the kilometers mean
I used OpenSkiData, with a snapshot downloaded on 2 November 2026. The calculation is straightforward: add the downhill-run lengths across the source’s difficulty categories, leaving out Nordic trails and lifts. I kept those values rather than swapping in advertised piste totals when a number looked unexpected. Mixing the two would make the comparison harder to interpret.
The broader source pool contains 375 operating downhill-area records with an Austrian country association, before narrowing the comparison to resorts that touch Tirol. Of those, 355 have downhill-length statistics; 20 missing values are not treated as zero.
The less straightforward part was deciding what counts as one area. A ticket alliance, a destination and a lift-connected network aren’t the same thing. I left out broad alliances and duplicate component records: counting Lech/Zürs again alongside Ski Arlberg, for example, would count part of the same network twice. Mayrhofen–Hippach stays in, although its different mountains don’t all connect by lift.
The geographic scope is an editorial decision: I only picked ski resorts that touch Tirol, rather than trying to rank all of Austria. A resort can extend into a neighboring state or country and still belong in this comparison. I also kept point-only records such as Sölden and SkiWelt eligible: missing an outline shouldn’t disqualify an area with length statistics.
I kept each resort’s full source total rather than cutting pistes at Tirol’s state boundary or the Austrian border. Touching Tirol determines the geographic scope, not where the kilometers stop. That leaves an editorial selection of ten reviewed resort areas, rather than an official top ten.
An outline is not a piste
The polygons help locate the resorts, but I didn’t use their area to calculate the bars. An outline can include forest, rock, buildings and all the space between pistes. Measuring that would answer a different question from how many kilometers of downhill runs are mapped.
The first problem with drawing those outlines was that many records don’t have one. Only 188 of the 375 OpenSkiData records in the broader Austrian source pool have Polygon or MultiPolygon geometry. The other 187 are points. Converting those points into circles or invented boundaries would make the map look more complete without adding evidence.
For four ranked areas, I could use Land Tirol’s planning polygons as a separate source. That required reviewing the matches rather than assuming similar names meant identical areas:
- SkiWelt: two original planning features.
- Serfaus–Fiss–Ladis: the Komperdell feature.
- Ischgl–Samnaun: Silvretta Schiarena, without the Swiss extent.
- Sölden: that’s the Ötztaler Gletscher.
The catch is their age: these planning envelopes date to 30 October 2011. I used dashed outlines and a visible year so they wouldn’t look like current resort boundaries.
Ischgl–Samnaun shows why that distinction matters. The planning polygon covers only part of the area, while the bar keeps the full cross-border length. It helps locate the resort, but it doesn’t enclose every kilometer counted in the chart.
For Sölden, the Ötztaler Gletscher polygon contains the OpenSkiData reference point, and 219 of 223 associated piste records intersect it. That supports the match, not an equivalence between the historical envelope and today’s footprint. The original planning-feature name remains in the downloadable data.
The Tirol layer contains 102 valid polygons, retained without clipping or geometric union; its STAND field supplies the 2011 date. Six of the ten displayed areas use original OpenSkiData outlines, while four use the reviewed Tirol fallbacks. No convex hulls, artificial buffers or substitute boundaries are generated. Neither source’s record count is a count of unique resorts: overlaps and component records are retained, not deduplicated.
The polygon review documents those associations. Neither dataset’s geometry is modified to make the sources agree.
Keeping the labels readable
Putting ten names on a small part of the Alps turned out to be a separate mapping problem. Avoiding overlapping text wasn’t enough. A connector could still run across another resort, or two labels could end up in the opposite north/south order from the areas they describe.
For label placement, I used the occupancy-bitmap approach described in Fast and Flexible Overlap Detection for Chart Labeling, with application-specific extensions. d3-annotation renders the labels.
Finding an empty rectangle for the text is only half the problem; the connection back to the resort needs to remain readable too. I treated each label and its leader as one connected obstacle, including the small, visually empty gap before the text. Leaders can’t cross another ranked resort’s polygon. Each starts at a visual interior center of its own polygon, rather than whichever boundary vertex makes placement easiest.
Hard rules alone don’t produce a useful layout, so I also added placement preferences. Labels tend outward, away from the basemap, with a local north/south preference to keep their relative positions sensible. Covering the regional basemap adds a cost. Together, these encourage a loose surrounding arrangement without forcing names into fixed slots around an oval.
Bregenz, Innsbruck and Salzburg stay anchored to their actual reference points. Hover changes the highlight, not the geography or the label positions.
Sources and limitations
I kept the map self-contained: it renders from local files without requesting tiles or querying a ski-data API when you visit. This post stores its own copy of the figure, so later changes to the challenge site won’t silently change the comparison here.
- Ski outlines and downhill statistics: OpenSkiData / OpenSkiMap.org, including OpenStreetMap contributors, Skimap.org, Who’s On First and Mapterhorn. The reduced ski dataset is distributed under ODbL 1.0.
- Historical planning polygons: Land Tirol – tiris, Schigebietsgrenzen, CC BY 4.0.
- Political context and reference places: Natural Earth, public domain.
Ranking values and calculation, review decisions and the snapshot manifest are available alongside the figure. The challenge repository contains the preparation scripts and source notes.
Additional downloads include the OpenSkiData polygons, Tirol polygons, OpenSkiData coverage, Tirol dates and Sölden match, reviewed crosswalk, spatial audit and reproduction notes.
Country and region classifications can be coarse or inconsistent, especially near borders. Selected polygons remain intact; the generalized Austrian border does not validate, clip or reclassify them. Shared state edges are drawn once. Administrative lines are context, not surveyed boundaries, and official resort boundaries have not been independently verified. “Operating” is a source classification, not a statement that lifts or pistes are open today.
The restrained background, categorical source colors and narrow-screen layout follow Datawrapper’s symbol-map guidance. Fill color does not encode size, quality or activity. Underneath, it’s static HTML, CSS, JavaScript and local Leaflet, with permanent SVG labels. I used AI assistance for source inspection, data preparation, implementation and checks.
For me, the useful part is seeing the mapped networks and their uneven boundary coverage together. The next step would be checking newer planning data and reviewing more resort groupings, rather than adding more decimal places. This version isn’t a guide to today’s open pistes, snow conditions, land ownership or the boundaries a resort would draw for itself.
Making room for charts in Cactus
This post was also an opportunity to extend this blog’s Cactus theme to give charts like this more room. The normal text column works well for reading, but squeezing a map, long resort names and a bar chart into that width would make all three harder to use. I wanted wider figures without making the paragraphs wider too.
Posts can now opt in with wideFigures: true in the frontmatter. In MDX, WideSection lets a figure extend beyond the text column while keeping the prose at its usual reading width. On larger screens, the table of contents has its own column so the chart doesn’t run underneath it. Other posts keep the existing layout.
The VisualizationEmbed component loads a local copy of the chart in an iframe. That keeps its styles and scripts separate from the blog, while a small message bridge synchronizes light and dark mode and adjusts the frame height to its content. The chart responds to the width it actually gets: map and ranking sit side by side when there’s room and stack when there isn’t. This gives me a reusable way to include interactive charts in future posts without rebuilding the page layout each time.
Let’s see if I find the time to contribute that upstream.
I used Pi Coding Agent with gpt-6.1-sol to create the chart.