Use pointers, not keys, to refer to regulators
In the process, move the code that used to handle serial numbering for elements into the `Serial` trait, where it can provide serial numbers for regulators too.
This commit is contained in:
parent
fbd6177a07
commit
8a86038de0
3 changed files with 106 additions and 80 deletions
|
@ -3,6 +3,7 @@ name = "dyna3"
|
|||
version = "0.1.0"
|
||||
authors = ["Aaron Fenyes", "Glen Whitney"]
|
||||
edition = "2021"
|
||||
rust-version = "1.86"
|
||||
|
||||
[features]
|
||||
default = ["console_error_panic_hook"]
|
||||
|
|
|
@ -4,7 +4,6 @@ use slab::Slab;
|
|||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::Cell,
|
||||
collections::BTreeSet,
|
||||
fmt,
|
||||
fmt::{Debug, Formatter},
|
||||
hash::{Hash, Hasher},
|
||||
|
@ -30,24 +29,55 @@ use crate::{
|
|||
specified::SpecifiedValue
|
||||
};
|
||||
|
||||
// the types of the keys we use to access an assembly's elements and regulators
|
||||
// the types of the keys we use to access an assembly's elements
|
||||
pub type ElementKey = usize;
|
||||
pub type RegulatorKey = usize;
|
||||
|
||||
pub type ElementColor = [f32; 3];
|
||||
|
||||
/* KLUDGE */
|
||||
// we should reconsider this design when we build a system for switching between
|
||||
// assemblies. at that point, we might want to switch to hierarchical keys,
|
||||
// where each each element has a key that identifies it within its assembly and
|
||||
// where each each item has a key that identifies it within its assembly and
|
||||
// each assembly has a key that identifies it within the sesssion
|
||||
static NEXT_ELEMENT_SERIAL: AtomicU64 = AtomicU64::new(0);
|
||||
static NEXT_SERIAL: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
pub trait Serial {
|
||||
// a serial number that uniquely identifies this element
|
||||
fn serial(&self) -> u64;
|
||||
|
||||
// take the next serial number, panicking if that was the last one left
|
||||
fn next_serial() -> u64 where Self: Sized {
|
||||
// the technique we use to panic on overflow is taken from _Rust Atomics
|
||||
// and Locks_, by Mara Bos
|
||||
//
|
||||
// https://marabos.nl/atomics/atomics.html#example-handle-overflow
|
||||
//
|
||||
NEXT_SERIAL.fetch_update(
|
||||
Ordering::SeqCst, Ordering::SeqCst,
|
||||
|serial| serial.checked_add(1)
|
||||
).expect("Out of serial numbers for elements")
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for dyn Serial {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.serial().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn Serial {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.serial() == other.serial()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for dyn Serial {}
|
||||
|
||||
pub trait ProblemPoser {
|
||||
fn pose(&self, problem: &mut ConstraintProblem);
|
||||
}
|
||||
|
||||
pub trait Element: ProblemPoser + DisplayItem {
|
||||
pub trait Element: Serial + ProblemPoser + DisplayItem {
|
||||
// the default identifier for an element of this type
|
||||
fn default_id() -> String where Self: Sized;
|
||||
|
||||
|
@ -65,23 +95,7 @@ pub trait Element: ProblemPoser + DisplayItem {
|
|||
|
||||
// the regulators the element is subject to. the assembly that owns the
|
||||
// element is responsible for keeping this set up to date
|
||||
fn regulators(&self) -> Signal<BTreeSet<RegulatorKey>>;
|
||||
|
||||
// a serial number that uniquely identifies this element
|
||||
fn serial(&self) -> u64;
|
||||
|
||||
// take the next serial number, panicking if that was the last one left
|
||||
fn next_serial() -> u64 where Self: Sized {
|
||||
// the technique we use to panic on overflow is taken from _Rust Atomics
|
||||
// and Locks_, by Mara Bos
|
||||
//
|
||||
// https://marabos.nl/atomics/atomics.html#example-handle-overflow
|
||||
//
|
||||
NEXT_ELEMENT_SERIAL.fetch_update(
|
||||
Ordering::SeqCst, Ordering::SeqCst,
|
||||
|serial| serial.checked_add(1)
|
||||
).expect("Out of serial numbers for elements")
|
||||
}
|
||||
fn regulators(&self) -> Signal<Vec<Rc<dyn Regulator>>>;
|
||||
|
||||
// the configuration matrix column index that was assigned to the element
|
||||
// last time the assembly was realized, or `None` if the element has never
|
||||
|
@ -102,13 +116,13 @@ impl Debug for dyn Element {
|
|||
|
||||
impl Hash for dyn Element {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.serial().hash(state)
|
||||
<dyn Serial>::hash(self, state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn Element {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.serial() == other.serial()
|
||||
<dyn Serial>::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,8 +133,8 @@ pub struct Sphere {
|
|||
pub label: String,
|
||||
pub color: ElementColor,
|
||||
pub representation: Signal<DVector<f64>>,
|
||||
pub regulators: Signal<BTreeSet<RegulatorKey>>,
|
||||
pub serial: u64,
|
||||
pub regulators: Signal<Vec<Rc<dyn Regulator>>>,
|
||||
serial: u64,
|
||||
column_index: Cell<Option<usize>>
|
||||
}
|
||||
|
||||
|
@ -138,7 +152,7 @@ impl Sphere {
|
|||
label: label,
|
||||
color: color,
|
||||
representation: create_signal(representation),
|
||||
regulators: create_signal(BTreeSet::default()),
|
||||
regulators: create_signal(Vec::new()),
|
||||
serial: Self::next_serial(),
|
||||
column_index: None.into()
|
||||
}
|
||||
|
@ -175,14 +189,10 @@ impl Element for Sphere {
|
|||
self.representation
|
||||
}
|
||||
|
||||
fn regulators(&self) -> Signal<BTreeSet<RegulatorKey>> {
|
||||
fn regulators(&self) -> Signal<Vec<Rc<dyn Regulator>>> {
|
||||
self.regulators
|
||||
}
|
||||
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
|
||||
fn column_index(&self) -> Option<usize> {
|
||||
self.column_index.get()
|
||||
}
|
||||
|
@ -192,6 +202,12 @@ impl Element for Sphere {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serial for Sphere {
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemPoser for Sphere {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
let index = self.column_index().expect(
|
||||
|
@ -207,8 +223,8 @@ pub struct Point {
|
|||
pub label: String,
|
||||
pub color: ElementColor,
|
||||
pub representation: Signal<DVector<f64>>,
|
||||
pub regulators: Signal<BTreeSet<RegulatorKey>>,
|
||||
pub serial: u64,
|
||||
pub regulators: Signal<Vec<Rc<dyn Regulator>>>,
|
||||
serial: u64,
|
||||
column_index: Cell<Option<usize>>
|
||||
}
|
||||
|
||||
|
@ -226,7 +242,7 @@ impl Point {
|
|||
label,
|
||||
color,
|
||||
representation: create_signal(representation),
|
||||
regulators: create_signal(BTreeSet::default()),
|
||||
regulators: create_signal(Vec::new()),
|
||||
serial: Self::next_serial(),
|
||||
column_index: None.into()
|
||||
}
|
||||
|
@ -259,14 +275,10 @@ impl Element for Point {
|
|||
self.representation
|
||||
}
|
||||
|
||||
fn regulators(&self) -> Signal<BTreeSet<RegulatorKey>> {
|
||||
fn regulators(&self) -> Signal<Vec<Rc<dyn Regulator>>> {
|
||||
self.regulators
|
||||
}
|
||||
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
|
||||
fn column_index(&self) -> Option<usize> {
|
||||
self.column_index.get()
|
||||
}
|
||||
|
@ -276,6 +288,12 @@ impl Element for Point {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serial for Point {
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemPoser for Point {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
let index = self.column_index().expect(
|
||||
|
@ -287,7 +305,7 @@ impl ProblemPoser for Point {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait Regulator: ProblemPoser + OutlineItem {
|
||||
pub trait Regulator: Serial + ProblemPoser + OutlineItem {
|
||||
fn subjects(&self) -> Vec<Rc<dyn Element>>;
|
||||
fn measurement(&self) -> ReadSignal<f64>;
|
||||
fn set_point(&self) -> Signal<SpecifiedValue>;
|
||||
|
@ -303,10 +321,25 @@ pub trait Regulator: ProblemPoser + OutlineItem {
|
|||
}
|
||||
}
|
||||
|
||||
impl Hash for dyn Regulator {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
<dyn Serial>::hash(self, state)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn Regulator {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
<dyn Serial>::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for dyn Regulator {}
|
||||
|
||||
pub struct InversiveDistanceRegulator {
|
||||
pub subjects: [Rc<dyn Element>; 2],
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>
|
||||
pub set_point: Signal<SpecifiedValue>,
|
||||
serial: u64
|
||||
}
|
||||
|
||||
impl InversiveDistanceRegulator {
|
||||
|
@ -321,8 +354,9 @@ impl InversiveDistanceRegulator {
|
|||
});
|
||||
|
||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||
let serial = Self::next_serial();
|
||||
|
||||
InversiveDistanceRegulator { subjects, measurement, set_point }
|
||||
InversiveDistanceRegulator { subjects, measurement, set_point, serial }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,6 +374,12 @@ impl Regulator for InversiveDistanceRegulator {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serial for InversiveDistanceRegulator {
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemPoser for InversiveDistanceRegulator {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
self.set_point.with_untracked(|set_pt| {
|
||||
|
@ -358,7 +398,8 @@ impl ProblemPoser for InversiveDistanceRegulator {
|
|||
pub struct HalfCurvatureRegulator {
|
||||
pub subject: Rc<dyn Element>,
|
||||
pub measurement: ReadSignal<f64>,
|
||||
pub set_point: Signal<SpecifiedValue>
|
||||
pub set_point: Signal<SpecifiedValue>,
|
||||
serial: u64
|
||||
}
|
||||
|
||||
impl HalfCurvatureRegulator {
|
||||
|
@ -368,8 +409,9 @@ impl HalfCurvatureRegulator {
|
|||
);
|
||||
|
||||
let set_point = create_signal(SpecifiedValue::from_empty_spec());
|
||||
let serial = Self::next_serial();
|
||||
|
||||
HalfCurvatureRegulator { subject, measurement, set_point }
|
||||
HalfCurvatureRegulator { subject, measurement, set_point, serial }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -399,6 +441,12 @@ impl Regulator for HalfCurvatureRegulator {
|
|||
}
|
||||
}
|
||||
|
||||
impl Serial for HalfCurvatureRegulator {
|
||||
fn serial(&self) -> u64 {
|
||||
self.serial
|
||||
}
|
||||
}
|
||||
|
||||
impl ProblemPoser for HalfCurvatureRegulator {
|
||||
fn pose(&self, problem: &mut ConstraintProblem) {
|
||||
self.set_point.with_untracked(|set_pt| {
|
||||
|
@ -502,7 +550,7 @@ impl Assembly {
|
|||
|
||||
pub fn insert_regulator(&self, regulator: Rc<dyn Regulator>) {
|
||||
// add the regulator to the assembly's regulator list
|
||||
let key = self.regulators.update(
|
||||
self.regulators.update(
|
||||
|regs| regs.insert(regulator.clone())
|
||||
);
|
||||
|
||||
|
@ -511,7 +559,7 @@ impl Assembly {
|
|||
|subj| subj.regulators()
|
||||
).collect();
|
||||
for regulators in subject_regulators {
|
||||
regulators.update(|regs| regs.insert(key));
|
||||
regulators.update(|regs| regs.push(regulator.clone()));
|
||||
}
|
||||
|
||||
// update the realization when the regulator becomes a constraint, or is
|
||||
|
|
|
@ -13,8 +13,7 @@ use crate::{
|
|||
Element,
|
||||
HalfCurvatureRegulator,
|
||||
InversiveDistanceRegulator,
|
||||
Regulator,
|
||||
RegulatorKey
|
||||
Regulator
|
||||
},
|
||||
specified::SpecifiedValue
|
||||
};
|
||||
|
@ -90,12 +89,12 @@ fn RegulatorInput(regulator: Rc<dyn Regulator>) -> View {
|
|||
}
|
||||
|
||||
pub trait OutlineItem {
|
||||
fn outline_item(self: Rc<Self>, element: Rc<dyn Element>) -> View;
|
||||
fn outline_item(self: Rc<Self>, element: &Rc<dyn Element>) -> View;
|
||||
}
|
||||
|
||||
impl OutlineItem for InversiveDistanceRegulator {
|
||||
fn outline_item(self: Rc<Self>, element: Rc<dyn Element>) -> View {
|
||||
let other_subject_label = if self.subjects[0] == element {
|
||||
fn outline_item(self: Rc<Self>, element: &Rc<dyn Element>) -> View {
|
||||
let other_subject_label = if self.subjects[0] == element.clone() {
|
||||
self.subjects[1].label()
|
||||
} else {
|
||||
self.subjects[0].label()
|
||||
|
@ -112,7 +111,7 @@ impl OutlineItem for InversiveDistanceRegulator {
|
|||
}
|
||||
|
||||
impl OutlineItem for HalfCurvatureRegulator {
|
||||
fn outline_item(self: Rc<Self>, _element: Rc<dyn Element>) -> View {
|
||||
fn outline_item(self: Rc<Self>, _element: &Rc<dyn Element>) -> View {
|
||||
view! {
|
||||
li(class="regulator") {
|
||||
div(class="regulator-label") // for spacing
|
||||
|
@ -124,16 +123,6 @@ impl OutlineItem for HalfCurvatureRegulator {
|
|||
}
|
||||
}
|
||||
|
||||
// a list item that shows a regulator in an outline view of an element
|
||||
#[component(inline_props)]
|
||||
fn RegulatorOutlineItem(regulator_key: RegulatorKey, element: Rc<dyn Element>) -> View {
|
||||
let state = use_context::<AppState>();
|
||||
let regulator = state.assembly.regulators.with(
|
||||
|regs| regs[regulator_key].clone()
|
||||
);
|
||||
regulator.outline_item(element)
|
||||
}
|
||||
|
||||
// a list item that shows an element in an outline view of an assembly
|
||||
#[component(inline_props)]
|
||||
fn ElementOutlineItem(element: Rc<dyn Element>) -> View {
|
||||
|
@ -158,14 +147,10 @@ fn ElementOutlineItem(element: Rc<dyn Element>) -> View {
|
|||
};
|
||||
let regulated = element.regulators().map(|regs| regs.len() > 0);
|
||||
let regulator_list = element.regulators().map(
|
||||
move |elt_reg_keys| elt_reg_keys
|
||||
|regs| regs
|
||||
.clone()
|
||||
.into_iter()
|
||||
.sorted_by_key(
|
||||
|®_key| state.assembly.regulators.with(
|
||||
|regs| regs[reg_key].subjects().len()
|
||||
)
|
||||
)
|
||||
.sorted_by_key(|reg| reg.subjects().len())
|
||||
.collect()
|
||||
);
|
||||
let details_node = create_node_ref();
|
||||
|
@ -223,16 +208,8 @@ fn ElementOutlineItem(element: Rc<dyn Element>) -> View {
|
|||
ul(class="regulators") {
|
||||
Keyed(
|
||||
list=regulator_list,
|
||||
view=move |reg_key| {
|
||||
let element_for_view = element.clone();
|
||||
view! {
|
||||
RegulatorOutlineItem(
|
||||
regulator_key=reg_key,
|
||||
element=element_for_view
|
||||
)
|
||||
}
|
||||
},
|
||||
key=|reg_key| reg_key.clone()
|
||||
view=move |reg| reg.outline_item(&element),
|
||||
key=|reg| reg.serial()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue