allow substitution of variables
This commit is contained in:
parent
8da067fec2
commit
157535b5ff
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
impl Region<Scalar> for Region1 {
|
||||||
fn full() -> Self {
|
|
||||||
Region1::Full
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user