clone

an offline map explorer where each world, from a game map to a city's open data, ships as one .atlas file

the included Earth wears its topography and bathymetry, one level deeper

Dami committed 1171ebc
The pin moves to the July 2004 Blue Marble Next Generation variant with
shaded relief and ocean-floor bathymetry -- the rendering NASA's own maps
lead with, and the one that gives the planet its texture instead of a
flat dark ocean. Same publication family, same single pinned image, new
URL, new digest, new first-capture time.

The capture also cuts one level deeper: local zoom 6, a 16384×8192
picture the 21600-wide source still fills with real detail, encoded at
JPEG quality 85 -- measured against quality 90, the two are visually
indistinguishable tile for tile, and the finished bundle lands at 21 MiB
against 24 at 90, inside the 25 MiB budget with room kept. The world's
ground is unchanged: the raster still fills the top half of the world
square and zoom 6 is simply detail past the world-pixel resolution, the
way every deep pyramid in the corpus is.
commit
1171ebc4feb8eb6f0f545dd7994bc60eca1ecac9
parent
7e3826a506e027eae8f3f0d02cb6d5fb4544ed58
author
Dami <dami.etoile@gmail.com>
kind
feat risk score 2.0 of 3, Jev's estimate
8 files changed, +51 -39
Mdocs/decisions/0019-an-earth-volume-is-included.md2+-
Mdocs/generate.md2+-
Mincluded/README.md36++++++++++++++++++-------------
Dincluded/earth-20260803-eaf23347cf1e.atlasbin
Aincluded/earth-20260803-ec3c1b0b5a9c.atlasbin
Minternal/generate/crawl/bluemarble.go31+++++++++++++++-----------
Minternal/generate/crawl/bluemarble_test.go6+++---
Mmain_test.go13++++++-----
M docs/decisions/0019-an-earth-volume-is-included.md +1 -1
M docs/generate.md +1 -1
M included/README.md +21 -15
@@ -16,12 +16,12 @@ collections, no features, and no runtime network dependency of any kind.
1616 1717 | Fact | Value |1818 |---|---|19-| Product | Blue Marble: Next Generation, July 2004 — NASA Earth Observatory's global, cloud-free, true-color base map |20-| Product page | <https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-map/> |21-| Source image | <https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-base/july/world.200407.3x21600x10800.jpg> |19+| Product | Blue Marble: Next Generation w/ Topography and Bathymetry, July 2004 — NASA Earth Observatory's global, cloud-free, true-color composite with shaded relief and ocean-floor bathymetry |20+| Product page | <https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-topography-bathymetry/> |21+| Source image | <https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-topography-bathymetry/july/world.topo.bathy.200407.3x21600x10800.jpg> |2222 | Source dimensions | 21600 × 10800 |23-| Source SHA-256 | `dea8b4dc8a4f93f5f8bce0c8c85a508a178e7901e9ed8e6bf86e6ce7ef6d61e2` |24-| First captured | `2026-08-03T14:30:39Z` |23+| Source SHA-256 | `d225f1f35a6448a4d1d8f6de6e48f3433e470085b70a35800e64f384f269a7b0` |24+| First captured | `2026-08-03T15:27:26Z` |2525 | Credit | NASA Earth Observatory |2626 2727 NASA imagery is free of copyright. NASA's media guidelines ask that the credit
@@ -32,17 +32,23 @@ runtime-URL prohibition holds for this volume exactly as for any other.
3232 3333 ## Derivation3434 35-The pinned source is downsampled to the 8192 × 4096 reference level — the top36-half of the world square, the shared whole-sphere equirectangular window35+The pinned source is downsampled to the pyramid's deepest level — local zoom36+6, a 16384 × 8192 picture the 21600-wide source still fills with real detail —37+through the deterministic fixed-point Catmull-Rom resampler in38+`internal/generate/crawl/resample.go` (`catmull-rom-fixed15`), cut into39+256-pixel tiles, and encoded as JPEG at quality **85**40+(`internal/generate/crawl/bluemarble.go` is the one place both settings are41+spelled). The world's ground is unchanged by the depth: the raster fills the42+top half of the world square, the shared whole-sphere equirectangular window3743 (`atlas.geometry.equirect.px = 0,0,8192,4096`,38-`atlas.geometry.equirect.deg = -180,90,180,-90`) — through the deterministic39-fixed-point Catmull-Rom resampler in `internal/generate/crawl/resample.go`40-(`catmull-rom-fixed15`), cut into 256-pixel tiles, and encoded as JPEG at41-quality **90** (`internal/generate/crawl/bluemarble.go` is the one place that42-setting is spelled). The ordinary tile lane derives every shallower level,43-coverage, bounds and stamps from that reference level, and the ordinary compose44-lane writes and validates the bundle. The full extent survives uncropped, and45-tiles are stored, not deflated, as format v3 requires.44+`atlas.geometry.equirect.deg = -180,90,180,-90`), and zoom 6 is simply detail45+past the world-pixel resolution, the way every deep pyramid in the corpus is.46+The ordinary tile lane folds the reference level and everything shallower down47+from the cut and derives coverage, bounds and stamps; the ordinary compose lane48+writes and validates the bundle. The full extent survives uncropped, tiles are49+stored, not deflated, as format v3 requires, and the finished file is ~21 MiB —50+inside the 25 MiB budget the included volume keeps so the executable stays51+portable.4652 4753 ## Regeneration4854
D included/earth-20260803-eaf23347cf1e.atlas +0 -0

Binary file.

A included/earth-20260803-ec3c1b0b5a9c.atlas +0 -0

Binary file.

M internal/generate/crawl/bluemarble.go +18 -13
@@ -59,17 +59,19 @@ type blueMarblePin struct {
5959 Quality int6060 }6161 62-// blueMarble is the shipped pin: Blue Marble Next Generation, July 2004, as63-// published by NASA Earth Observatory. included/README.md is the recipe that64-// carries these same facts for a person.62+// blueMarble is the shipped pin: Blue Marble Next Generation with topography63+// and bathymetry, July 2004, as published by NASA Earth Observatory -- the64+// variant whose shaded relief and ocean floor give the planet its texture,65+// which is also the rendering NASA's own maps lead with. included/README.md is66+// the recipe that carries these same facts for a person.6567 var blueMarble = blueMarblePin{66- Page: "https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-map/",67- Asset: "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-base/july/world.200407.3x21600x10800.jpg",68- SHA256: "dea8b4dc8a4f93f5f8bce0c8c85a508a178e7901e9ed8e6bf86e6ce7ef6d61e2",69- CapturedAt: "2026-08-03T14:30:39Z",68+ Page: "https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/base-topography-bathymetry/",69+ Asset: "https://assets.science.nasa.gov/content/dam/science/esd/eo/images/bmng/bmng-topography-bathymetry/july/world.topo.bathy.200407.3x21600x10800.jpg",70+ SHA256: "d225f1f35a6448a4d1d8f6de6e48f3433e470085b70a35800e64f384f269a7b0",71+ CapturedAt: "2026-08-03T15:27:26Z",7072 Width: 21600,7173 Height: 10800,72- Quality: 90,74+ Quality: 85,7375 }7476 7577 // blueMarbleResampler names the cut for the capture body: the resampler beside
@@ -77,9 +79,12 @@ var blueMarble = blueMarblePin{
7779 // is cut renames this, and the renamed policy reads as a new capture.7880 const blueMarbleResampler = "catmull-rom-fixed15"7981 80-// blueMarbleZoom is the reference level the source is cut to: the level whose81-// pixels are the world square's own, holding the whole 8192×4096 picture.82-const blueMarbleZoom = doc.SyntheticZoom82+// blueMarbleZoom is the level the source is cut to: one deeper than the83+// reference level whose pixels are the world square's own, so the pyramid84+// holds a 16384×8192 picture the 21600-wide source still fills with real85+// detail. The deriver folds the reference level and everything shallower down86+// from this cut.87+const blueMarbleZoom = doc.SyntheticZoom + 18388 8489 // blueMarbleIDBit marks Blue Marble identities in the archive register, beside8590 // the bits the other sources' identities carry.
@@ -184,7 +189,7 @@ func verifyBlueMarble(data []byte, pin blueMarblePin) error {
184189 }185190 186191 // writeBlueMarble derives the capture from verified source bytes: the image187-// decoded, held to its declared size, cut to the reference level through the192+// decoded, held to its declared size, cut to the capture level through the188193 // deterministic resampler, tiled, and recorded -- and the capture body written189194 // last, carrying the product's identity and the policy the cut was made under.190195 func writeBlueMarble(store *Archive, worldDir string, worldID int64, pin blueMarblePin, source []byte, log *slog.Logger) error {
@@ -240,7 +245,7 @@ func writeBlueMarble(store *Archive, worldDir string, worldID int64, pin blueMar
240245 body, err := json.MarshalIndent(blueMarbleCapture{241246 Source: nasabluemarble.SourceName,242247 Body: nasabluemarble.Body,243- Product: "Blue Marble: Next Generation, July 2004",248+ Product: "Blue Marble: Next Generation w/ Topography and Bathymetry, July 2004",244249 Credit: "NASA Earth Observatory",245250 AssetSHA256: pin.SHA256,246251 Width: pin.Width,
M internal/generate/crawl/bluemarble_test.go +3 -3
M main_test.go +7 -6
@@ -113,7 +113,7 @@ func TestIncludedEarthIsAValidOrdinaryBundle(t *testing.T) {
113113 if m.Worlds[0].Points != 0 || m.Worlds[0].Paths != 0 || m.Worlds[0].Areas != 0 {114114 t.Errorf("the manifest counts features on a raster-only world: %+v", m.Worlds[0])115115 }116- if m.Version.CreatedAt != "2026-08-03T14:30:39Z" {116+ if m.Version.CreatedAt != "2026-08-03T15:27:26Z" {117117 t.Errorf("createdAt %s is not the pinned capture time", m.Version.CreatedAt)118118 }119119 }
@@ -135,12 +135,12 @@ func TestIncludedEarthDeclaresTheWholeSphere(t *testing.T) {
135135 if lens.Name != "Blue Marble" {136136 t.Errorf("lens %q", lens.Name)137137 }138- if lens.MinZoom != 0 || lens.MaxZoom != 5 || lens.FullZoom != 5 || lens.SourceZoom != 5 {139- t.Errorf("zooms min %d max %d full %d source %d, want 0/5/5/5",138+ if lens.MinZoom != 0 || lens.MaxZoom != 6 || lens.FullZoom != 6 || lens.SourceZoom != 6 {139+ t.Errorf("zooms min %d max %d full %d source %d, want 0/6/6/6",140140 lens.MinZoom, lens.MaxZoom, lens.FullZoom, lens.SourceZoom)141141 }142- if len(lens.Formats) != 6 {143- t.Errorf("%d formats for 6 levels", len(lens.Formats))142+ if len(lens.Formats) != 7 {143+ t.Errorf("%d formats for 7 levels", len(lens.Formats))144144 }145145 for _, format := range lens.Formats {146146 if format != "jpg" {
@@ -190,7 +190,7 @@ func TestIncludedEarthPyramidOpensAtEveryLevel(t *testing.T) {
190190 t.Fatalf("%s is compressed; format v3 stores tiles", name)191191 }192192 }193- wantPerLevel := map[string]int{"0": 1, "1": 2, "2": 8, "3": 32, "4": 128, "5": 512}193+ wantPerLevel := map[string]int{"0": 1, "1": 2, "2": 8, "3": 32, "4": 128, "5": 512, "6": 2048}194194 for level, want := range wantPerLevel {195195 if perLevel[level] != want {196196 t.Errorf("level %s holds %d tiles, want %d", level, perLevel[level], want)
@@ -200,6 +200,7 @@ func TestIncludedEarthPyramidOpensAtEveryLevel(t *testing.T) {
200200 for _, name := range []string{201201 "tiles/earth/0/0/0.jpg", "tiles/earth/1/1/0.jpg", "tiles/earth/2/3/1.jpg",202202 "tiles/earth/3/7/3.jpg", "tiles/earth/4/15/7.jpg", "tiles/earth/5/31/15.jpg",203+ "tiles/earth/6/63/31.jpg",203204 } {204205 data, err := reader.ReadEntry(name)205206 if err != nil {