Curvature regulators #80
1 changed files with 21 additions and 15 deletions
|
@ -31,6 +31,10 @@ pub type ElementColor = [f32; 3];
|
||||||
// each assembly has a key that identifies it within the sesssion
|
// each assembly has a key that identifies it within the sesssion
|
||||||
static NEXT_ELEMENT_SERIAL: AtomicU64 = AtomicU64::new(0);
|
static NEXT_ELEMENT_SERIAL: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
pub trait ProblemPoser {
|
||||||
|
fn pose(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
@ -123,8 +127,10 @@ impl Element {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn write_to_problem(&self, problem: &mut ConstraintProblem) {
|
|
||||||
|
impl ProblemPoser for Element {
|
||||||
|
fn pose(&self, problem: &mut ConstraintProblem, _elts: &Slab<Element>) {
|
||||||
if let Some(index) = self.column_index {
|
if let Some(index) = self.column_index {
|
||||||
problem.gram.push_sym(index, index, 1.0);
|
problem.gram.push_sym(index, index, 1.0);
|
||||||
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
problem.guess.set_column(index, &self.representation.get_clone_untracked());
|
||||||
|
@ -134,14 +140,10 @@ impl Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Regulator: OutlineItem {
|
pub trait Regulator: ProblemPoser + OutlineItem {
|
||||||
// get information
|
|
||||||
fn subjects(&self) -> Vec<ElementKey>;
|
fn subjects(&self) -> Vec<ElementKey>;
|
||||||
fn measurement(&self) -> ReadSignal<f64>;
|
fn measurement(&self) -> ReadSignal<f64>;
|
||||||
fn set_point(&self) -> Signal<SpecifiedValue>;
|
fn set_point(&self) -> Signal<SpecifiedValue>;
|
||||||
|
|
||||||
// write problem data
|
|
||||||
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProductRegulator {
|
pub struct ProductRegulator {
|
||||||
|
@ -162,8 +164,10 @@ impl Regulator for ProductRegulator {
|
||||||
fn set_point(&self) -> Signal<SpecifiedValue> {
|
fn set_point(&self) -> Signal<SpecifiedValue> {
|
||||||
self.set_point
|
self.set_point
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
|
||||||
|
impl ProblemPoser for ProductRegulator {
|
||||||
|
fn pose(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
||||||
self.set_point.with_untracked(|set_pt| {
|
self.set_point.with_untracked(|set_pt| {
|
||||||
if let Some(val) = set_pt.value {
|
if let Some(val) = set_pt.value {
|
||||||
let subject_column_indices = self.subjects.map(
|
let subject_column_indices = self.subjects.map(
|
||||||
|
@ -197,8 +201,10 @@ impl Regulator for HalfCurvatureRegulator {
|
||||||
fn set_point(&self) -> Signal<SpecifiedValue> {
|
fn set_point(&self) -> Signal<SpecifiedValue> {
|
||||||
self.set_point
|
self.set_point
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn write_to_problem(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
|
||||||
|
impl ProblemPoser for HalfCurvatureRegulator {
|
||||||
|
fn pose(&self, problem: &mut ConstraintProblem, elts: &Slab<Element>) {
|
||||||
self.set_point.with_untracked(|set_pt| {
|
self.set_point.with_untracked(|set_pt| {
|
||||||
if let Some(val) = set_pt.value {
|
if let Some(val) = set_pt.value {
|
||||||
if let Some(col) = elts[self.subject].column_index {
|
if let Some(col) = elts[self.subject].column_index {
|
||||||
|
@ -441,11 +447,11 @@ impl Assembly {
|
||||||
let problem = self.elements.with_untracked(|elts| {
|
let problem = self.elements.with_untracked(|elts| {
|
||||||
let mut problem_to_be = ConstraintProblem::new(elts.len());
|
let mut problem_to_be = ConstraintProblem::new(elts.len());
|
||||||
for (_, elt) in elts {
|
for (_, elt) in elts {
|
||||||
elt.write_to_problem(&mut problem_to_be);
|
elt.pose(&mut problem_to_be, elts);
|
||||||
}
|
}
|
||||||
self.regulators.with_untracked(|regs| {
|
self.regulators.with_untracked(|regs| {
|
||||||
glen marked this conversation as resolved
Outdated
|
|||||||
for (_, reg) in regs {
|
for (_, reg) in regs {
|
||||||
reg.write_to_problem(&mut problem_to_be, elts);
|
reg.pose(&mut problem_to_be, elts);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
problem_to_be
|
problem_to_be
|
||||||
|
@ -621,7 +627,7 @@ mod tests {
|
||||||
"Sphere".to_string(),
|
"Sphere".to_string(),
|
||||||
[1.0_f32, 1.0_f32, 1.0_f32],
|
[1.0_f32, 1.0_f32, 1.0_f32],
|
||||||
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
engine::sphere(0.0, 0.0, 0.0, 1.0)
|
||||||
).write_to_problem(&mut ConstraintProblem::new(1));
|
).pose(&mut ConstraintProblem::new(1), &Slab::new());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +651,7 @@ mod tests {
|
||||||
subjects: subjects,
|
subjects: subjects,
|
||||||
measurement: create_memo(|| 0.0),
|
measurement: create_memo(|| 0.0),
|
||||||
set_point: create_signal(SpecifiedValue::try_from("0.0".to_string()).unwrap())
|
set_point: create_signal(SpecifiedValue::try_from("0.0".to_string()).unwrap())
|
||||||
}.write_to_problem(&mut ConstraintProblem::new(2), &elts);
|
}.pose(&mut ConstraintProblem::new(2), &elts);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue
It's OK with me if you just call the interior variable
problem
even though it's being returned out to an exterior variable namedproblem
-- I don't think it would reduce clarity. Not necessary to change, just wanted to make sure you knew that I don't have any issue with using the same name in a case like this. And I do think that concise variable names are definitely helpful.Good to know. For now, I think it's worth clearly distinguishing the interior "builder" variable and the exterior "storage" variable, because they have some differences in usage: for example, the builder variable is mutable, and the storage variable isn't. However, I'd be fine with switching to the convention of using the same name for both.
Well, we are either going to have the convention of using the same variable name inside and outside, or always distinguishing the names. We're not going to do it one way in some places and the other way in other places. I like the "same name" convention better -- more concise with no loss in clarity. So if you are not against that change in convention, please just go ahead and change this instance to conform. We can discuss (A,B,C) from the other thread in person.
I've switched to the same-name convention in commit
955220c
.Great, I see that, and this code is fine. It occurs to me that the organization that would be used for this code in some languages would be to have the
problem = ConstraintProblem::new(...)
outside the closure in self.elements.with_untracked(...) and then have some sort of reference to the problem be visible inside that closure. I suppose that is possible in Rust as well. If you think it's cleaner/clearer to organize it that way, feel free to refactor this, but also feel free to leave it as is if you prefer. In the latter case, please just resolve this thread.I chose this organization so that
problem
could be immutable in the scope where it's used, and only mutable in the scope where it's created.