refactor(properties): rework ellipse geometry panel

Single Geometry section: Start/Center/End points, Major/Minor radius (editable; minor derives ratio), Radius ratio, Start/End angle editable. Major/Minor axis vectors, parameters, Length and Normal kept read-only at the end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-08 22:48:25 +03:00
commit 954a2e8b43

View file

@ -176,47 +176,53 @@ fn properties(ell: &Ellipse) -> Vec<PropSection> {
let n = glam::DVec3::new(ell.normal.x, ell.normal.y, ell.normal.z); let n = glam::DVec3::new(ell.normal.x, ell.normal.y, ell.normal.z);
let v = n.cross(u); let v = n.cross(u);
// Parametric end point in WCS: center + r_major·cos(t1)·u + r_minor·sin(t1)·v. // Parametric points in WCS: center + r_major·cos(t)·u + r_minor·sin(t)·v.
let t1 = ell.end_parameter; let center = glam::DVec3::new(ell.center.x, ell.center.y, ell.center.z);
let end = glam::DVec3::new(ell.center.x, ell.center.y, ell.center.z) let pt_at = |t: f64| center + u * (r_major * t.cos()) + v * (r_minor * t.sin());
+ u * (r_major * t1.cos()) let start = pt_at(ell.start_parameter);
+ v * (r_minor * t1.sin()); let end = pt_at(ell.end_parameter);
// Axis vectors (center → axis endpoint) in WCS.
let major_vec = u * r_major;
let minor_vec = v * r_minor;
let start_angle = ell.start_parameter.to_degrees().rem_euclid(360.0); let start_angle = ell.start_parameter.to_degrees().rem_euclid(360.0);
let end_angle = ell.end_parameter.to_degrees().rem_euclid(360.0); let end_angle = ell.end_parameter.to_degrees().rem_euclid(360.0);
let props = ell.mass_props(); let props = ell.mass_props();
vec![ vec![PropSection {
PropSection { title: "Geometry".into(),
title: "Geometry".into(), props: vec![
props: vec![ ro("Start X", "start_x", format!("{:.4}", start.x)),
edit("Center X", "center_x", ell.center.x), ro("Start Y", "start_y", format!("{:.4}", start.y)),
edit("Center Y", "center_y", ell.center.y), ro("Start Z", "start_z", format!("{:.4}", start.z)),
edit("Center Z", "center_z", ell.center.z), edit("Center X", "center_x", ell.center.x),
ro("End X", "end_x", format!("{:.4}", end.x)), edit("Center Y", "center_y", ell.center.y),
ro("End Y", "end_y", format!("{:.4}", end.y)), edit("Center Z", "center_z", ell.center.z),
ro("End Z", "end_z", format!("{:.4}", end.z)), ro("End X", "end_x", format!("{:.4}", end.x)),
edit("Major radius", "major_r", r_major), ro("End Y", "end_y", format!("{:.4}", end.y)),
ro("Minor radius", "minor_r", format!("{r_minor:.4}")), ro("End Z", "end_z", format!("{:.4}", end.z)),
edit("Radius ratio", "ratio", ell.minor_axis_ratio), edit("Major radius", "major_r", r_major),
ro("Start angle", "start_angle", format!("{start_angle:.2}")), edit("Minor radius", "minor_r", r_minor),
ro("End angle", "end_angle", format!("{end_angle:.2}")), edit("Radius ratio", "ratio", ell.minor_axis_ratio),
edit("Start parameter", "start_param", ell.start_parameter), edit("Start angle", "start_angle", start_angle),
edit("End parameter", "end_param", ell.end_parameter), edit("End angle", "end_angle", end_angle),
ro("Area", "area", format!("{:.4}", props.area)), ro("Major axis vector X", "major_x", format!("{:.4}", major_vec.x)),
ro("Length", "length", format!("{:.4}", props.perimeter)), ro("Major axis vector Y", "major_y", format!("{:.4}", major_vec.y)),
], ro("Major axis vector Z", "major_z", format!("{:.4}", major_vec.z)),
}, ro("Minor axis vector X", "minor_x", format!("{:.4}", minor_vec.x)),
PropSection { ro("Minor axis vector Y", "minor_y", format!("{:.4}", minor_vec.y)),
title: "Misc".into(), ro("Minor axis vector Z", "minor_z", format!("{:.4}", minor_vec.z)),
props: vec![ ro("Area", "area", format!("{:.4}", props.area)),
edit("Normal X", "normal_x", ell.normal.x), ro("Start parameter", "start_param", format!("{:.4}", ell.start_parameter)),
edit("Normal Y", "normal_y", ell.normal.y), ro("End parameter", "end_param", format!("{:.4}", ell.end_parameter)),
edit("Normal Z", "normal_z", ell.normal.z), ro("Length", "length", format!("{:.4}", props.perimeter)),
], ro("Normal X", "normal_x", format!("{:.4}", ell.normal.x)),
}, ro("Normal Y", "normal_y", format!("{:.4}", ell.normal.y)),
] ro("Normal Z", "normal_z", format!("{:.4}", ell.normal.z)),
],
}]
} }
fn apply_geom_prop(ell: &mut Ellipse, field: &str, value: &str) { fn apply_geom_prop(ell: &mut Ellipse, field: &str, value: &str) {
@ -236,12 +242,15 @@ fn apply_geom_prop(ell: &mut Ellipse, field: &str, value: &str) {
ell.major_axis.z *= s; ell.major_axis.z *= s;
} }
} }
"ratio" => ell.minor_axis_ratio = v, "minor_r" => {
"start_param" => ell.start_parameter = v, let major = ell.major_axis_length();
"end_param" => ell.end_parameter = v, if major > 1e-12 && v > 0.0 {
"normal_x" => ell.normal.x = v, ell.minor_axis_ratio = v / major;
"normal_y" => ell.normal.y = v, }
"normal_z" => ell.normal.z = v, }
"ratio" if v > 0.0 => ell.minor_axis_ratio = v,
"start_angle" => ell.start_parameter = v.to_radians(),
"end_angle" => ell.end_parameter = v.to_radians(),
_ => {} _ => {}
} }
} }