mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
fix(fires): paint aggregated heat cells warm by density, not by strongest FRP
Coloring each far-zoom cell with the ramp stop of its strongest detection turned a burning region into a blue / teal / lime mosaic: neighbouring cells flipped hue on one outlier and the cold stops did not read as fire. Cells say where it burns, so they go back to the heat-normalized score (density, night share, max FRP) on the warm end of the ramp — lime, amber, red — with the cell card accent matching. Single detections keep the full six-stop FRP ramp. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
1 parent
1dad6b658a
commit
887b261195
4 files changed
+39
-15
No files matched your search
@@ -2,7 +2,8 @@
|
|||||||
cold → hot ramp (blue · teal · lime · amber · orange · red at 0 · 5 · 20 ·
|
cold → hot ramp (blue · teal · lime · amber · orange · red at 0 · 5 · 20 ·
|
||||||
50 · 100 · 300 MW), and add a log-scale minimum-FRP slider whose track is the
|
50 · 100 · 300 MW), and add a log-scale minimum-FRP slider whose track is the
|
||||||
ramp, an All / Nominal+ / High confidence switch and an "N of M shown"
|
ramp, an All / Nominal+ / High confidence switch and an "N of M shown"
|
||||||
counter to the layer row. The filter applies once before rendering, so
|
counter to the layer row. Far-zoom heat cells keep a warm density fill
|
||||||
|
(lime · amber · red). The filter applies once before rendering, so
|
||||||
markers, cards, heat cells, context and the top-fires query agree; share
|
markers, cards, heat cells, context and the top-fires query agree; share
|
||||||
links keep it (`w` token: `f`, `c`), and `get_active_fires` takes matching
|
links keep it (`w` token: `f`, `c`), and `get_active_fires` takes matching
|
||||||
`min_frp_mw` and `confidence` arguments. Default 0 MW / All (gekh, #1426).
|
`min_frp_mw` and `confidence` arguments. Default 0 MW / All (gekh, #1426).
|
||||||
@@ -2058,9 +2058,12 @@ accessible name remains "Don't show this again". Control behavior is unchanged.
|
|||||||
|
|
||||||
Every FIRMS detection is colored by fire radiative power on a six-stop cold →
|
Every FIRMS detection is colored by fire radiative power on a six-stop cold →
|
||||||
hot ramp: blue from 0 MW, teal from 5, lime from 20, amber from 50, orange from
|
hot ramp: blue from 0 MW, teal from 5, lime from 20, amber from 50, orange from
|
||||||
100 and red from 300 MW (`FRP_RAMP` in `src/data/firmsIntensity.js`). Heat
|
100 and red from 300 MW (`FRP_RAMP` in `src/data/firmsIntensity.js`). Glow
|
||||||
cells, glow sprites and card accents read the same ramp; confidence and
|
sprites and fire-card accents read that ramp; confidence and brightness do
|
||||||
brightness do not affect the color.
|
not affect the color. Aggregated heat cells (far zoom) instead take the warm
|
||||||
|
end of the ramp — lime, amber or red — from their heat-normalized score
|
||||||
|
(density, night share and strongest FRP), so a region reads as one field
|
||||||
|
rather than a per-cell mosaic; the cell card's accent matches its fill.
|
||||||
|
|
||||||
The Active Fires row carries a "Fire intensity (FRP)" slider on a log scale
|
The Active Fires row carries a "Fire intensity (FRP)" slider on a log scale
|
||||||
whose track is painted with the ramp and ticked at the same six values (its
|
whose track is painted with the ramp and ticked at the same six values (its
|
||||||
|
|||||||
@@ -137,15 +137,33 @@ export function createModel({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill color for an aggregated heat cell: the ramp color of its strongest
|
* Severity stop for an aggregated heat cell from its heat-normalized score
|
||||||
* detection, so cells, markers and the slider legend read on one scale.
|
* (density, night share and strongest FRP together). Cells say *where* it
|
||||||
* @param {number} maxFrp - Strongest FRP in the cell, megawatts.
|
* burns, so they stay on the warm end of the ramp — lime, amber, red — and
|
||||||
|
* read as one field instead of a per-cell mosaic; the cold stops belong to
|
||||||
|
* single detections, which say *how hard* each one burns.
|
||||||
|
* @param {number} normalized - 0..1 heat score (sqrt-normalized to the view).
|
||||||
|
* @returns {{name: string, minFrp: number, color: Cesium.Color}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function cellColorStop(normalized) {
|
||||||
|
const name =
|
||||||
|
normalized > 0.72 ? 'red' : normalized > 0.42 ? 'amber' : 'lime';
|
||||||
|
return (
|
||||||
|
DETECTION_COLOR_STOPS.find((stop) => stop.name === name) ||
|
||||||
|
DETECTION_COLOR_STOPS[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill color for an aggregated heat cell.
|
||||||
|
* @param {number} normalized - 0..1 heat score (see {@link cellColorStop}).
|
||||||
* @param {number} alpha - Fill alpha (heat-normalized by the caller).
|
* @param {number} alpha - Fill alpha (heat-normalized by the caller).
|
||||||
* @returns {Cesium.Color}
|
* @returns {Cesium.Color}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function heatColor(maxFrp, alpha) {
|
function heatColor(normalized, alpha) {
|
||||||
return frpColorStop(maxFrp).color.withAlpha(alpha);
|
return cellColorStop(normalized).color.withAlpha(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -476,14 +494,14 @@ export function createModel({
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cell card accent: the ramp stop of the cell's strongest detection,
|
* Cell card accent: the warm severity stop of the cell's heat score,
|
||||||
* mirroring heatColor.
|
* mirroring heatColor.
|
||||||
* @param {number} maxFrp - Strongest FRP in the cell, megawatts.
|
* @param {number} normalized - 0..1 heat score.
|
||||||
* @returns {string} "r, g, b" accent string.
|
* @returns {string} "r, g, b" accent string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function cellAccent(maxFrp) {
|
function cellAccent(normalized) {
|
||||||
return accentForSeverity(frpColorStop(maxFrp).name);
|
return accentForSeverity(cellColorStop(normalized).name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Coordinate line like "30.512°N 75.831°E". */
|
/** Coordinate line like "30.512°N 75.831°E". */
|
||||||
@@ -590,6 +608,7 @@ export function createModel({
|
|||||||
cellIntersectsBounds,
|
cellIntersectsBounds,
|
||||||
heatScore,
|
heatScore,
|
||||||
heatColor,
|
heatColor,
|
||||||
|
cellColorStop,
|
||||||
frpColorStop,
|
frpColorStop,
|
||||||
detectionColorStop,
|
detectionColorStop,
|
||||||
frpPixelSize,
|
frpPixelSize,
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ export function createRendering({
|
|||||||
const score = components.model.heatScore(cell);
|
const score = components.model.heatScore(cell);
|
||||||
const normalized = Math.min(1, Math.sqrt(score / maxScore));
|
const normalized = Math.min(1, Math.sqrt(score / maxScore));
|
||||||
const alpha = 0.16 + normalized * 0.5;
|
const alpha = 0.16 + normalized * 0.5;
|
||||||
const color = components.model.heatColor(cell.maxFrp, alpha);
|
const color = components.model.heatColor(normalized, alpha);
|
||||||
const centerLon = cell.lonCell + lod.gridDegrees / 2;
|
const centerLon = cell.lonCell + lod.gridDegrees / 2;
|
||||||
const centerLat = cell.latCell + lod.gridDegrees / 2;
|
const centerLat = cell.latCell + lod.gridDegrees / 2;
|
||||||
const position = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 0);
|
const position = Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 0);
|
||||||
@@ -170,12 +170,13 @@ export function createRendering({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Cells arrive heat-sorted, so candidate order doubles as label priority.
|
// Cells arrive heat-sorted, so candidate order doubles as label priority.
|
||||||
|
// Accent is resolved here because `normalized` only exists in this walk.
|
||||||
layerState._labelCandidates.push({
|
layerState._labelCandidates.push({
|
||||||
position,
|
position,
|
||||||
cullPosition: components.model.cellCullPosition(centerLon, centerLat),
|
cullPosition: components.model.cellCullPosition(centerLon, centerLat),
|
||||||
fire: null,
|
fire: null,
|
||||||
cell,
|
cell,
|
||||||
accent: components.model.cellAccent(cell.maxFrp),
|
accent: components.model.cellAccent(normalized),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user