diff --git a/README.md b/README.md index c3a1a15..fee577d 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ mountains and trenches are all in the same places; or drop into a cross-section a subduction zone, a spreading ridge or a transform fault, where the descending slab is fitted to the earthquakes that trace it. -## What is on screen +## Features **Global map** @@ -35,7 +35,7 @@ The science, the sources and the model's limits are documented in [`doc/model.md`](doc/model.md); the code is documented in [`doc/implementation-notes.md`](doc/implementation-notes.md). -## Quick start +## Quick Start ```bash npm install @@ -60,17 +60,7 @@ npm start # dev server → http://localhost:5173 `npm run build-data` writes `src/common/data/generated/`, which is committed — normal builds never touch the network. Downloads are cached under `.cache/data/`. -## Data sources - -| Dataset | Source | Licence | -|---|---|---| -| Plate outlines, boundaries, Euler poles | Bird (2003), PB2002, doi:10.1029/2001GC000252, via [fraxen/tectonicplates](https://github.com/fraxen/tectonicplates) | ODC-BY 1.0 | -| Coastlines | [Natural Earth](https://www.naturalearthdata.com/) 1:110 m land | Public domain | -| Earthquakes | [USGS ANSS ComCat](https://earthquake.usgs.gov/fdsnws/event/1/) | Public domain | -| Volcanoes | [NOAA NCEI](https://www.ngdc.noaa.gov/hazel/) / Smithsonian GVP Holocene volcano list | Public domain | -| Elevation and bathymetry | [NOAA NCEI global DEM mosaic](https://gis.ngdc.noaa.gov/arcgis/rest/services/DEM_mosaics/DEM_global_mosaic/ImageServer) | Public domain | - -## Tech stack +## Tech Stack | Tool | Version | Purpose | |---|---|---| @@ -83,6 +73,16 @@ builds never touch the network. Downloads are cached under `.cache/data/`. Localized in English, Spanish and French; ships default and projector colour profiles and full Interactive Description support. +### Data sources + +| Dataset | Source | Licence | +|---|---|---| +| Plate outlines, boundaries, Euler poles | Bird (2003), PB2002, doi:10.1029/2001GC000252, via [fraxen/tectonicplates](https://github.com/fraxen/tectonicplates) | ODC-BY 1.0 | +| Coastlines | [Natural Earth](https://www.naturalearthdata.com/) 1:110 m land | Public domain | +| Earthquakes | [USGS ANSS ComCat](https://earthquake.usgs.gov/fdsnws/event/1/) | Public domain | +| Volcanoes | [NOAA NCEI](https://www.ngdc.noaa.gov/hazel/) / Smithsonian GVP Holocene volcano list | Public domain | +| Elevation and bathymetry | [NOAA NCEI global DEM mosaic](https://gis.ngdc.noaa.gov/arcgis/rest/services/DEM_mosaics/DEM_global_mosaic/ImageServer) | Public domain | + ## License GNU Affero General Public License v3.0 — see [OpenPhysics org license](https://github.com/OpenPhysics/.github/blob/main/LICENSE). diff --git a/assets/screenshot.png b/assets/screenshot.png new file mode 100644 index 0000000..bc4cd17 Binary files /dev/null and b/assets/screenshot.png differ diff --git a/src/PlateTectonicsColors.ts b/src/PlateTectonicsColors.ts index f5ad35f..e11ac3b 100644 --- a/src/PlateTectonicsColors.ts +++ b/src/PlateTectonicsColors.ts @@ -81,6 +81,39 @@ const PlateTectonicsColors = { projector: "#8a8578", }), + /** + * Stops of the elevation ramp shown in the topography swatch, sampled from the + * shaded relief raster: abyssal plain → shelf → lowland → upland → ice and peak. + * + * These are the one group whose `projector` values match their `default` ones. + * The raster is a fixed build-time image that Projector Mode cannot repaint, so + * a swatch that claims to be a slice of it has to stay the same colour too — + * they are ProfileColorProperties so the ramp is declared here with every other + * color rather than inlined at the point of use. + */ + reliefRampColorProperties: [ + new ProfileColorProperty(PlateTectonicsNamespace, "reliefDeepOcean", { + default: "#0d2a5c", + projector: "#0d2a5c", + }), + new ProfileColorProperty(PlateTectonicsNamespace, "reliefShelf", { + default: "#3c7fbe", + projector: "#3c7fbe", + }), + new ProfileColorProperty(PlateTectonicsNamespace, "reliefLowland", { + default: "#5a8256", + projector: "#5a8256", + }), + new ProfileColorProperty(PlateTectonicsNamespace, "reliefUpland", { + default: "#b08a5c", + projector: "#b08a5c", + }), + new ProfileColorProperty(PlateTectonicsNamespace, "reliefPeak", { + default: "#efefef", + projector: "#efefef", + }), + ], + /** * Wash colors used to tell neighbouring plates apart. Plate *i* uses entry * *i* mod `platePaletteColorProperties.length`; the palette is longer than the diff --git a/src/plate-tectonics/view/LegendSwatches.ts b/src/plate-tectonics/view/LegendSwatches.ts index 495ec62..5e67edd 100644 --- a/src/plate-tectonics/view/LegendSwatches.ts +++ b/src/plate-tectonics/view/LegendSwatches.ts @@ -36,6 +36,12 @@ const SWATCH_HEIGHT = 12; /** Opacity of the plate-palette blocks in the "tectonic plates" swatch. */ const PLATE_SWATCH_OPACITY = 0.75; +/** + * Where each {@link PlateTectonicsColors.reliefRampColorProperties} stop sits along + * the topography swatch; one ratio per color, in the same order. + */ +const RELIEF_RAMP_STOPS = [0, 0.45, 0.6, 0.85, 1]; + /** Builds the icon for one symbol, centred on its own origin-free bounds. */ export function createLegendSwatch(kind: SwatchKind): Node { switch (kind) { @@ -105,14 +111,14 @@ export function createLegendSwatch(kind: SwatchKind): Node { return hotspotDiamond(0); case "topography": - // A slice of the relief ramp: deep ocean through shelf to high ground. + // A slice of the relief ramp: deep ocean through shelf to high ground. The + // stops are bunched past the middle because most of the Earth's surface is + // below sea level, so an evenly spaced ramp would read as almost all ocean. return new Rectangle(0, 0, SWATCH_WIDTH, SWATCH_HEIGHT, { - fill: new LinearGradient(0, 0, SWATCH_WIDTH, 0) - .addColorStop(0, "#0d2a5c") - .addColorStop(0.45, "#3c7fbe") - .addColorStop(0.6, "#5a8256") - .addColorStop(0.85, "#b08a5c") - .addColorStop(1, "#efefef"), + fill: PlateTectonicsColors.reliefRampColorProperties.reduce( + (gradient, color, index) => gradient.addColorStop(RELIEF_RAMP_STOPS[index] as number, color), + new LinearGradient(0, 0, SWATCH_WIDTH, 0), + ), cornerRadius: 2, });