feat: Point coordinate regulators #118

Open
glen wants to merge 1 commit from glen/dyna3:pointCoordRegulators into main
5 changed files with 117 additions and 5 deletions

21
app-proto/Cargo.lock generated
View file

@ -255,6 +255,7 @@ dependencies = [
"charming", "charming",
"console_error_panic_hook", "console_error_panic_hook",
"dyna3", "dyna3",
"enum-iterator",
"itertools", "itertools",
"js-sys", "js-sys",
"lazy_static", "lazy_static",
@ -271,6 +272,26 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "enum-iterator"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4549325971814bda7a44061bf3fe7e487d447cba01e4220a4b454d630d7a016"
dependencies = [
"enum-iterator-derive",
]
[[package]]
name = "enum-iterator-derive"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685adfa4d6f3d765a26bc5dbc936577de9abf756c1feeb3089b01dd395034842"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"

View file

@ -10,6 +10,7 @@ default = ["console_error_panic_hook"]
dev = [] dev = []
[dependencies] [dependencies]
enum-iterator = "2.3.0"
itertools = "0.13.0" itertools = "0.13.0"
js-sys = "0.3.70" js-sys = "0.3.70"
lazy_static = "1.5.0" lazy_static = "1.5.0"

View file

@ -1,3 +1,4 @@
use enum_iterator::{all, Sequence};
use nalgebra::{DMatrix, DVector, DVectorView}; use nalgebra::{DMatrix, DVector, DVectorView};
use std::{ use std::{
cell::Cell, cell::Cell,
@ -26,6 +27,7 @@ use crate::{
ConfigSubspace, ConfigSubspace,
ConstraintProblem, ConstraintProblem,
DescentHistory, DescentHistory,
MatrixEntry,
Realization, Realization,
}, },
specified::SpecifiedValue, specified::SpecifiedValue,
@ -269,6 +271,7 @@ pub struct Point {
impl Point { impl Point {
const WEIGHT_COMPONENT: usize = 3; const WEIGHT_COMPONENT: usize = 3;
const NORM_COMPONENT: usize = 4;
pub fn new( pub fn new(
id: String, id: String,
@ -303,6 +306,15 @@ impl Element for Point {
) )
} }
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>
})
.collect()
}
fn id(&self) -> &String { fn id(&self) -> &String {
&self.id &self.id
} }
@ -446,14 +458,14 @@ impl ProblemPoser for InversiveDistanceRegulator {
} }
pub struct HalfCurvatureRegulator { pub struct HalfCurvatureRegulator {
pub subject: Rc<dyn Element>, pub subject: Rc<Sphere>,
pub measurement: ReadSignal<f64>, pub measurement: ReadSignal<f64>,
pub set_point: Signal<SpecifiedValue>, pub set_point: Signal<SpecifiedValue>,
serial: u64, serial: u64,
} }
impl HalfCurvatureRegulator { impl HalfCurvatureRegulator {
pub fn new(subject: Rc<dyn Element>) -> Self { pub fn new(subject: Rc<Sphere>) -> Self {
let measurement = subject.representation().map( let measurement = subject.representation().map(
|rep| rep[Sphere::CURVATURE_COMPONENT] |rep| rep[Sphere::CURVATURE_COMPONENT]
); );
@ -498,6 +510,69 @@ impl ProblemPoser for HalfCurvatureRegulator {
} }
} }
#[derive(Clone, Copy, Sequence)]
pub enum Axis {X = 0, Y = 1, Z = 2}
impl Axis {
pub const N_AXIS: usize = (Axis::Z as usize) + 1;
pub const NAME: [&str; Axis::N_AXIS] = ["X", "Y", "Z"];
}
pub struct PointCoordinateRegulator {
pub subject: Rc<Point>,
pub axis: Axis,
pub measurement: ReadSignal<f64>,
pub set_point: Signal<SpecifiedValue>,
serial: u64
}
impl PointCoordinateRegulator {
pub fn new(subject: Rc<Point>, axis: Axis) -> Self {
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() }
}
}
impl Serial for PointCoordinateRegulator {
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 }
}
impl ProblemPoser for PointCoordinateRegulator {
fn pose(&self, problem: &mut ConstraintProblem) {
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.");
problem.frozen.push(self.axis as usize, col, val);
// Check if all three coordinates have been frozen, and if so,
// freeze the coradius as well
let mut coords = [0.0; Axis::N_AXIS];
let mut nset: usize = 0;
for &MatrixEntry {index, value} in &(problem.frozen) {
if index.1 == col && index.0 < Axis::N_AXIS {
nset += 1;
coords[index.0] = value
}
}
if nset == Axis::N_AXIS {
let [x, y, z] = coords;
problem.frozen.push(
Point::NORM_COMPONENT, col, point(x,y,z)[Point::NORM_COMPONENT]);
}
}
});
}
}
// the velocity is expressed in uniform coordinates // the velocity is expressed in uniform coordinates
pub struct ElementMotion<'a> { pub struct ElementMotion<'a> {
pub element: Rc<dyn Element>, pub element: Rc<dyn Element>,

View file

@ -6,9 +6,11 @@ use web_sys::{KeyboardEvent, MouseEvent, wasm_bindgen::JsCast};
use crate::{ use crate::{
AppState, AppState,
assembly::{ assembly::{
Axis,
Element, Element,
HalfCurvatureRegulator, HalfCurvatureRegulator,
InversiveDistanceRegulator, InversiveDistanceRegulator,
PointCoordinateRegulator,
Regulator, Regulator,
}, },
specified::SpecifiedValue specified::SpecifiedValue
@ -119,6 +121,19 @@ impl OutlineItem for HalfCurvatureRegulator {
} }
} }
impl OutlineItem for PointCoordinateRegulator {
fn outline_item(self: Rc<Self>, _element: &Rc<dyn Element>) -> View {
view! {
li(class = "regulator") {
div(class = "regulator-label") { (Axis::NAME[self.axis as usize]) }
div(class = "regulator-type") { "Coordinate" }
RegulatorInput(regulator = self)
div(class = "status")
}
}
}
}
// a list item that shows an element in an outline view of an assembly // a list item that shows an element in an outline view of an assembly
#[component(inline_props)] #[component(inline_props)]
fn ElementOutlineItem(element: Rc<dyn Element>) -> View { fn ElementOutlineItem(element: Rc<dyn Element>) -> View {

View file

@ -46,14 +46,14 @@ pub fn project_sphere_to_normalized(rep: &mut DVector<f64>) {
// normalize a point's representation vector by scaling // normalize a point's representation vector by scaling
pub fn project_point_to_normalized(rep: &mut DVector<f64>) { pub fn project_point_to_normalized(rep: &mut DVector<f64>) {
rep.scale_mut(0.5 / rep[3]); rep.scale_mut(0.5 / rep[3]); //FIXME: This 3 should be Point::WEIGHT_COMPONENT
} }
// --- partial matrices --- // --- partial matrices ---
pub struct MatrixEntry { pub struct MatrixEntry {
index: (usize, usize), pub index: (usize, usize),
value: f64, pub value: f64,
} }
pub struct PartialMatrix(Vec<MatrixEntry>); pub struct PartialMatrix(Vec<MatrixEntry>);