Add a point element
Also add a new test assembly, "Pointed," to try out the new element.
This commit is contained in:
parent
873de78f2d
commit
1945086586
3 changed files with 179 additions and 51 deletions
|
@ -2,6 +2,7 @@ use nalgebra::{DMatrix, DVector, DVectorView};
|
|||
use rustc_hash::FxHashMap;
|
||||
use slab::Slab;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::Cell,
|
||||
collections::BTreeSet,
|
||||
rc::Rc,
|
||||
|
@ -16,6 +17,7 @@ use crate::{
|
|||
Q,
|
||||
change_half_curvature,
|
||||
local_unif_to_std,
|
||||
point,
|
||||
realize_gram,
|
||||
sphere,
|
||||
ConfigSubspace,
|
||||
|
@ -197,6 +199,87 @@ impl ProblemPoser for Sphere {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Point {
|
||||
pub id: String,
|
||||
pub label: String,
|
||||
pub representation: Signal<DVector<f64>>,
|
||||
pub regulators: Signal<BTreeSet<RegulatorKey>>,
|
||||
pub serial: u64,
|
||||
column_index: Cell<Option<usize>>
|
||||
}
|
||||
|
||||
impl Point {
|
||||
const WEIGHT_COMPONENT: usize = 3;
|
||||
|
||||
pub fn new(
|
||||
id: String,
|
||||
label: String,
|
||||
representation: DVector<f64>
|
||||
) -> Point {
|
||||
Point {
|
||||
id,
|
||||
label,
|
||||
representation: create_signal(representation),
|
||||
regulators: create_signal(BTreeSet::default()),
|
||||
serial: Self::next_serial(),
|
||||
column_index: None.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for Point {
|
||||
fn default_id() -> String {
|
||||
"point".to_string()
|
||||
}
|
||||
|
||||
fn default(id: String, id_num: u64) -> Point {
|
||||
Point::new(
|
||||
id,
|
||||
format!("Point {id_num}"),
|
||||
point(0.0, 0.0, 0.0)
|
||||
)
|
||||
}
|
||||
|
||||
fn id(&self) -> &String {
|
||||
&self.id
|
||||
}
|
||||
|
||||
fn label(&self) -> &String {
|
||||
&self.label
|
||||
}
|
||||
|
||||
fn representation(&self) -> Signal<DVector<f64>> {
|
||||
self.representation
|
||||
}
|
||||
|
||||
fn regulators(&self) -> Signal<BTreeSet<RegulatorKey>> {
|
||||
self.regulators
|
||||
}
|
||||
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
|
||||
fn column_index(&self) -> Option<usize> {
|
||||
self.column_index.get()
|
||||
}
|
||||
|
||||
fn set_column_index(&self, index: usize) {
|
||||
self.column_index.set(Some(index));
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemPoser for Point {
|
||||
fn pose(&self, problem: &mut ConstraintProblem, _elts: &Slab<Rc<dyn Element>>) {
|
||||
let index = self.column_index().expect(
|
||||
format!("Point \"{}\" should be indexed before writing problem data", self.id).as_str()
|
||||
);
|
||||
problem.gram.push_sym(index, index, 0.0);
|
||||
problem.frozen.push(Point::WEIGHT_COMPONENT, index, 0.5);
|
||||
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Regulator: ProblemPoser + OutlineItem {
|
||||
fn subjects(&self) -> Vec<ElementKey>;
|
||||
fn measurement(&self) -> ReadSignal<f64>;
|
||||
|
@ -617,8 +700,7 @@ impl Assembly {
|
|||
// step the assembly along the deformation. this changes the elements'
|
||||
// normalizations, so we restore those afterward
|
||||
/* KLUDGE */
|
||||
// since our test assemblies only include spheres, we assume that every
|
||||
// element is on the 1 mass shell
|
||||
// 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() {
|
||||
|
@ -626,13 +708,15 @@ impl Assembly {
|
|||
// step the assembly along the deformation
|
||||
*rep += motion_proj.column(column_index);
|
||||
|
||||
// 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);
|
||||
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 => {
|
||||
console::log_1(&JsValue::from(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue