Add a trait method to normalize representations

This corrects the dispatching of the normalization routine for spheres,
and it adds a (perhaps redundant) normalization routine for points.
This commit is contained in:
Aaron Fenyes 2025-05-19 18:54:45 -07:00
parent a671a8273a
commit f4e5c34fde
2 changed files with 31 additions and 14 deletions

View file

@ -1,6 +1,5 @@
use nalgebra::{DMatrix, DVector, DVectorView}; use nalgebra::{DMatrix, DVector, DVectorView};
use std::{ use std::{
any::{Any, TypeId},
cell::Cell, cell::Cell,
collections::{BTreeMap, BTreeSet}, collections::{BTreeMap, BTreeSet},
cmp::Ordering, cmp::Ordering,
@ -19,6 +18,8 @@ use crate::{
Q, Q,
change_half_curvature, change_half_curvature,
local_unif_to_std, local_unif_to_std,
normalize_mut_point,
normalize_mut_sphere,
point, point,
realize_gram, realize_gram,
sphere, sphere,
@ -107,6 +108,9 @@ pub trait Element: Serial + ProblemPoser + DisplayItem {
// element is responsible for keeping this set up to date // element is responsible for keeping this set up to date
fn regulators(&self) -> Signal<BTreeSet<Rc<dyn Regulator>>>; fn regulators(&self) -> Signal<BTreeSet<Rc<dyn Regulator>>>;
// normalize a representation vector for this kind of element
fn normalize_mut_rep(&self, rep: &mut DVector<f64>);
// the configuration matrix column index that was assigned to the element // the configuration matrix column index that was assigned to the element
// last time the assembly was realized, or `None` if the element has never // last time the assembly was realized, or `None` if the element has never
// been through a realization // been through a realization
@ -221,6 +225,10 @@ impl Element for Sphere {
self.regulators self.regulators
} }
fn normalize_mut_rep(&self, rep: &mut DVector<f64>) {
normalize_mut_sphere(rep);
}
fn column_index(&self) -> Option<usize> { fn column_index(&self) -> Option<usize> {
self.column_index.get() self.column_index.get()
} }
@ -313,6 +321,10 @@ impl Element for Point {
self.regulators self.regulators
} }
fn normalize_mut_rep(&self, rep: &mut DVector<f64>) {
normalize_mut_point(rep);
}
fn column_index(&self) -> Option<usize> { fn column_index(&self) -> Option<usize> {
self.column_index.get() self.column_index.get()
} }
@ -782,24 +794,14 @@ impl Assembly {
// step the assembly along the deformation. this changes the elements' // step the assembly along the deformation. this changes the elements'
// normalizations, so we restore those afterward // normalizations, so we restore those afterward
/* KLUDGE */
// for now, we only restore the normalizations of spheres
for elt in self.elements.get_clone_untracked() { for elt in self.elements.get_clone_untracked() {
elt.representation().update_silent(|rep| { elt.representation().update_silent(|rep| {
match elt.column_index() { match elt.column_index() {
Some(column_index) => { Some(column_index) => {
// step the assembly along the deformation // step the element along the deformation and then
// restore its normalization
*rep += motion_proj.column(column_index); *rep += motion_proj.column(column_index);
elt.normalize_mut_rep(rep);
if elt.type_id() == TypeId::of::<Sphere>() {
// restore normalization by contracting toward the
// last coordinate axis
let q_sp = rep.fixed_rows::<3>(0).norm_squared();
let half_q_lt = -2.0 * rep[3] * rep[4];
let half_q_lt_sq = half_q_lt * half_q_lt;
let scaling = half_q_lt + (q_sp + half_q_lt_sq).sqrt();
rep.fixed_rows_mut::<4>(0).scale_mut(1.0 / scaling);
}
}, },
None => { None => {
console::log_1(&JsValue::from( console::log_1(&JsValue::from(

View file

@ -34,6 +34,21 @@ pub fn sphere_with_offset(dir_x: f64, dir_y: f64, dir_z: f64, off: f64, curv: f6
]) ])
} }
// normalize a sphere's representation vector by contracting toward the last
// coordinate axis
pub fn normalize_mut_sphere(rep: &mut DVector<f64>) {
let q_sp = rep.fixed_rows::<3>(0).norm_squared();
let half_q_lt = -2.0 * rep[3] * rep[4];
let half_q_lt_sq = half_q_lt * half_q_lt;
let scaling = half_q_lt + (q_sp + half_q_lt_sq).sqrt();
rep.fixed_rows_mut::<4>(0).scale_mut(1.0 / scaling);
}
// normalize a point's representation vector by scaling
pub fn normalize_mut_point(rep: &mut DVector<f64>) {
rep.scale_mut(0.5 / rep[3]);
}
// given a sphere's representation vector, change the sphere's half-curvature to // given a sphere's representation vector, change the sphere's half-curvature to
// `half-curv` and then restore normalization by contracting the representation // `half-curv` and then restore normalization by contracting the representation
// vector toward the curvature axis // vector toward the curvature axis