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; @@ -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<T: Clone + fmt::Display, TRegion: Region<T> + fmt::Display> fmt::Display fo @@ -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 {
Self { value, constraints }
}
@ -33,6 +34,16 @@ impl<T: Clone, TRegion: Region<T>> Var<T, TRegion> { @@ -33,6 +34,16 @@ impl<T: Clone, TRegion: Region<T>> Var<T, TRegion> {
&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
}

7
src/main.rs

@ -90,4 +90,11 @@ fn main() { @@ -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);
}

2
src/math/eqn.rs

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

97
src/math/mod.rs

@ -21,10 +21,15 @@ pub type Value = eqn::Expr; @@ -21,10 +21,15 @@ pub type Value = eqn::Expr;
// pub type Rot2 = nalgebra::UnitComplex<Value>;
pub trait Region<T> {
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<T>: GenericRegion {
fn singleton(value: T) -> Self;
// fn intersection(self, other: Self) -> Self;
fn nearest(&self, value: &T) -> Option<T>;
fn contains(&self, value: &T) -> Option<bool>;
@ -53,12 +58,16 @@ impl fmt::Display for Region1 { @@ -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 { @@ -67,13 +76,19 @@ impl Region1 {
other => other,
}
}
}
impl Region<Scalar> 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<Scalar> for Region1 {
fn singleton(value: Scalar) -> Self {
Region1::Singleton(value.into())
}
@ -230,6 +245,14 @@ impl Line2 { @@ -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 { @@ -257,11 +280,42 @@ impl fmt::Display for Region2 {
}
}
impl Region<Point2<Scalar>> 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<Point2<Scalar>> for Region2 {
fn singleton(value: Point2<Scalar>) -> Self {
Region2::Singleton(value.into())
}
@ -312,10 +366,6 @@ impl Region<Point2<Scalar>> for Region2 { @@ -312,10 +366,6 @@ impl Region<Point2<Scalar>> for Region2 {
}
impl Region<Point2<Value>> for Region2 {
fn full() -> Self {
Region2::Full
}
fn singleton(value: Point2<Value>) -> Self {
Region2::Singleton(value)
}
@ -353,15 +403,6 @@ impl Region<Point2<Value>> for Region2 { @@ -353,15 +403,6 @@ impl Region<Point2<Value>> 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 { @@ -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,
}
}
}

12
src/math/vec.rs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
use super::{Scalar, Value};
use super::eqn::Eqns;
use std::ops;
@ -92,8 +93,15 @@ impl<T> Point2<T> { @@ -92,8 +93,15 @@ impl<T> Point2<T> {
impl Point2<Value> {
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),
}
}
}

2
src/relation.rs

@ -1,5 +1,5 @@ @@ -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 {

Loading…
Cancel
Save