Compare commits

...

2 commits

Author SHA1 Message Date
Aaron Fenyes
adc60ac5c1 Spruce up formatting and error messages
Make the new code's formatting and error messages more consistent with
the previous code. I don't necessarily have a strong preference for the
previous conventions, but I do like stuff to be consistent.
2025-10-07 16:19:14 -07:00
Aaron Fenyes
27edbfb010 Streamline axis naming
This makes it simpler, from the programmer's perspective, to get the
name of an axis as a string slice and to format an axis name into a
string. To me, the matching method `Axis::name` seems more direct than
the explicit lookup table that it replaces, and I'm hoping that it will
be about as easy for the compiler to inline, or even easier.

Implementing `Display` enables us to hand an `Axis` to a string
formatter without any explicit conversion. It adds extra code in the
short run, but I'd expect it to simplify our code in the long run by
fitting into the conventions set by the Rust standard library.
2025-10-07 15:36:12 -07:00
2 changed files with 52 additions and 28 deletions

View file

@ -127,7 +127,7 @@ pub trait Element: Serial + ProblemPoser + DisplayItem {
}
impl Debug for dyn Element {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.id().fmt(f)
}
}
@ -305,13 +305,14 @@ impl Element for Point {
point(0.0, 0.0, 0.0),
)
}
fn default_regulators(self: Rc<Self>) -> Vec<Rc<dyn Regulator>> {
all::<Axis>()
.map(|axis| {
Rc::new(PointCoordinateRegulator::new(self.clone(), axis))
as Rc::<dyn Regulator>
})
.map(
|axis| Rc::new(
PointCoordinateRegulator::new(self.clone(), axis)
) as Rc::<dyn Regulator>
)
.collect()
}
@ -511,10 +512,18 @@ impl ProblemPoser for HalfCurvatureRegulator {
}
#[derive(Clone, Copy, Sequence)]
pub enum Axis {X = 0, Y = 1, Z = 2}
pub enum Axis { X = 0, Y = 1, Z = 2 }
impl Axis {
pub const NAME: [&str; Axis::CARDINALITY] = ["X", "Y", "Z"];
fn name(&self) -> &'static str {
match self { Axis::X => "X", Axis::Y => "Y", Axis::Z => "Z" }
}
}
impl fmt::Display for Axis {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
pub struct PointCoordinateRegulator {
@ -530,19 +539,32 @@ impl PointCoordinateRegulator {
let measurement = subject.representation().map(
move |rep| rep[axis as usize]
);
let set_point = create_signal(SpecifiedValue::from_empty_spec());
Self { subject, axis, measurement, set_point, serial: Self::next_serial() }
let serial = Self::next_serial();
Self { subject, axis, measurement, set_point, serial }
}
}
impl Serial for PointCoordinateRegulator {
fn serial(&self) -> u64 { self.serial }
fn serial(&self) -> u64 {
self.serial
}
}
impl Regulator for PointCoordinateRegulator {
fn subjects(&self) -> Vec<Rc<dyn Element>> { vec![self.subject.clone()] }
fn measurement(&self) -> ReadSignal<f64> { self.measurement }
fn set_point(&self) -> Signal<SpecifiedValue> { self.set_point }
fn subjects(&self) -> Vec<Rc<dyn Element>> {
vec![self.subject.clone()]
}
fn measurement(&self) -> ReadSignal<f64> {
self.measurement
}
fn set_point(&self) -> Signal<SpecifiedValue> {
self.set_point
}
}
impl ProblemPoser for PointCoordinateRegulator {
@ -550,22 +572,25 @@ impl ProblemPoser for PointCoordinateRegulator {
self.set_point.with_untracked(|set_pt| {
if let Some(val) = set_pt.value {
let col = self.subject.column_index().expect(
"Subject must be indexed before point-coordinate regulator poses.");
"Subject should be indexed before point coordinate regulator writes problem data"
);
problem.frozen.push(self.axis as usize, col, val);
// Check if all three spatial coordinates have been frozen, and if so,
// freeze the norm component as well
let mut coords = [0.0; Axis::CARDINALITY];
let mut nset: usize = 0;
for &MatrixEntry {index, value} in &(problem.frozen) {
if index.1 == col && index.0 < Axis::CARDINALITY {
nset += 1;
coords[index.0] = value
// if all three of the subject's spatial coordinates have been
// frozen, then freeze its norm component too
let mut coords_frozen = [0.0; Axis::CARDINALITY];
let mut n_set: usize = 0;
for &MatrixEntry { index, value } in &(problem.frozen) {
let (row_frozen, col_frozen) = index;
if col_frozen == col && row_frozen < Axis::CARDINALITY {
n_set += 1;
coords_frozen[row_frozen] = value
}
}
if nset == Axis::CARDINALITY {
let [x, y, z] = coords;
problem.frozen.push(
Point::NORM_COMPONENT, col, point(x,y,z)[Point::NORM_COMPONENT]);
if n_set == Axis::CARDINALITY {
let [x, y, z] = coords_frozen;
let norm = point(x, y, z)[Point::NORM_COMPONENT];
problem.frozen.push(Point::NORM_COMPONENT, col, norm);
}
}
});

View file

@ -6,7 +6,6 @@ use web_sys::{KeyboardEvent, MouseEvent, wasm_bindgen::JsCast};
use crate::{
AppState,
assembly::{
Axis,
Element,
HalfCurvatureRegulator,
InversiveDistanceRegulator,
@ -123,7 +122,7 @@ impl OutlineItem for HalfCurvatureRegulator {
impl OutlineItem for PointCoordinateRegulator {
fn outline_item(self: Rc<Self>, _element: &Rc<dyn Element>) -> View {
let name = format!("{} coordinate", Axis::NAME[self.axis as usize]);
let name = format!("{} coordinate", self.axis);
view! {
li(class = "regulator") {
div(class = "regulator-label") // for spacing