Skip to content

feat(coverage): per-pixel clutter model from NLCD land cover#457

Merged
SimmerV merged 15 commits intoMeshAddicts:developfrom
SimmerV:feature-add
May 7, 2026
Merged

feat(coverage): per-pixel clutter model from NLCD land cover#457
SimmerV merged 15 commits intoMeshAddicts:developfrom
SimmerV:feature-add

Conversation

@SimmerV
Copy link
Copy Markdown
Collaborator

@SimmerV SimmerV commented May 6, 2026

Summary

  • Replaces the legacy 4-preset Environment dropdown (0/3/6/12 dB flat clutter) with a calibrated per-pixel model: ITU-R P.452-17 endpoint clutter at TX/RX + ITU-R P.833-9 path-traversed vegetation, driven by USGS NLCD land cover (16 CONUS classes).
  • Operator setup is one command: docker compose --profile bake run --rm landcover-bake auto-downloads NLCD 2024 from MRLC and bakes the tile pyramid. Skip the bake and coverage falls back to a "Mixed Forest" default everywhere, with a clear amber status chip telling the operator how to enable.
  • New UI in Coverage + Scan settings: on/off toggle, 3-stop aggression slider (Conservative 0.7× / Calibrated 1.0× / Aggressive 1.3×), status chip, collapsible 16-class legend with per-class dB hints. State persists per-tool to localStorage.

Architecture

Frontend math — new clutterClasses.ts (NLCD class table + ITU formulas, citations on every row) and clutterPath.ts (per-pixel orchestration: P.452 endpoints + P.833 path integration with asymmetric d_k endpoint exclusion and canonical-id scratch buffer reused across pixels).

Frontend wiringlandcoverTiles.ts (LRU-cached slippy fetcher, buildClutterRaster with nearest-neighbor categorical resampling, downsampler for drag preview). Worker plumbing extended with a clutter buffer alongside the existing DEM. Map.tsx builds DEM + clutter in parallel, threads through to the worker pool, captures tilesPresent / tilesTotal telemetry for the status chip.

Backend — new /tiles/landcover static mount in api/api.py with year-long immutable cache. New scripts/landcover_tiles.py one-shot bake: auto-download with HTTP Range resume, zip extraction, multi-process tile generation (~16 min CONUS on 32 threads). New Dockerfile.landcover + landcover-bake compose service under profiles: ["bake"] so the bake doesn't run as part of normal docker compose up.

Docs — new top-level RF-MODEL.md (public-facing model explainer), scripts/README-landcover.md rewritten with the one-command flow as the headline, top-level README.md updated.

Side improvements

  • Map attribution control collapsed by default.

@SimmerV SimmerV self-assigned this May 6, 2026
@SimmerV SimmerV added the enhancement New feature or request label May 6, 2026
@SimmerV SimmerV added this to meshinfo May 6, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in meshinfo May 6, 2026
@SimmerV SimmerV moved this from Backlog to In review in meshinfo May 7, 2026
@daviesgeek daviesgeek requested a review from Copilot May 7, 2026 16:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades the Coverage + Scan propagation model from a legacy flat “environment clutter” offset to a per-pixel clutter-loss model driven by USGS NLCD land-cover tiles, and adds the operator tooling + docs needed to bake/serve those tiles.

Changes:

  • Add an NLCD tile bake pipeline (Python script + dedicated Docker bake image/profile) and mount baked tiles from the API at /tiles/landcover.
  • Implement frontend landcover tile fetching/caching and integrate ITU-R P.452/P.833 clutter loss into both coverage raster rendering and scan analysis, with new UI controls + persisted state.
  • Add/refresh operator documentation and adjust attribution UI behavior.

Reviewed changes

Copilot reviewed 30 out of 31 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
scripts/requirements-landcover.txt Adds bake-script Python dependencies (not installed in prod image).
scripts/README-landcover.md Operator runbook for baking and serving NLCD tiles.
scripts/landcover_tiles.py New multiprocess NLCD→slippy PNG tile baker with download+resume.
RF-MODEL.md New public-facing RF model explainer (ITM + ITU clutter + NLCD).
README.md Documents the new RF model + one-command bake flow.
frontend/src/pages/NodeMap.tsx Collapses MapLibre attribution control by default via MutationObserver.
frontend/src/pages/map/storage.ts Adds localStorage keys for clutter enable + aggression per tool.
frontend/src/pages/map/scanAnalysis.ts Replaces flat clutter offset with per-path clutter loss from NLCD raster.
frontend/src/pages/map/MapScanPanel.tsx Replaces “Environment” preset UI with clutter toggle + aggression + status + legend.
frontend/src/pages/map/MapLosPanel.tsx Import ordering tweak.
frontend/src/pages/map/MapDetailsPanel.tsx Import list updated (minor formatting).
frontend/src/pages/map/MapCoveragePanel.tsx Replaces “Environment” preset UI with clutter toggle + aggression + status + legend.
frontend/src/pages/map/landcoverTiles.ts New NLCD tile fetcher + LRU cache + raster builder + sampling utilities.
frontend/src/pages/map/landcoverTiles.test.ts Unit tests for zoom selection, sampling, and missing-tile behavior.
frontend/src/pages/map/coverageSliceWorker.ts Threads an optional clutter buffer through the coverage worker.
frontend/src/pages/map/coverageRaster.ts Integrates per-pixel clutter loss into raster rendering parameters/loop.
frontend/src/pages/map/coverageAnalysis.ts Replaces ENVIRONMENTS with AGGRESSION_STOPS + defaults/heuristics.
frontend/src/pages/map/ClutterUI.tsx Shared clutter UI components (slider, status chip, class legend).
frontend/src/pages/map/clutterPath.ts Implements endpoint + path-integrated clutter loss computation.
frontend/src/pages/map/clutterPath.test.ts Unit tests for clutter-path math and scratch-buffer behavior.
frontend/src/pages/map/clutterClasses.ts Defines NLCD class parameter table + ITU math helpers.
frontend/src/pages/map/clutterClasses.test.ts Unit tests for ITU math + table integrity.
frontend/src/pages/Map.tsx Wires clutter raster build into coverage+scan, adds UI state + telemetry plumbing.
frontend/src/maps/mapStyle.ts Removes Tilezen DEM attribution string from the style source spec.
Dockerfile.landcover New one-shot bake image to keep prod image lean.
docker-compose.yml Adds landcover-bake service behind a bake profile.
docker-compose-dev.yml Adds landcover-bake service behind a bake profile (dev compose).
config.toml.sample Adds [landcover] configuration stanza and operator guidance comments.
config.py Adds default landcover config fields to DEFAULT_CONFIG.
api/api.py Mounts baked landcover tiles and sets long-lived cache headers.
.gitignore Ignores docs/ directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/landcover_tiles.py Outdated
Comment thread scripts/landcover_tiles.py Outdated
Comment thread frontend/src/pages/map/clutterPath.ts
Comment thread config.toml.sample Outdated
Comment thread config.toml.sample Outdated
Comment thread config.py Outdated
Comment thread frontend/src/pages/map/clutterClasses.test.ts Outdated
Comment thread frontend/src/pages/Map.tsx
Comment thread frontend/src/pages/Map.tsx Outdated
Comment thread api/api.py Outdated
@SimmerV SimmerV merged commit 633a8ef into MeshAddicts:develop May 7, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in meshinfo May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants