Draw a roller-coaster loop from memory and you will draw a circle. Everyone does. It is also the single worst shape in its own family, and the reason is a whole number you cannot argue with.
A loop is not a radius
The useful move is to stop describing a loop by its size and start describing
it by its curvature — how hard it is turning, as a function of how far round
it has got. Turn through θ ∈ [0, 2π] with curvature κ(θ) and the track
follows itself:
dx = cos θ · ds dy = sin θ · ds ds = dθ / κ(θ)
That looks like it should make closing the loop hard. It doesn’t, and the
accident is a good one: the loop returns to rail height for any κ
symmetric about θ = π, because sin θ is antisymmetric there and the two
halves of ∫ sin θ ds cancel exactly. Closure is free. So the whole family
below is buildable, every member is as tall as every other, and the only real
choice left is where you spend the curvature:
κ(θ) = κ_b · [ 1 + (p − 1)·(1 − cos θ)/2 ] p = κ_crest / κ_floor
p = 1 is the circle. p > 1 is flat at the bottom and pinched at the top,
which is what every vertical loop built since the 1970s actually looks like.
The demo solves κ_b rather than letting you pick it, so a change of shape is
never quietly also a change of height: every loop on screen is 20 m tall.
Six
What a rider reads off the seat is the normal force, and only the normal equation matters — the pull of gravity along the track and the tension in the train are both tangential, so neither one ever enters it:
N/m = v²κ + g·cos θ
At the floor cos θ = 1 and gravity adds to the seat force. At the crest
cos θ = −1 and it subtracts, and N reaches zero when v²κ = g. That is
the whole of “falling out of the loop”.
Now put a circle in it. Energy gives v_b² = v_t² + 4gr, so
n_b = v_b²/(gr) + 1
n_t = v_t²/(gr) − 1
n_b − n_t = 4 + 1 + 1 = 6
The speeds cancel. The radius cancels. A circular loop always charges its rider exactly 6 g more at the floor than it gives at the crest — at any size, at any speed, for every circular loop ever built. The demo checks it across 24 of them, six sizes by four entry speeds, and gets 6 to 9 parts in 10¹⁵. It is an identity, not a tendency.
Enter one as slowly as it will let you — the speed that just barely keeps the
train on the rail, n_t = 0 — and the whole 6 lands on the floor. A 4 m loop
and a 40 m loop both hand over 6.000000000000 g. The big one is 3.16×
faster and needs a 100 m hill instead of a 10 m one. Every quantity you have
changes, except the one that hurts.
The fix runs the wrong way
The instinct is to make the loop gentler — bigger, rounder, less abrupt. That
does nothing, and the demo’s circle button is there so you can watch it do
nothing. What works is the opposite: pinch the crest.
Take the same 20 m loop and make the curvature at the top four times the curvature at the bottom, and it charges 3.10 g instead of 6.00 — a 48% cut for nothing but shape. Two things fall at once, and they both fall for the same reason:
- a sharper crest needs less speed to hold the train on (
v² = g/κ), so the whole ride is entered slower; - and because the height is fixed, a sharper crest is paid for with a flatter
floor —
κ_bdrops from 1/10 m to 1/21.6 m — which is exactly the term the floor’sv²κis built from.
It is worth being clear that this is not “the tight loop is slower”. Entry goes 22.14 → 21.10 m/s, 4.7%. The train arrives at the bottom at very nearly the speed it always did. The bottom is just no longer bent hard enough to charge it 6 g for the privilege. And it falls monotonically across the family: there is no point-mass loop anywhere where a blunter crest is kinder.
What it costs is land
The bill does arrive, just not in the units you were watching. A circle closes
on itself — ∫ cos θ ds = 0, so it lands precisely where it started, the only
member of the family that does. Pinch it and the loop walks: at p = 4 the
exit is 22.7 m downstream of the entry, and the rail grows from 62.8 m to
74.8 m of steel. That is the trade. Shape is free in newtons and expensive in
real estate, which is a fair description of most of civil engineering.
The train has a length
Everything above is about a point mass, which is the object the textbook answer is about and not the object anybody rides. A train is a rigid chain on the rail: every car shares one speed, and the energy that sets that speed is the mean car height, not the lead car’s. That single substitution is the entire train effect.
On a circle it changes nothing at all. Hang a 24 m train off the same loop and the floor still reads 6.000000 g — 8 parts in 10¹⁴ of drift. Uniform curvature has nowhere to put the extra speed a train brings over the top.
On a pinched loop it changes a great deal. At p = 6 the same loop goes from
2.72 g as a point mass to 4.50 g with a 24 m train, handing back 54% of
everything the shape had won. The mechanism is the mirror of the one that made
the shape work: a long train crests faster than a point mass does, because
most of it is still below the crest — and a pinched loop has concentrated all
its curvature exactly there.
It lands on the ends, not the back
The obvious guess is that the back row gets it. It doesn’t — or rather, it
does, and so does the front row, to within 10⁻¹⁴. Eight rows over 24 m of
train, on a p = 6 loop:
4.50 3.74 3.13 2.71 2.71 3.13 3.74 4.50 g
└──────────────── 1.66× apart, on one ride ──────────────┘
Your g is your own curvature multiplied by a speed the whole train sets.
The middle car is always closest to the train’s own centre of mass, so it
always rides at the honest speed for where it is. The cars at the ends are the
ones permanently out of step with the average — one of them fast because
everyone else is below it, the other fast because everyone else is below it —
and the loop charges for being out of step. The front row takes its 4.50 g at
122° and the back row takes exactly the same at 238°, mirrored about
the crest.
Neither of which is the floor, and neither is the crest. The worst moment of a pinched loop is out on the shoulder, a third of the way up, where nothing is supposed to be happening and nobody is looking. The circle, for all its 6 g, is nearly seat-blind: 6.00 to 5.81 across the same eight rows, a 3% spread against the pinched loop’s 66%. The shape that lowered the average raised the variance. That is usually the trade, and it is usually invisible.
So the shape is a readout of the train
Which means the design question has no answer at all until you say how long
the train is. A point mass wants p ≥ 12 — as sharp a crest as the budget
will buy, with no interior optimum anywhere. Give it a real train and an
optimum appears, and it slides:
18 m train → p = 11.5
24 m train → p = 8.0
30 m train → p = 5.0 crest radius 5.0 m
Longer train, blunter crest. Press T in the demo and watch the red curve in
the family view lift off the grey one and grow a minimum.
One honest caveat on all of that, which the demo will also show you: most of the damage a train does is not the shape’s fault. Size the entry speed for the train you actually have rather than for a point mass — 18.7 m/s instead of 20.9 — and the worst seat drops from 4.50 g to 3.12. Most of what looks like a shape problem is 2.2 m/s of entry speed. But the fan does not close: even correctly sized, the ends still take 1.39× what the middle of the train does. That part belongs to the shape, and no entry speed will buy it back.
Driving it
Three views, 1 2 3. The ride paints the load the rail carries as a
ribbon standing off the track — its width is the g any car reported passing
that point — with a dashed ghost of the circle it would have been, so the eye
can subtract one from the other. family is peak g across every shape, with
the circle’s 6.00 as a line nothing in the family can be talked out of.
seats is the fan: what each car felt, against where in the turn it was.
← → shape it. ↑ ↓ set the entry speed by hand; A puts it back to the
slowest legal one. T cycles the train length, F the floor you insist on at
the crest (0 g is weightless; 1 g is the comfortable design), and D switches
whether the entry is sized for the train you have or for the textbook point
mass — which is the one mistake in the whole piece that costs real g.
What the model does not do
- No friction, no drag. Energy is conserved exactly, so every number here
is the optimistic one. A real train loses a few percent a circuit and needs
a taller lift than the demo’s
hillreadout claims. - Curvature jumps from 0 to
κ_bat the loop entry. Real inversions ramp it in over a transition — that ramp is what “clothoid” actually names, and this one-parameter family is a cruder thing that only borrows the idea. The jump is a jerk problem, not a peak-g one: none of the numbers above move, but the entry would feel like a kick. - The train is a rigid chain of point masses on the rail — no suspension, no car height, no banking, and a seat that is exactly where the wheels are.
- “Loses the rail” here means
N < 0. A real coaster has upstop wheels, so negative g is a comfort failure — you hang in the restraint — rather than a derailment. It is also why the demo calls a too-slow entry a stall and stops: the train never reaches the crest and would roll back.
For context rather than as a claim the code checks: the loop-the-loop rides of the 1900s were built as circles and had a reputation for hurting necks. The vertical loop came back in the 1970s and came back pinched. This family is the smallest thing that shows why.
Reusing it
src/inversion.mjs is framework-free and has no DOM in it. Metres, m/s, and g.
import { buildLoop, minEntrySpeed, run, evaluate, familySweep } from './inversion.mjs';
const track = buildLoop({ tightness: 4, height: 20 }); // κ_b is solved, not chosen
const entry = minEntrySpeed(track, { floorG: 1 }); // closed form, no search
const ride = run(track, { v0: entry.v, cars: 8, trainLength: 24 });
ride.peakG; // the worst any car felt
ride.trace[i].g; // per-car g at step i
familySweep({ trainLength: 24 }); // peak g across every shape, same height
buildLoop returns the sampled track (s, x, y, theta, kappa) plus
at(s) for interpolation, so anything that wants to put a vehicle on a plane
curve and ask what the vehicle feels can use it without caring that it was
written about roller coasters.
node scripts/screenshot-demo.mjs boots the demo in a real Chromium, drives it
through its own hooks, and asserts all 30 of the claims above against the
running code before it writes a single screenshot.



