forked from 1b-agent/fieldcraft-upstream
ui: Relax around worst element at the top of Mesh Quality; plain preview text (#398)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
87af68f550
commit
a6f1a6dbeb
3 files changed
+16
-14
No files matched your search
@@ -374,7 +374,9 @@ pub(crate) fn weights(model: &Model, p: &Value) -> Result<(BTreeMap<u32, f64>, O
|
|||||||
nodes.extend(el.nodes.iter().copied());
|
nodes.extend(el.nodes.iter().copied());
|
||||||
}
|
}
|
||||||
if listed == 0 {
|
if listed == 0 {
|
||||||
return Err(EngineError::Params("say which nodes to relax: give one of `center` and `radius`, `around_element`, `nodes`, `elements` or `set`".into()));
|
return Err(EngineError::Params(
|
||||||
|
"say which nodes to relax: give one of `center` and `radius`, `around_element`, `nodes`, `elements` or `set`".into(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if let Some(only) = &only {
|
if let Some(only) = &only {
|
||||||
nodes.retain(|n| only.contains(n));
|
nodes.retain(|n| only.contains(n));
|
||||||
@@ -450,7 +452,7 @@ fn relax_nodes(s: &mut Session, p: &Value) -> Result<Value> {
|
|||||||
s.model.set_node(*n, *x)?;
|
s.model.set_node(*n, *x)?;
|
||||||
}
|
}
|
||||||
let summary = format!(
|
let summary = format!(
|
||||||
"moved {} node{} (largest {:.3e}); scaled Jacobian min {:.3} → {:.3}{}",
|
"moved {} node{} (largest {:.3e}); scaled Jacobian min from {:.3} to {:.3}{}",
|
||||||
r.moved,
|
r.moved,
|
||||||
if r.moved == 1 { "" } else { "s" },
|
if r.moved == 1 { "" } else { "s" },
|
||||||
r.max_displacement,
|
r.max_displacement,
|
||||||
|
|||||||
@@ -1179,7 +1179,7 @@ impl ModelApp {
|
|||||||
let p = self.relax_preview()?;
|
let p = self.relax_preview()?;
|
||||||
let r = &p.relaxed;
|
let r = &p.relaxed;
|
||||||
Some(format!(
|
Some(format!(
|
||||||
"Preview: {} nodes move (largest {:.3}); scaled Jacobian min {:.3} → {:.3}, edge ratio max {:.2} → {:.2}, {} → {} invalid",
|
"Preview: {} nodes move (largest {:.3}); scaled Jacobian min {:.3} to {:.3}, edge ratio max {:.2} to {:.2}, invalid {} to {}",
|
||||||
r.moved,
|
r.moved,
|
||||||
r.max_displacement,
|
r.max_displacement,
|
||||||
r.before.min_quality,
|
r.before.min_quality,
|
||||||
|
|||||||
+11
-11
@@ -347,7 +347,8 @@ const METRICS: [(&str, &str, bool); 4] = [
|
|||||||
const MAX_SELECT: usize = 10_000;
|
const MAX_SELECT: usize = 10_000;
|
||||||
|
|
||||||
/// `mesh.quality`'s reply: the counts, then each metric's range, histogram and worst element (a
|
/// `mesh.quality`'s reply: the counts, then each metric's range, histogram and worst element (a
|
||||||
/// click selects and frames it), and buttons selecting the invalid and undetermined elements.
|
/// click selects and frames it), buttons selecting the invalid and undetermined elements, and
|
||||||
|
/// Relax around worst element (#398).
|
||||||
fn quality(ui: &mut egui::Ui, t: &Tokens, v: &Value, acts: &mut Vec<Act>) {
|
fn quality(ui: &mut egui::Ui, t: &Tokens, v: &Value, acts: &mut Vec<Act>) {
|
||||||
let n = |k: &str| v.get(k).and_then(Value::as_u64).unwrap_or(0);
|
let n = |k: &str| v.get(k).and_then(Value::as_u64).unwrap_or(0);
|
||||||
let labels = |k: &str| -> Vec<u32> {
|
let labels = |k: &str| -> Vec<u32> {
|
||||||
@@ -392,6 +393,15 @@ fn quality(ui: &mut egui::Ui, t: &Tokens, v: &Value, acts: &mut Vec<Act>) {
|
|||||||
acts.push(Act::Elements(l));
|
acts.push(Act::Elements(l));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(worst) = v.pointer("/metrics/scaled_jacobian/worst").and_then(Value::as_u64).and_then(|w| u32::try_from(w).ok()) {
|
||||||
|
if ui
|
||||||
|
.button("Relax around worst element")
|
||||||
|
.on_hover_text("Open Relax Nodes with its sphere round the element of smallest scaled Jacobian; preview, then OK")
|
||||||
|
.clicked()
|
||||||
|
{
|
||||||
|
acts.push(Act::Relax(worst));
|
||||||
|
}
|
||||||
|
}
|
||||||
for (key, label, low_bad) in METRICS {
|
for (key, label, low_bad) in METRICS {
|
||||||
let Some(m) = v.pointer(&format!("/metrics/{key}")).filter(|m| m.is_object()) else { continue };
|
let Some(m) = v.pointer(&format!("/metrics/{key}")).filter(|m| m.is_object()) else { continue };
|
||||||
let f = |k: &str| m.get(k).and_then(Value::as_f64);
|
let f = |k: &str| m.get(k).and_then(Value::as_f64);
|
||||||
@@ -419,16 +429,6 @@ fn quality(ui: &mut egui::Ui, t: &Tokens, v: &Value, acts: &mut Vec<Act>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(worst) = v.pointer("/metrics/scaled_jacobian/worst").and_then(Value::as_u64).and_then(|w| u32::try_from(w).ok()) {
|
|
||||||
ui.add_space(6.0);
|
|
||||||
if ui
|
|
||||||
.button("Relax around worst element")
|
|
||||||
.on_hover_text("Open Relax Nodes with its sphere round the element of smallest scaled Jacobian; preview, then OK")
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
acts.push(Act::Relax(worst));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(skipped) = v.get("skipped").and_then(Value::as_object).filter(|s| !s.is_empty()) {
|
if let Some(skipped) = v.get("skipped").and_then(Value::as_object).filter(|s| !s.is_empty()) {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
let text: Vec<String> = skipped.iter().map(|(k, n)| format!("{k}: {}", n.as_u64().map_or_else(|| n.to_string(), count))).collect();
|
let text: Vec<String> = skipped.iter().map(|(k, n)| format!("{k}: {}", n.as_u64().map_or_else(|| n.to_string(), count))).collect();
|
||||||
|
|||||||
Reference in new issue
Block a user