///|
pub fn view_layer_kind_label(kind : ViewLayerKind) -> String {
match kind {
ElevationLayer => "elevation"
SlopeLayer => "slope"
RoughnessLayer => "roughness"
HazardLayer => "hazard"
RouteLayer => "route"
EvidenceLayer => "evidence"
PowerLayer => "power"
}
}
///|
fn layer_toggle(
kind : ViewLayerKind,
label : String,
visible : Bool,
value_unit : String,
legend_min : Double,
legend_max : Double,
status : String,
) -> LayerToggle {
{
layer_id: view_layer_kind_label(kind),
kind,
label,
visible,
value_unit,
legend_min,
legend_max,
status,
}
}
///|
fn view_layers(
metrics : @terrain.TerrainMetrics,
energy : @mission.EnergyAssessment,
) -> Array[LayerToggle] {
[
layer_toggle(
ElevationLayer,
"Elevation",
true,
"m",
metrics.min_elevation_m,
metrics.max_elevation_m,
"measured",
),
layer_toggle(
SlopeLayer,
"Slope",
true,
"grade",
0.0,
metrics.max_neighbor_grade,
"derived",
),
layer_toggle(
RoughnessLayer,
"Roughness",
false,
"m",
0.0,
metrics.roughness_m,
"derived",
),
layer_toggle(
HazardLayer,
"Hazard",
true,
"risk",
0.0,
1.0,
@terrain.hazard_label(metrics.hazard_class),
),
layer_toggle(RouteLayer, "Routes", true, "state", 0.0, 1.0, "blocked"),
layer_toggle(EvidenceLayer, "Evidence", false, "state", 0.0, 1.0, "ready"),
layer_toggle(
PowerLayer,
"Power",
false,
"Wh",
0.0,
energy.available_energy_wh,
@mission.energy_decision_label(energy),
),
]
}
///|
fn bounded_intensity(
value : Double,
min_value : Double,
max_value : Double,
) -> Double {
if max_value <= min_value {
0.0
} else {
let raw = (value - min_value) / (max_value - min_value)
if raw < 0.0 {
0.0
} else if raw > 1.0 {
1.0
} else {
raw
}
}
}
///|
fn hazard_score(hazard : String) -> Double {
match hazard {
"clear" => 0.0
"caution" => 0.55
_ => 1.0
}
}
///|
fn cell_layer_values(
cell : @core.TerrainCell,
slope_grade : Double,
roughness_m : Double,
hazard : String,
metrics : @terrain.TerrainMetrics,
energy : @mission.EnergyAssessment,
) -> Array[CellLayerValue] {
[
{
layer_id: "elevation",
value: cell.elevation_m,
value_label: "\{cell.elevation_m} m",
status: "measured",
intensity: bounded_intensity(
cell.elevation_m,
metrics.min_elevation_m,
metrics.max_elevation_m,
),
},
{
layer_id: "slope",
value: slope_grade,
value_label: "\{slope_grade} grade",
status: "derived",
intensity: bounded_intensity(slope_grade, 0.0, metrics.max_neighbor_grade),
},
{
layer_id: "roughness",
value: roughness_m,
value_label: "\{roughness_m} m",
status: "derived",
intensity: bounded_intensity(roughness_m, 0.0, metrics.roughness_m),
},
{
layer_id: "hazard",
value: hazard_score(hazard),
value_label: hazard,
status: hazard,
intensity: hazard_score(hazard),
},
{
layer_id: "power",
value: energy.available_energy_wh,
value_label: "\{energy.available_energy_wh} Wh",
status: @mission.energy_decision_label(energy),
intensity: bounded_intensity(
energy.available_energy_wh,
0.0,
energy.required_energy_wh,
),
},
]
}