results: clamp the contour legend's range; values above it in an over colour (#191)

results.contour takes range {min?, max?} (or "auto"), kept until the field changes: a
singular peak no longer squeezes the field into the bottom bands. Values above a clamped
maximum go to an extra band drawn in the over colour, split exactly at the clamp; the legend
shows that band up to the true maximum and says it is clamped. The results panel has Legend
max/min (Auto or a value), the MCP show_results tool a range argument, and headless pictures
follow the clamp too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 11:07:46 -04:00
1 parent 441f03d093
commit 5112855b83
10 files changed
+227 -26

No files matched your search

+16
View File
@@ -372,6 +372,12 @@ pub struct ResultsView {
/// Contours of this field; `None` draws the deformed shape in element colours.
pub contour: Option<Field>,
pub bands: u32,
/// The legend's range, clamped below the field's smallest or above its largest value (each
/// `None` follows the field): a singular peak no longer squeezes the field into one band.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub range_min: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub range_max: Option<f64>,
/// The mode shown, from 1 (frequency steps).
pub mode: usize,
/// The field frame shown (explicit steps); `None` is the last.
@@ -404,6 +410,8 @@ impl ResultsView {
scale: true_scale.then_some(1.0),
contour: Some(contour),
bands: DEFAULT_BANDS,
range_min: None,
range_max: None,
mode: 1,
frame: None,
animate: false,
@@ -413,6 +421,11 @@ impl ResultsView {
pub fn pick(&self) -> Pick {
Pick { mode: self.mode, frame: self.frame }
}
/// The contour bands for a field ranging from `min` to `max`, clamped to the view's range.
pub fn bands(&self, min: f64, max: f64) -> fieldcraft_render::contour::Bands {
fieldcraft_render::contour::Bands::clamped(min, max, self.range_min, self.range_max, self.bands)
}
}
/// The automatic deformation scale draws the largest displacement this fraction of the model's
@@ -650,6 +663,9 @@ impl Session {
let ends =
range(r.nodes(), &values).map(|((ln, lv), (hn, hv))| json!({"min": {"node": ln, "value": lv}, "max": {"node": hn, "value": hv}}));
out["contour"] = json!({"field": f, "label": f.label(), "unit": f.unit(r, self.model.units()), "range": ends});
if v.range_min.is_some() || v.range_max.is_some() {
out["contour"]["legend"] = json!({"min": v.range_min, "max": v.range_max});
}
}
match r.kind() {
Kind::Frequency(fr) => {