Chapter Two

A Line With Character

Five stations, proper spacing, and the first signs of personality.

A two-station metro is a proof of concept. A five-station line is a transit system. The jump from two to five introduces problems that two stations never had: spacing, rhythm, label collision, and the question of what a line actually looks like when it has enough stations to have character.

Let's build a proper line. We'll call it Line 1 of our fictional Metro Lumina — a transit system that exists only in this guide but will grow more complex with each chapter.

Live Editor — Five stations on a horizontal line

That works, but it's lifeless. Every station is equidistant. Every label floats at the same height. The line is perfectly horizontal, like a ruler. Real transit lines aren't like this — stations cluster in city centers and spread out in suburbs. The line has rhythm.

Spacing Tells a Story

On a geographic map, station spacing reflects actual distance. On a schematic map (the style we're building), spacing is a design choice. Most transit maps use a hybrid approach: roughly even spacing in the center, slightly wider at the edges.

But there's a subtler tool: uneven spacing signals importance. A tighter cluster suggests a busy downtown core. A wide gap suggests a long suburban stretch. The data is in the whitespace.

Try This

In the editor above, move "Central" to x: 280 and "Old Town" to x: 200. Notice how the tighter center spacing creates a visual "downtown" cluster. Then push "Park North" out to x: 580. The wide gap tells the reader: that last stretch is a long ride.

Label Placement

On a horizontal line, labels go above. Simple enough. But what happens when the line isn't horizontal? Or when labels overlap? Label placement is one of the hardest problems in cartography — entire PhD theses have been written about it.

We won't solve the general case. Instead, we'll use a pragmatic approach: alternate above and below. For horizontal lines, odd-indexed stations get labels above, even-indexed get labels below. This eliminates most collisions with zero complexity.

Live Editor — Alternating label placement

The alternating pattern instantly makes the map more readable. The thin tick marks connecting each label to its station are a small touch borrowed from professional transit maps — they resolve ambiguity when stations are close together.

Making It Diagonal

Real metro lines aren't horizontal. They follow the geography of their city — running north-south, curving along a river, climbing a hillside. Let's tilt our line and see what happens to the labels.

Live Editor — A diagonal line with adapted labels

Now we're computing label position based on the track's direction at each station. The perpAngle — the angle perpendicular to the track — tells us which way to push the label so it doesn't overlap the line. Alternating the side multiplier still gives us the above/below stagger, but now "above" and "below" are relative to the track direction, not the page.

This perpendicular angle concept will come back repeatedly. In Chapter 4, it's how we offset parallel lines. In Chapter 5, it's how we orient station pill shapes. Getting comfortable with "perpendicular to the track direction" is the single most useful geometric intuition for transit map rendering.

The Data Model So Far

Let's formalize what we've built. Our data model for a single line:

Live Editor — Clean data model for a single line

Notice the key change: the rendering logic is now a renderLine() function that takes a data object and returns SVG. The data describes what to draw; the function decides how. This separation will be essential when we have multiple lines — we'll call the same function for each line with different data.

Also notice the track angle computation for mid-line stations now uses prev and next — it averages the direction from both neighboring segments. This gives a smoother angle at stations where the line changes direction. Try moving "Central" up to y: 60 — the labels at the bend point stay properly placed because they're computed from the averaged angle.

Why We Use IDs

Each station now has an id field. We don't need it yet, but it's about to become critical. When two lines share a station, they reference it by ID — "Line 1 stops at 'central', and so does Line 3." The ID is how we know they're the same physical station, even though the two lines define their station sequences independently. Naming things is the first step toward connecting them.

Terminus Markers

One last detail. The first and last stations on a line — the termini — are visually distinct on most transit maps. They're typically larger, filled with the line color, or drawn as a different shape. This signals "this is where the line begins or ends" without needing a legend.

The simplest approach: make terminus stations slightly larger and fill them with the line color instead of leaving them hollow.

Live Editor — Terminus stations stand out

Now Harbour and Park North visually declare themselves as endpoints. The filled circle with a white inner dot is a common convention — the London Underground, Tokyo Metro, and dozens of other systems use variations of it. The terminus labels are also slightly brighter and bolder than intermediate stations.

The line name badge at the bottom center is a small touch. On a single-line diagram it's redundant, but when we have four lines crossing the same map it becomes essential.

What We've Learned

This chapter gave our line character. Not through decoration, but through data-driven decisions: station spacing creates rhythm, alternating labels prevent collision, perpendicular positioning adapts to any track angle, and terminus markers signal endpoints.

We also formalized the separation between data and rendering — a renderLine() function that takes a data object and returns SVG. This pattern scales: in Chapter 4, we'll call it for multiple lines. In Chapter 7, we'll feed it data parsed from a real transit feed.

But there's a glaring problem with our line. Look at Editor 4 — when the track changes direction at "Central", the segments meet in a hard angle. It looks like a broken stick, not a smooth transit line. In the next chapter, we fix this with bezier curves.

Drawing Transit — An open guide to programmatic transit maps