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 2adf4669f4
commit c263d5b8a6
2 changed files with 31 additions and 14 deletions

View file

@ -1,6 +1,5 @@
use nalgebra::{DMatrix, DVector, DVectorView};
use std::{
any::{Any, TypeId},
cell::Cell,
collections::{BTreeMap, BTreeSet},
cmp::Ordering,
@ -19,6 +18,8 @@ use crate::{
Q,
change_half_curvature,
local_unif_to_std,
normalize_mut_point,
normalize_mut_sphere,
point,
realize_gram,
sphere,
@ -106,6 +107,9 @@ pub trait Element: Serial + ProblemPoser + DisplayItem {
// element is responsible for keeping this set up to date
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
// last time the assembly was realized, or `None` if the element has never
// been through a realization
@ -214,6 +218,10 @@ impl Element for Sphere {
self.regulators
}
fn normalize_mut_rep(&self, rep: &mut DVector<f64>) {
normalize_mut_sphere(rep);
}
fn column_index(&self) -> Option<usize> {
self.column_index.get()
}
@ -300,6 +308,10 @@ impl Element for Point {
self.regulators
}
fn normalize_mut_rep(&self, rep: &mut DVector<f64>) {
normalize_mut_point(rep);
}
fn column_index(&self) -> Option<usize> {
self.column_index.get()
}
@ -769,24 +781,14 @@ impl Assembly {
// step the assembly along the deformation. this changes the elements'
// normalizations, so we restore those afterward
/* KLUDGE */
// for now, we only restore the normalizations of spheres
for elt in self.elements.get_clone_untracked() {
elt.representation().update_silent(|rep| {
match elt.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);
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);
}
elt.normalize_mut_rep(rep);
},
None => {
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
// `half-curv` and then restore normalization by contracting the representation
// vector toward the curvature axis