Give the aerodromes a colour of their own, and say what each aircraft is

Four things about the animated pictures, and the window kept in step with
them.

The aerodromes were amber, and so is an aeroplane at twelve thousand feet.
Sixteen units of CIELAB apart is not two colours, it is one: an aircraft low
over a field was drawn in the field's own colour and neither could be picked
out from the other.  They are magenta now, fifty-six units from the nearest
altitude colour, which is what the ramp leaves free once red, amber, green,
cyan and violet have gone on height -- and what an aeronautical chart marks
an aerodrome in anyway.  The test states that as the distance rather than as
the colour, so that changing the ramp cannot quietly walk an aircraft back
into the airports.

The height beside an aircraft was the flight level, which is shorter and is
what an aviator reads, but "376" is only a height to somebody who already
knows it is one.  It is feet with the unit on it now, rounded to the
twenty-five feet Mode S reports altitude in: a real reading is a multiple of
that and comes through untouched, while a moment interpolated between two
reports stops claiming to know the height to the foot.

The flag of the country of registration now comes off the address block
where no register answered.  Taking it from the register's answer alone left
the flag off exactly the aircraft that had nothing else beside them either.
Mexico was missing from the address table while we were in there, which a
receiver in the American southwest notices; two registers independently give
XA- registrations for that block.

And what sort of aircraft it is, which is two facts and not one.  What it is
comes off the air: every identification message carries three bits under its
type code saying whether it is light, large, heavy, a rotorcraft, a glider,
a drone or a van on the apron, and that is the only word about what an
aircraft *is* that needs no register.  They were being decoded and thrown
away.  They are inside the identification frame the log already writes down
in full, so every log this program has ever written has them, including the
ones written before anything here knew to look.

Whether it is military comes off no air at all -- a tanker calls itself
heavy exactly as an airliner does -- and is read from the address block
instead.  On one evening here AE07D3 broadcast "heavy" and sat in the United
States military block; the register, asked separately, came back with a
C-17A Globemaster III, tail 90-0534, United States Air Force.

Labels in an animation now behave as the boxes in the window do.  One keeps
its place for as long as that place still works and is moved only when
something takes it, which on a real log is about half as many moves as
deciding afresh every frame; the moves that are left are eased over half a
second of playback; and what the next label is laid out against is where a
moving one is going rather than where it has reached.  A still has no frame
before it and places its labels exactly as it always did.

The fading was only half done.  A label's name faded, because it is drawn in
the aircraft's own colour, but its rows and its flag were fixed colours and
stayed at full brightness -- so the brightest thing on that part of the
picture was the one aeroplane nothing had been heard from.  An indexed
picture cannot blend, so the row grey and all twelve flag colours now have
dimmed copies at each of the four fade steps, and the whole box goes
together.  A crowded frame, which drops back to the short label, drops the
class and the flag with it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
The Dust Council 2026-09-04 22:45:41 -07:00
parent 8eb3bdbb86
commit f9b21f7e35
13 changed files with 1616 additions and 67 deletions

121
README.md
View file

@ -1013,6 +1013,35 @@ would otherwise make one box wider than the map under it. A route breaks at
the arrow first, so the two ends of the flight stay whole and sit under one
another where they read as a pair.
**A box that has to move swings there rather than jumping.** Two things make
one move: an aircraft flies into the space its neighbour's box was using, or
a new one arrives and claims it. Recomputing the layout every frame and
drawing the answer means boxes teleport, and the eye reads a thing that
teleports as a different thing — on a busy screen several do it at once.
So a box keeps the spot it has for as long as that spot still works, and is
only moved when something genuinely takes it. On a real evening's log that is
about a third as many moves as placing each box afresh every frame. The moves
that are left are eased over about half a second, and the picture redraws at
thirty frames a second for as long as anything is actually moving, dropping
back to its usual five the moment everything has settled.
The spot a box is *heading for* is what the next box is laid out against, not
the place it has got to so far — laying out against a box in mid-swing would
move its neighbours too, and move them back when it arrived, and the screen
would never settle. A box on the move is drawn last, over the ones standing
still, so it stays readable while it crosses them. The box is remembered as an
offset from its aircraft, so one crossing the window carries its box along
without that counting as a move at all.
Thirty frames a second is affordable because **the ground is dimmed once and
kept**. Cutting the view out of the fetched map, dimming it and looking every
level up in the palette is about 70 ms over two megapixels, and none of it
changes between one frame and the next unless the view, the window, the
brightness or the map itself has. Doing it every frame put a ceiling of a
dozen frames a second on the window at 1920×1080 and spent a whole core
holding it there; keeping it takes the same window from 87 ms a frame to 14.
`d` cycles the detail — full box, just height and speed, or symbols alone —
for when the sky is busy. `t` toggles trails, `g` the map underneath, `[`/`]`
its brightness, `+`/`-` the range, `q` closes it.
@ -1022,7 +1051,7 @@ losing their box as they go — a box at a tenth of its colour is something in
the way of the aircraft still flying. One that has gone quiet stops being
counted as overhead, since saying it is would be saying more than was heard.
The map holds still. It is fetched a third larger than the window in every
The map holds still. It is fetched an eighth larger than the window in every
direction, and the middle of the view settles once and then stays put rather
than being recomputed as aircraft come and go — otherwise the view shifts by a
fraction of a mile every few seconds, throws away the tiles fetched for the
@ -1225,18 +1254,34 @@ Time runs at `--speed` seconds of flying per second of animation, or give
high cold, with the key along the bottom; the trail behind each aircraft is the
path it actually flew, in the colours of the heights it flew them at.
Beside each aircraft goes what is known about it — flight level and speed,
type and registration, and the two ends of the route, each with **a small flag
of the country the airport is in**:
Beside each aircraft goes what is known about it — height and speed, what sort
of aircraft it is, type and registration, and the two ends of the route, each
with **a small flag of the country the airport is in**:
```
PRIME04
36,000 ft 493MPH
[US] MILITARY HEAVY
C17 90-0534
```
```
BAW49
330 552MPH
33,000 ft 552MPH
[GB] HEAVY
B744 G-VROS
[GB] EGLL
[US] KSEA
```
The height is in feet with the unit on it. It used to be the flight level —
`330`, hundreds of feet, the way it is said on the radio — which is shorter
and is what an aviator reads, but three digits beside an aircraft are only a
height to somebody who already knows they are one. It is rounded to the
nearest 25 ft, the step Mode S reports altitude in: a real reading is a
multiple of that and comes through untouched, while a moment between two
reports — which is most of the moments in an animation, since they are
interpolated — stops claiming to know the aircraft's height to the foot.
The flags are twelve pixels by eight, drawn from a table in `flags.py` rather
than fetched: at that size a flag is not a rendering of the real thing but the
arrangement that makes one recognisable — the bands and where they run, the
@ -1251,6 +1296,34 @@ The aircraft's own **country of registration** gets a flag too, beside the
type and registration — from the register where one answered, and otherwise
from the 24-bit address, which says by treaty who issued it.
### What sort of aircraft it is
`MILITARY HEAVY` above is two facts, joined only because both are known.
**What it is** comes off the air. Every identification message carries three
bits under its type code saying what sort of thing is transmitting — light,
small, large, high vortex, heavy, high performance, rotorcraft, and under a
different type code glider, airship, parachutist, ultralight, drone,
spacecraft, or a vehicle on the ground. It is the only word about what an
aircraft *is* that needs no register at all. Which list the three bits index
depends on the type code, so the same value means "heavy" in one message and
"parachutist" in another. Zero means the aircraft declined to say, which is
common and is answered with nothing rather than a guess.
**Whether it is military** comes off no air at all: no aircraft broadcasts it,
and a tanker calls itself `heavy` exactly as an airliner does. It is read from
the 24-bit address instead — states set aside blocks of their national range
for their armed forces, and those blocks are published. Two honest limits: a
state can fly a military aircraft on a civil address whenever it likes, so
this finds nobody who does not want to be found; and the table here holds the
allocations a receiver in the ordinary world actually hears rather than every
one that exists.
Worth seeing the two agree. On one evening here, address `AE07D3` was in the
United States military block and broadcast the category `heavy`; the register,
asked separately and knowing nothing of either, came back with a C-17A
Globemaster III, tail 90-0534, operated by the United States Air Force.
**Every aerodrome under the picture is marked**, not only the ones being flown
between: a receiver hears aircraft over its own county, and the county's
airports are what say where on the map you are looking. They come from the
@ -1258,6 +1331,44 @@ same OpenStreetMap data the tiles are drawn from, asked as a question rather
than a picture, once per area and kept for a month — a runway does not move.
`--no-airports` turns it off.
They are drawn **magenta**, which nothing else on the picture is. The old
amber sat 16 units of CIELAB from the altitude ramp's 12,000-foot yellow,
which is to say it was the same colour: an aeroplane low over a field was
drawn in the field's own colour and neither could be picked out from the
other. The ramp already spends red, amber, green, cyan and violet on height;
magenta is what it leaves free, it is 56 units away, and it is what an
aeronautical chart marks an aerodrome in anyway. There is a test that states
this as the property — how far the airport colour is from the nearest
altitude colour — rather than as the colour, so that changing the ramp cannot
quietly walk an aircraft back into the airports.
### Labels that stay where they are
The same two rules as the window, so the two look like the same program.
**A label keeps its place** for as long as that place still works, and is
moved only when something genuinely takes it. Deciding afresh every frame
means a label hops from one side of its aircraft to the other and back
because the aeroplane two along moved a pixel — on a real evening's log that
is about twice as many moves as keeping it. The place is remembered as an
offset from the aircraft, so one crossing the picture carries its label along
and only a real clash asks for a new spot.
**The moves that are left are eased** over about half a second of playback,
not jumped. What the next label is laid out against is where a moving one is
going, not where it has got to, since laying out against a label in mid-swing
would move its neighbours too and move them back when it arrived. A still
picture has no frame before it, so it places its labels exactly as it always
did.
**The whole box fades with the aircraft.** The name always did, because it is
drawn in the aircraft's own colour; the rows and the flag were fixed colours
and stayed at full brightness on a label that was on its way out, which left
the brightest thing on that part of the picture being the one aeroplane
nothing had been heard from. An indexed picture cannot blend, so the row grey
and all twelve flag colours have their own dimmed copies at each of the four
fade steps.
The GIF is written here from first principles — a palette, an LZW stream, frame
differencing with a transparent index — in the same spirit as the PNGs
elsewhere, so nothing but numpy is needed to draw one. Where ffmpeg happens to