Browse Source

allow substitution of variables

eqn_relations
Alex Mikhalev 6 years ago
parent
commit
157535b5ff
  1. 13
      src/entity.rs
  2. 7
      src/main.rs
  3. 2
      src/math/eqn.rs
  4. 97
      src/math/mod.rs
  5. 12
      src/math/vec.rs
  6. 2
      src/relation.rs

13
src/entity.rs

@ -2,6 +2,7 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use crate::math::{Point2, Region, Region1, Region2, Scalar}; use crate::math::{Point2, Region, Region1, Region2, Scalar};
use crate::math::eqn::{Eqns};
use std::fmt; use std::fmt;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -16,7 +17,7 @@ impl<T: Clone + fmt::Display, TRegion: Region<T> + fmt::Display> fmt::Display fo
} }
} }
impl<T: Clone, TRegion: Region<T>> Var<T, TRegion> { impl<T: Clone, TRegion: Region<T> + Clone> Var<T, TRegion> {
pub fn new(value: T, constraints: TRegion) -> Self { pub fn new(value: T, constraints: TRegion) -> Self {
Self { value, constraints } Self { value, constraints }
} }
@ -33,6 +34,16 @@ impl<T: Clone, TRegion: Region<T>> Var<T, TRegion> {
&self.value &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 { pub fn constraints(&self) -> &TRegion {
&self.constraints &self.constraints
} }

7
src/main.rs

@ -90,4 +90,11 @@ fn main() {
} else { } else {
println!("All constraints have been solved") 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);
} }

2
src/math/eqn.rs

@ -588,7 +588,7 @@ impl fmt::Display for Eqn {
} }
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct Eqns(Vec<Eqn>); pub struct Eqns(pub Vec<Eqn>);
impl Unknowns for Eqns { impl Unknowns for Eqns {
fn unknowns(&self) -> UnknownSet { fn unknowns(&self) -> UnknownSet {

97
src/math/mod.rs

@ -21,10 +21,15 @@ pub type Value = eqn::Expr;
// pub type Rot2 = nalgebra::UnitComplex<Value>; // pub type Rot2 = nalgebra::UnitComplex<Value>;
pub trait Region<T> { pub trait GenericRegion {
fn full() -> Self; fn full() -> Self;
fn intersection(self, other: Self) -> Self;
fn simplify(self) -> Self;
fn evaluate_with(self, eqns: &eqn::Eqns) -> Self;
}
pub trait Region<T>: GenericRegion {
fn singleton(value: T) -> Self; fn singleton(value: T) -> Self;
// fn intersection(self, other: Self) -> Self;
fn nearest(&self, value: &T) -> Option<T>; fn nearest(&self, value: &T) -> Option<T>;
fn contains(&self, value: &T) -> Option<bool>; fn contains(&self, value: &T) -> Option<bool>;
@ -53,12 +58,16 @@ impl fmt::Display for Region1 {
} }
} }
impl Region1 { impl GenericRegion for Region1 {
pub fn intersection(self, other: Region1) -> Self { fn intersection(self, other: Region1) -> Self {
Region1::Intersection(Box::new(self), Box::new(other)) Region1::Intersection(Box::new(self), Box::new(other))
} }
pub fn simplify(self) -> Self { fn full() -> Self {
Region1::Full
}
fn simplify(self) -> Self {
use Region1::*; use Region1::*;
match self { match self {
Singleton(n) => Singleton(n.simplify()), Singleton(n) => Singleton(n.simplify()),
@ -67,13 +76,19 @@ impl Region1 {
other => other, other => other,
} }
} }
}
impl Region<Scalar> for Region1 { fn evaluate_with(self, eqns: &eqn::Eqns) -> Self {
fn full() -> Self { use Region1::*;
Region1::Full 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<Scalar> for Region1 {
fn singleton(value: Scalar) -> Self { fn singleton(value: Scalar) -> Self {
Region1::Singleton(value.into()) Region1::Singleton(value.into())
} }
@ -230,6 +245,14 @@ impl Line2 {
} }
Region2::Line(new_l) 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)] #[derive(Clone, Debug)]
@ -257,11 +280,42 @@ impl fmt::Display for Region2 {
} }
} }
impl Region<Point2<Scalar>> for Region2 { impl GenericRegion for Region2 {
fn full() -> Self { fn full() -> Self {
Region2::Full 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<Point2<Scalar>> for Region2 {
fn singleton(value: Point2<Scalar>) -> Self { fn singleton(value: Point2<Scalar>) -> Self {
Region2::Singleton(value.into()) Region2::Singleton(value.into())
} }
@ -312,10 +366,6 @@ impl Region<Point2<Scalar>> for Region2 {
} }
impl Region<Point2<Value>> for Region2 { impl Region<Point2<Value>> for Region2 {
fn full() -> Self {
Region2::Full
}
fn singleton(value: Point2<Value>) -> Self { fn singleton(value: Point2<Value>) -> Self {
Region2::Singleton(value) Region2::Singleton(value)
} }
@ -353,15 +403,6 @@ impl Region<Point2<Value>> for Region2 {
} }
impl 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 { pub fn union(r1: Region2, r2: Region2) -> Region2 {
use Region2::*; use Region2::*;
@ -402,14 +443,4 @@ impl Region2 {
(r1, r2) => Intersection(Box::new(r1), Box::new(r2)), (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,
}
}
} }

12
src/math/vec.rs

@ -1,4 +1,5 @@
use super::{Scalar, Value}; use super::{Scalar, Value};
use super::eqn::Eqns;
use std::ops; use std::ops;
@ -92,8 +93,15 @@ impl<T> Point2<T> {
impl Point2<Value> { impl Point2<Value> {
pub fn simplify(self) -> Self { pub fn simplify(self) -> Self {
Self { Self {
x: self.x.distribute().simplify().distribute().simplify(), x: self.x.distribute().simplify(),
y: self.y.distribute().simplify().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),
} }
} }
} }

2
src/relation.rs

@ -1,5 +1,5 @@
use crate::entity::{Point as PointEntity, PointRef}; 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)] #[derive(Clone, Copy, Debug, PartialEq)]
pub enum ResolveResult { pub enum ResolveResult {

Loading…
Cancel
Save