13 Commits

Author SHA1 Message Date
Schuwi
a2f5c902a3 Add --false-color rendering mode for agentic interpretation
Maps raw cloud cover to six distinct stepped colour bands (clear green
through overcast red) on a dark navy background, with fine gradation
below 30% where conditions matter for astrophotography and two coarse
bands above. Skips OSM base map and alpha blending entirely.

The triangulation now stores raw cover values; scale_cloud_cover() is
applied post-blur only in the default blending mode, keeping its
behaviour identical.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 21:09:47 +01:00
Schuwi
56f779990d Update README to reflect current project state 2026-03-07 23:38:36 +01:00
Schuwi
28b7e90af8 Improve color scheme
- boost base map contrast
- adjust cloud colors to a slightly bluish shade
- start drawing lowest cloud cover percentage above 0 at 30% alpha
2026-03-07 23:19:11 +01:00
Schuwi
c7c08ebead Add --center-lat, --center-lon, --zoom CLI arguments
Allow overriding the map centre and OSM zoom level from the command
line, keeping the existing values as defaults.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 11:10:55 +01:00
Schuwi
71d6588dc3 Derive OSM viewport from zoom level instead of the other way around
Replace the heuristic choose_zoom() back-computation with a fixed
OSM_ZOOM constant (zoom 10). The orthographic projection half-extents
are now derived so that one tile pixel maps exactly to one output pixel,
eliminating bilinear interpolation artefacts on the OSM base layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 11:04:26 +01:00
Schuwi
ff69c1d2db Add OpenStreetMap base layer with Carto tile overlay
- Fetch Carto Voyager no-label base tiles and label-only tiles separately,
  cached under cache/osm_tiles/{z}/ and cache/osm_tiles/labels/{z}/
- Rasterize both into the orthographic projection via exact inverse projection
  (new unproject/pixel_to_geo methods on OrthoProjection)
- Render pipeline: basemap → cloud blend → label overlay (labels above clouds)
- Bilinear interpolation for base tiles; premultiplied-alpha bilinear for label
  tiles to prevent dark-fringe artifacts at text edges
- Dynamic zoom selection (floor-based) from actual geographic bounding box
- Fix horizontal squish: derive HALF_W_DEG from pixel aspect ratio so
  degrees-per-pixel is equal on both axes
- Add --no-basemap flag to skip tile fetching for offline/fast use
- Remove hardcoded city markers/labels when tile label overlay is present

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 10:52:34 +01:00
Schuwi
ac9f9da3c4 Fix green bar at bottom of map caused by off-by-one in map height
map_h was subtracting MARGIN twice but the map_area only has a single
bottom margin, leaving the last 8 rows of the land background unrendered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:57:05 +01:00
Schuwi
764f4f6378 Add animated GIF output with parallelised frame quantization
Render an animated clct_animation.gif alongside the per-step PNGs.
Frames are loaded and colour-quantized in parallel via rayon, then
written sequentially with the gif crate.  Also converts timestamps
to CET/CEST using chrono-tz.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:53:49 +01:00
Schuwi
0c73e04959 Parallelize GRIB2 downloads using a dedicated rayon thread pool
Downloads clat/clon concurrently via rayon::join and all forecast steps
in parallel via par_iter, then renders frames sequentially. A separate
thread pool (up to 16 threads) is used for downloads to avoid blocking
the global pool during CPU-bound rendering.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:27:39 +01:00
Schuwi
ee9b039d56 Improve rendering: barycentric interpolation, Gaussian blur, white-cloud palette
Replace nearest-neighbour BFS flood fill with Delaunay triangulation
(spade) + barycentric interpolation for smooth cloud boundaries.
Add NaN-aware separable Gaussian blur (σ=8 px, rayon-parallelised) to
remove triangulation facets. Switch colour scheme from blue bands to a
continuous green-to-white opacity blend matching the DWD app style.
Pixel interpolation loop is also parallelised with rayon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:19:46 +01:00
Schuwi
4ee33a882d Flood fill to improve performance 2026-03-06 21:41:16 +01:00
Schuwi
a9eed7f378 Fix GRIB2 scale factor decoding (sign-magnitude, not two's complement)
GRIB2 encodes binary (E) and decimal (D) scale factors in sign-and-magnitude
format (MSB = sign bit, lower 15 bits = magnitude), not two's complement.
The previous read_i16 call misinterpreted 0x8009 as -32759 instead of -9,
causing 2^E to underflow to 0.0 in f32 and zeroing all decoded values.

Fix: replace read_i16 with read_grib_scale for E and D in
decode_simple_packing. Add regression tests covering sign-magnitude decoding
and a realistic DWD CLCT packing scenario.
2026-03-06 21:40:39 +01:00
Schuwi
6c9a20bf59 Initial commit 2026-03-03 23:26:05 +01:00