Prototypes Prototype docsP11 · Docs and assistant
Map of Aarhus (P37)
DocsPage 37 of 39

Map of Aarhus (P37)

Atlas is a map of Aarhus written for this prototype in plain JavaScript, with no dependencies at run time. It draws the city on the GPU, finds addresses and places as you type, and gives routes by car, bike and foot. It opens on the route from Nye, the new town north of Aarhus, to Aarhus H.

The data

Everything on the map comes from one file: BBBike's extract of OpenStreetMap for Aarhus, 25,709,550 bytes in the PBF format. It holds 2,443,807 nodes, 310,926 ways and 3,092 relations.

Atlas has its own reader for the format. It reads the blocks and inflates them with zlib. It decodes the protobuf wire format, the string tables, the dense nodes stored as deltas, the ways and the relations.

The tiles

The build writes vector tiles of Atlas's own format for zooms 10 to 16. A tile holds layers for water, land use, parks and forest, buildings, roads, railways, place names, street names and points of interest. Each feature is simplified for its zoom and clipped to its tile with a margin. Its coordinates are whole numbers written as varints.

The sea is built from the coastline. OpenStreetMap draws the coastline as lines with the land on their left, so the build joins the lines and closes them along the edge of the extract.

The 13,477 tiles are packed into four archives with an index, one for zooms 10 to 13 and one for each zoom after. The page reads a tile with an HTTP Range request. The Worker answers each Range request with status 206 and the requested bytes only.

Drawing

A Web Worker fetches the tiles in view and inflates them. It cuts the areas into triangles by ear clipping, holes included, and extrudes the lines into strips with joins and round caps. The page draws with WebGPU where the browser offers it and with WebGL2 where it does not. Both draw the same meshes with the same arithmetic.

While the next zoom loads, the tiles of the zoom before are drawn in its place. You can drag the map with inertia, zoom with the wheel or a pinch around the pointer, double click, and use the arrow keys and plus and minus.

Labels are placed by priority: towns before districts, stops before shops, main roads before side streets. A label goes only where it overlaps nothing placed before it. A street name follows its street letter by letter.

Routes

The build makes a road graph for car, bike and foot from the roads' tags: one-way streets, roundabouts, access and speed limits. A road without a speed limit gets the Danish limit for its class. An edge's weight is its travel time in tenths of a second.

Each graph is contracted into a hierarchy. Nodes are removed one at a time, the node that would add the fewest shortcuts first. A shortcut goes in only when a witness search finds no other path as quick. The car graph has 78,966 nodes and 98,099 shortcuts. The bike graph has 103,432 nodes and 183,182 shortcuts. The foot graph has 123,719 nodes and 284,041 shortcuts.

A route is two small searches upward that meet, so it takes a fraction of a millisecond. A pressed point is snapped to the nearest road through a grid of the road segments. The steps come from the street names and the angles between the roads.

From Nye to Aarhus H the router gives 18 minutes by car and 41 minutes by bike.

Reach

The reach tool shows where a mode gets to in 5, 10 and 15 minutes from a point. One search to every junction gives the times (PHAST), and marching squares turn them into areas.

The judge

The router is held against plain Dijkstra on the same graph before contraction. The tests compare 10,000 random pairs for each mode, and every pair has the same time. The hierarchy's path, unpacked into roads, is a path of the road graph that adds up to that time. The page against Dijkstra runs the same comparison in the browser, with the time of each method.

The map shows the attribution © OpenStreetMap contributors with a link to openstreetmap.org/copyright, and the data is used under the Open Database License.

Previous: Verifiable election (P36). Next: SQL database (P38).

How Prototype docs is built

The pages are written in Markdown and built into these pages and an index of 221 sections. The assistant answers from the index, and every answer names the sections it was taken from.