From 157535b5ffaa462d67d056cdef09b620619fe449 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Tue, 12 Feb 2019 23:38:26 -0800 Subject: [PATCH] allow substitution of variables --- src/entity.rs | 13 ++++++- src/main.rs | 7 ++++ src/math/eqn.rs | 2 +- src/math/mod.rs | 97 ++++++++++++++++++++++++++++++++----------------- src/math/vec.rs | 12 +++++- src/relation.rs | 2 +- 6 files changed, 95 insertions(+), 38 deletions(-) diff --git a/src/entity.rs b/src/entity.rs index 8b6e6a5..7e2dae5 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::rc::Rc; use crate::math::{Point2, Region, Region1, Region2, Scalar}; +use crate::math::eqn::{Eqns}; use std::fmt; #[derive(Clone, Copy, Debug)] @@ -16,7 +17,7 @@ impl + fmt::Display> fmt::Display fo } } -impl> Var { +impl + Clone> Var { pub fn new(value: T, constraints: TRegion) -> Self { Self { value, constraints } } @@ -33,6 +34,16 @@ impl> Var { &self.value } + pub fn evaluate_with(&mut self, eqns: &Eqns) -> bool { + self.constraints = self.constraints.clone().evaluate_with(eqns).simplify(); + if let Some(n) = self.constraints.nearest(&self.value) { + self.value = n; + true + } else { + false + } + } + pub fn constraints(&self) -> &TRegion { &self.constraints } diff --git a/src/main.rs b/src/main.rs index 88a0a9a..1886d16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,4 +90,11 @@ fn main() { } else { println!("All constraints have been solved") } + let e1 = eqn::Eqn::new(eqn::Expr::Unkn(u1), eqn::Expr::Const(1.)); + let e2 = eqn::Eqn::new(eqn::Expr::Unkn(u2), eqn::Expr::Const(1.)); + let eqns = eqn::Eqns(vec![e1, e2]); + for p in &mut points { + p.borrow_mut().pos.evaluate_with(&eqns); + } + print_points(&points); } diff --git a/src/math/eqn.rs b/src/math/eqn.rs index 55090b6..375f88a 100644 --- a/src/math/eqn.rs +++ b/src/math/eqn.rs @@ -588,7 +588,7 @@ impl fmt::Display for Eqn { } #[derive(Clone, Debug, PartialEq)] -pub struct Eqns(Vec); +pub struct Eqns(pub Vec); impl Unknowns for Eqns { fn unknowns(&self) -> UnknownSet { diff --git a/src/math/mod.rs b/src/math/mod.rs index e51e087..719621d 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -21,10 +21,15 @@ pub type Value = eqn::Expr; // pub type Rot2 = nalgebra::UnitComplex; -pub trait Region { +pub trait GenericRegion { fn full() -> Self; + fn intersection(self, other: Self) -> Self; + fn simplify(self) -> Self; + fn evaluate_with(self, eqns: &eqn::Eqns) -> Self; +} + +pub trait Region: GenericRegion { fn singleton(value: T) -> Self; - // fn intersection(self, other: Self) -> Self; fn nearest(&self, value: &T) -> Option; fn contains(&self, value: &T) -> Option; @@ -53,12 +58,16 @@ impl fmt::Display for Region1 { } } -impl Region1 { - pub fn intersection(self, other: Region1) -> Self { +impl GenericRegion for Region1 { + fn intersection(self, other: Region1) -> Self { Region1::Intersection(Box::new(self), Box::new(other)) } - pub fn simplify(self) -> Self { + fn full() -> Self { + Region1::Full + } + + fn simplify(self) -> Self { use Region1::*; match self { Singleton(n) => Singleton(n.simplify()), @@ -67,13 +76,19 @@ impl Region1 { other => other, } } -} -impl Region for Region1 { - fn full() -> Self { - Region1::Full + fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + use Region1::*; + match self { + Singleton(n) => Singleton(n.evaluate_with(eqns)), + Range(l, u) => Range(l.evaluate_with(eqns), u.evaluate_with(eqns)), + Intersection(r1, r2) => r1.evaluate_with(eqns).intersection(r2.evaluate_with(eqns)), + other => other, + } } +} +impl Region for Region1 { fn singleton(value: Scalar) -> Self { Region1::Singleton(value.into()) } @@ -230,6 +245,14 @@ impl Line2 { } Region2::Line(new_l) } + + pub fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + Line2 { + start: self.start.evaluate_with(eqns), + dir: self.dir, + extent: self.extent.evaluate_with(eqns), + } + } } #[derive(Clone, Debug)] @@ -257,11 +280,42 @@ impl fmt::Display for Region2 { } } -impl Region> for Region2 { +impl GenericRegion for Region2 { fn full() -> Self { Region2::Full } + fn intersection(self, other: Self) -> Self { + use Region2::*; + match (self, other) { + (Empty, _) | (_, Empty) => Empty, + (Full, r) | (r, Full) => r, + (r1, r2) => Intersection(Box::new(r1), Box::new(r2)), + } + } + + fn simplify(self) -> Region2 { + use Region2::*; + match self { + Singleton(n) => Singleton(n.simplify()), + Line(l) => l.simplify(), + Intersection(r1, r2) => r1.simplify().intersect(r2.simplify()), + other => other, + } + } + + fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + use Region2::*; + match self { + Singleton(n) => Singleton(n.evaluate_with(eqns)), + Line(l) => Line(l.evaluate_with(eqns)), + Intersection(r1, r2) => r1.evaluate_with(eqns).intersection(r2.evaluate_with(eqns)), + other => other, + } + } +} + +impl Region> for Region2 { fn singleton(value: Point2) -> Self { Region2::Singleton(value.into()) } @@ -312,10 +366,6 @@ impl Region> for Region2 { } impl Region> for Region2 { - fn full() -> Self { - Region2::Full - } - fn singleton(value: Point2) -> Self { Region2::Singleton(value) } @@ -353,15 +403,6 @@ impl Region> for Region2 { } impl Region2 { - pub fn intersection(self, other: Self) -> Self { - use Region2::*; - match (self, other) { - (Empty, _) | (_, Empty) => Empty, - (Full, r) | (r, Full) => r, - (r1, r2) => Intersection(Box::new(r1), Box::new(r2)), - } - } - /* pub fn union(r1: Region2, r2: Region2) -> Region2 { use Region2::*; @@ -402,14 +443,4 @@ impl Region2 { (r1, r2) => Intersection(Box::new(r1), Box::new(r2)), } } - - pub fn simplify(self) -> Region2 { - use Region2::*; - match self { - Singleton(n) => Singleton(n.simplify()), - Line(l) => l.simplify(), - Intersection(r1, r2) => r1.simplify().intersect(r2.simplify()), - other => other, - } - } } diff --git a/src/math/vec.rs b/src/math/vec.rs index 753b948..2d7ee33 100644 --- a/src/math/vec.rs +++ b/src/math/vec.rs @@ -1,4 +1,5 @@ use super::{Scalar, Value}; +use super::eqn::Eqns; use std::ops; @@ -92,8 +93,15 @@ impl Point2 { impl Point2 { pub fn simplify(self) -> Self { Self { - x: self.x.distribute().simplify().distribute().simplify(), - y: self.y.distribute().simplify().distribute().simplify(), + x: self.x.distribute().simplify(), + y: self.y.distribute().simplify(), + } + } + + pub fn evaluate_with(self, eqns: &Eqns) -> Self { + Self { + x: self.x.evaluate_with(eqns), + y: self.y.evaluate_with(eqns), } } } diff --git a/src/relation.rs b/src/relation.rs index c84b788..8cb77ce 100644 --- a/src/relation.rs +++ b/src/relation.rs @@ -1,5 +1,5 @@ use crate::entity::{Point as PointEntity, PointRef}; -use crate::math::{Line2, Vec2, Point2, Region1, Region2, Rot2, Scalar, Value, Region}; +use crate::math::{Line2, Vec2, Point2, Region1, Region2, Rot2, Scalar, Value, GenericRegion}; #[derive(Clone, Copy, Debug, PartialEq)] pub enum ResolveResult {