use nalgebra::DVector; use rustc_hash::FxHashMap; use slab::Slab; use std::collections::BTreeSet; use sycamore::prelude::*; #[derive(Clone, PartialEq)] pub struct Element { pub id: String, pub label: String, pub color: [f32; 3], pub rep: DVector, pub constraints: BTreeSet } #[derive(Clone)] pub struct Constraint { pub args: (usize, usize), pub rep: f64 } // a complete, view-independent description of an assembly #[derive(Clone)] pub struct Assembly { // elements and constraints pub elements: Signal>, pub constraints: Signal>, // indexing pub elements_by_id: Signal> } impl Assembly { pub fn new() -> Assembly { Assembly { elements: create_signal(Slab::new()), constraints: create_signal(Slab::new()), elements_by_id: create_signal(FxHashMap::default()) } } pub fn insert_new_element(&self) { // find the next unused identifier in the default sequence let mut id_num = 1; let mut id = format!("sphere{}", id_num); while self.elements_by_id.with( |elts_by_id| elts_by_id.contains_key(&id) ) { id_num += 1; id = format!("sphere{}", id_num); } // create and insert a new element let elt = Element { id: id.clone(), label: format!("Sphere {}", id_num), color: [0.75_f32, 0.75_f32, 0.75_f32], rep: DVector::::from_column_slice(&[0.0, 0.0, 0.0, 0.5, -0.5]), constraints: BTreeSet::default() }; let key = self.elements.update(|elts| elts.insert(elt)); self.elements_by_id.update(|elts_by_id| elts_by_id.insert(id, key)); } pub fn insert_constraint(&self, constraint: Constraint) { let args = constraint.args; let key = self.constraints.update(|csts| csts.insert(constraint)); self.elements.update(|elts| { elts[args.0].constraints.insert(key); elts[args.1].constraints.insert(key); }) } }