Wrap seventeen moons and dwarf planets in the missions' own maps, grey where no probe looked

Audit #40. Io, Titan and Pluto had square disc photographs (40.5, 42.6 and
42.9% black sky) that PR #33 unlisted, and every other moon or dwarf planet
fell through to the derived surface. Seventeen of them are now wrapped in
public-domain global mosaics from USGS Astrogeology and the NASA PDS: Phobos
(Viking), Io, Europa, Ganymede, Callisto (Galileo and Voyager), Mimas,
Enceladus, Tethys, Dione, Rhea, Titan, Iapetus, Phoebe (Cassini), Triton
(Voyager 2), Ceres (Dawn), Pluto and Charon (New Horizons). io.jpg, titan.jpg
and pluto.jpg are replaced by maps under the same names.

Every file is simple cylindrical over 360 by 180 degrees, with longitude 0 in
the middle and east to the right, the frame MAP_TO_BODY puts on the IAU body
frame. Processing: the source's no-data pixels (0 in every band) become one
flat grey, the mean of the mapped surface, never invented terrain; area
downsampling to 2048x1024 for bodies over 1 000 km in radius and 1024x512
for the rest; half a turn where the source is centred on 180; JPEG q85
(Europa q82). Largest file 386 KB (Europa); 3.5 MB for all seventeen.

The centre was read from each GeoTIFF's central meridian and left-edge tie
point, not from its label: Rhea's and Enceladus's labels say CENTER_LONGITUDE
= 180 over images centred on 0. Taken from the label, Rhea came out half a
turn round, which the seam it left down the middle of the map gave away.
Each map was then checked by eye against the IAU Gazetteer: Pele and Loki on
Io, Pwyll on Europa, Osiris and Tros on Ganymede, Valhalla and Asgard on
Callisto, Herschel on Mimas, Ali Baba and Aladdin on Enceladus, Odysseus on
Tethys, Creusa on Dione, Inktomi on Rhea, Xanadu, Shangri-La and Belet on
Titan, Cassini Regio on Iapetus, Jason on Phoebe, Occator and Haulani on
Ceres, Stickney on Phobos, Sputnik Planitia and Cthulhu on Pluto, Mordor
Macula on Charon, Leviathan Patera on Triton.

Unmapped share, now grey: Triton 38.6%, Charon 34.0%, Pluto 31.9%, Phoebe
20.4%, the Galilean polar gaps 3.6-4.3%, Ceres's south pole 3.6%, the rest
under 0.2%. Pixels darker than 8 of 255: at most 0.55% (Charon's Mordor
Macula, Pluto's Cthulhu), against the 20-43% black sky of the photographs
PR #33 dropped.

Left out, and said so in src/assets/textures/README.md: Deimos, whose only
cylindrical map (Stooke, Viking) has no label for its longitude direction and
on which neither Voltaire nor Swift could be found to settle it; the five
Uranian moons, whose only maps (Schenk 2020, USRA) carry no licence; Hyperion,
Nereid, Proteus, Eris, Haumea and Makemake, which have no photographic
simple-cylindrical map.

Source URLs, credits, licences, processing and each measurement are in the new
src/assets/textures/README.md; the root README now points there and counts
twenty-seven bodies in real photography. texture-catalog.spec.ts checks that
the seventeen are registered and that Deimos, the Uranian moons, Hyperion and
Eris are not. Unit suite 790 -> 792 tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-24 23:41:28 +02:00
co-authored by Claude Opus 5.5
parent 76fb38665f
commit 302fa963ad
21 changed files with 131 additions and 10 deletions
@@ -0,0 +1,18 @@
import { describe, expect, it } from 'vitest';
import { bodyTexturePath } from './texture-catalog';
describe('bodyTexturePath', () => {
it('wraps the moons and dwarf planets that have a mission mosaic in it', () => {
const mapped = ['phobos', 'io', 'europa', 'ganymede', 'callisto', 'mimas', 'enceladus', 'tethys', 'dione', 'rhea', 'titan', 'iapetus', 'phoebe', 'triton', 'ceres', 'pluto', 'charon'];
for (const id of mapped) {
expect(bodyTexturePath(id)).toBe(`assets/textures/bodies/${id}.jpg`);
}
});
it('leaves the bodies with no map it could check to their derived surface', () => {
for (const id of ['deimos', 'miranda', 'ariel', 'umbriel', 'titania', 'oberon', 'hyperion', 'eris']) {
expect(bodyTexturePath(id)).toBeUndefined();
}
});
});
+28 -6
View File
@@ -10,15 +10,20 @@ import * as THREE from 'three/webgpu';
* `procedural-planet-texture.ts`, which derives a surface from the body's own measured size,
* mass, orbit and host star instead.
*
* Io, Pluto, Titan and Deimos used to be listed with the square photographs of them in
* `assets/textures/bodies/`: pictures of a lit disc against black sky, not maps. Wrapped round a
* sphere they put black sky on a fifth to a third of the surface, in a band up to 57 degrees wide
* across the equator that the spin then swept past the camera. They are left out until a real map
* of each is added.
* Io, Pluto, Titan and Deimos used to be listed with square photographs of them: pictures of a
* lit disc against black sky, not maps, which wrapped round a sphere put black sky on a fifth to a
* third of the surface. Io's, Pluto's and Titan's are now the global mosaics the moons below are
* drawn from; Deimos's photograph is still in the folder, unlisted, for want of a map whose
* longitudes could be checked.
*
* Provenance (CC BY 4.0 Solar System Scope, via Wikimedia Commons — see each file's Commons page
* for the original credit line): mercury/venus/earth/mars/saturn/uranus/neptune/moon/sun/
* saturn-ring/skybox — Solar System Scope texture pack; jupiter — Solar System Scope 8k pack.
*
* The moons', Ceres's and Pluto's are public-domain mission mosaics from USGS Astrogeology and the
* PDS, each put in the same frame — longitude 0 in the middle, east to the right — and each
* measured, in `assets/textures/README.md`. Where a probe saw only part of a body (Pluto, Charon,
* Triton, Phoebe, the Galilean poles), the rest is a flat grey, never invented terrain.
*/
const BODY_TEXTURE_PATHS: Record<string, string> = {
mercury: 'assets/textures/bodies/mercury.jpg',
@@ -29,7 +34,24 @@ const BODY_TEXTURE_PATHS: Record<string, string> = {
saturn: 'assets/textures/bodies/saturn.jpg',
uranus: 'assets/textures/bodies/uranus.jpg',
neptune: 'assets/textures/bodies/neptune.jpg',
moon: 'assets/textures/bodies/moon.jpg'
moon: 'assets/textures/bodies/moon.jpg',
phobos: 'assets/textures/bodies/phobos.jpg',
io: 'assets/textures/bodies/io.jpg',
europa: 'assets/textures/bodies/europa.jpg',
ganymede: 'assets/textures/bodies/ganymede.jpg',
callisto: 'assets/textures/bodies/callisto.jpg',
mimas: 'assets/textures/bodies/mimas.jpg',
enceladus: 'assets/textures/bodies/enceladus.jpg',
tethys: 'assets/textures/bodies/tethys.jpg',
dione: 'assets/textures/bodies/dione.jpg',
rhea: 'assets/textures/bodies/rhea.jpg',
titan: 'assets/textures/bodies/titan.jpg',
iapetus: 'assets/textures/bodies/iapetus.jpg',
phoebe: 'assets/textures/bodies/phoebe.jpg',
triton: 'assets/textures/bodies/triton.jpg',
ceres: 'assets/textures/bodies/ceres.jpg',
pluto: 'assets/textures/bodies/pluto.jpg',
charon: 'assets/textures/bodies/charon.jpg'
};
/** The Sun isn't a `BodyRecord` (it's the system's star marker), so it's looked up separately. */