From ce4a662847da4f40e6cf4e9a1795ad614289d147 Mon Sep 17 00:00:00 2001 From: Alex Mikhalev Date: Fri, 18 Oct 2019 14:02:00 -0700 Subject: [PATCH] got more stuff to work? --- src/entity.rs | 4 +- src/main.rs | 2 +- src/math/eqn.rs | 301 +++++++++++++++++++++++++++++++++------------ src/math/expr.rs | 222 +++++++++++++++++++++++++-------- src/math/region.rs | 44 +++---- src/math/vec.rs | 34 ++--- src/relation.rs | 8 +- 7 files changed, 435 insertions(+), 180 deletions(-) diff --git a/src/entity.rs b/src/entity.rs index 3f10f8b..56caabc 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -44,7 +44,7 @@ impl + Clone> Constrainable { } pub fn resolve_with(&mut self, eqns: &Eqns) -> bool { - let resolved_constraints = self.constraints.clone().evaluate_with(eqns).simplify(); + let resolved_constraints = self.constraints.clone().substitute(eqns).simplify(); if let Some(n) = resolved_constraints.nearest(&self.value) { self.value = n; true @@ -54,7 +54,7 @@ impl + Clone> Constrainable { } pub fn evaluate_with(&mut self, eqns: &Eqns) -> bool { - self.constraints = self.constraints.clone().evaluate_with(eqns).simplify(); + self.constraints = self.constraints.clone().substitute(eqns).simplify(); if let Some(n) = self.constraints.nearest(&self.value) { self.value = n; true diff --git a/src/main.rs b/src/main.rs index f6225bc..d337d35 100644 --- a/src/main.rs +++ b/src/main.rs @@ -103,7 +103,7 @@ fn main() { } let e1 = Eqn::new(Expr::Unkn(u1), Expr::Const(1.)); let e2 = Eqn::new(Expr::Unkn(u2), Expr::Const(1.)); - let eqns = Eqns(vec![e1, e2]); + let eqns = Eqns(vec![e1, e2].into()); for p in &mut points { p.borrow_mut().resolve_with(&eqns); } diff --git a/src/math/eqn.rs b/src/math/eqn.rs index fbbcb99..aa1362b 100644 --- a/src/math/eqn.rs +++ b/src/math/eqn.rs @@ -1,8 +1,10 @@ +use std::borrow::{Borrow, Cow}; +use std::collections::btree_map::Entry; +use std::collections::BTreeMap; use std::fmt; use super::expr::Expr; use super::unknown::*; -use super::Scalar; use crate::math::expr::Expr::*; #[derive(Clone, Debug, PartialEq)] @@ -43,62 +45,71 @@ impl Eqn { Eqn(self.0.simplify(), self.1.simplify()) } - pub fn solve(&self, for_u: Unknown) -> Option { - use Expr::*; - if !self.has_unknown(for_u) { - return None; - } - trace!("solve: {}", self); - let (l, r) = ( - self.0 - .clone().distribute() - .simplify(), - self.1 - .clone().distribute() - .simplify(), - ); - let (mut l, mut r) = ord_by_unkn(l, r, for_u)?; - loop { - trace!("solve iter: {} == {}", l, r); - let (new_l, new_r): (Expr, Expr) = match l { - Unkn(u) => return if u == for_u { Some(r.simplify()) } else { None }, - Sum(es) => { - let (us, not_us): (Vec<_>, Vec<_>) = - es.into_iter().partition(|e| e.has_unknown(for_u)); - if us.len() != 1 { - return None; - } - ( - Sum(us).simplify(), - Expr::new_minus(r, Sum(not_us)).simplify(), - ) + pub fn substitute(self, eqns: &Eqns) -> Eqn { + Self(self.0.substitute(eqns), self.1.substitute(eqns)) + } +} + +pub fn solve_eqn(eqn: &Eqn, for_u: Unknown) -> Option { + use Expr::*; + if !eqn.has_unknown(for_u) { + return None; + } + trace!("solve: {}", eqn); + let (mut l, mut r) = (eqn.0.clone().distribute().simplify(), eqn.1.clone().distribute().simplify()); + if l == r { + return None + }; + l = (l - r).distribute().simplify(); + r = Expr::Const(0.); + loop { + trace!("solve iter: {} == {}", l, r); + let (new_l, new_r): (Expr, Expr) = match l { + Unkn(u) => return if u == for_u { Some(r.simplify()) } else { None }, + Sum(es) => { + let (us, not_us): (Vec<_>, Vec<_>) = + es.into_iter().partition(|e| e.has_unknown(for_u)); + if us.len() != 1 { + return None; } - Product(es) => { - let (us, not_us): (Vec<_>, Vec<_>) = - es.into_iter().partition(|e| e.has_unknown(for_u)); - if us.len() != 1 { - return None; - } - ( - Product(us).simplify(), - Expr::new_div(r, Product(not_us)).simplify(), - ) + ( + us.into_iter().next().unwrap(), + if not_us.len() == 0 { + r + } else { + Expr::new_minus(r, Sum(not_us)) + }, + ) + } + Product(es) => { + let (us, not_us): (Vec<_>, Vec<_>) = + es.into_iter().partition(|e| e.has_unknown(for_u)); + if us.len() != 1 { + return None; } - Neg(v) => (*v, Expr::new_neg(r)), - Div(num, den) => { - let (nu, du) = (num.has_unknown(for_u), den.has_unknown(for_u)); - match (nu, du) { - (true, false) => (*num, Expr::new_product(r, *den)), - (false, true) => (Expr::new_product(r, *den), *num), - (true, true) => return None, // TODO: simplify - (false, false) => return None, - } + ( + us.into_iter().next().unwrap(), + if not_us.len() == 0 { + r + } else { + Expr::new_div(r, Product(not_us)) + }, + ) + } + Neg(v) => (*v, Expr::new_neg(r)), + Div(num, den) => { + let (nu, du) = (num.has_unknown(for_u), den.has_unknown(for_u)); + match (nu, du) { + (true, false) => (*num, Expr::new_product(r, *den)), + (false, true) => (Expr::new_product(r, *den), *num), + (true, true) => return None, // TODO: simplify + (false, false) => return None, } - Const(_) => return None, - }; - l = new_l; - r = new_r; - } + } + Const(_) => return None, + }; + l = new_l.distribute().simplify(); + r = new_r.distribute().simplify(); } } @@ -109,9 +120,9 @@ impl fmt::Display for Eqn { } #[derive(Clone, Debug, PartialEq)] -pub struct Eqns(pub Vec); +pub struct Eqns<'a>(pub Cow<'a, [Eqn]>); -impl Unknowns for Eqns { +impl<'a> Unknowns for Eqns<'a> { fn unknowns(&self) -> UnknownSet { self.0.iter().flat_map(|eqn: &Eqn| eqn.unknowns()).collect() } @@ -123,11 +134,11 @@ impl Unknowns for Eqns { } } -impl fmt::Display for Eqns { +impl<'a> fmt::Display for Eqns<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{{ "); + write!(f, "{{ ")?; let mut first = true; - for eq in &self.0 { + for eq in (&self.0 as &Borrow<[Eqn]>).borrow() { if first { first = false; } else { @@ -139,8 +150,91 @@ impl fmt::Display for Eqns { } } +pub fn solve_eqns<'a>(eqns: &Eqns<'a>, for_vars: &[Unknown]) -> Option> { + let eqn_unknowns = eqns.unknowns(); + let has_all_vars = for_vars.iter().all(|u| eqn_unknowns.contains(u)); + if !has_all_vars { + // return None; + } + let mut var_sols = BTreeMap::>::new(); + for u in &eqn_unknowns { + for eq in (&eqns.0 as &Borrow<[Eqn]>).borrow() { + let sol = solve_eqn(eq, *u); + if let Some(sol) = sol { + //println!("sol {0} -> {2} from {1}", u, eq, sol); + match var_sols.entry(*u) { + Entry::Vacant(vac) => { + vac.insert(vec![sol]); + } + Entry::Occupied(mut occ) => { + if !occ.get().contains(&sol) { + occ.get_mut().push(sol); + }; + } + }; + } else { + //println!("no sol for {0} in {1}", u, eq); + } + } + } + let mut new_eqns: Vec = Vec::new(); + let mut all_have_sols = true; + for e in &var_sols { + let mut has_sol = false; + let mut last_expr = Unkn(*e.0); + println!("{}", e.0); + for s in e.1 { + println!(" == {}", s); + new_eqns.push(Eqn(last_expr, s.clone())); + last_expr = s.clone(); + match s { + Const(_) => { has_sol = true; } + _ => {} + }; + } + if !has_sol { + all_have_sols = false + } + } + let mut new_eqns = Eqns(new_eqns.into()); + println!("new eqns: {}", new_eqns); + if all_have_sols { + return Some(new_eqns); + } + return solve_eqns(&new_eqns, for_vars); + /* + let mut more_eqns: Vec = Vec::new(); + let mut new_orig_eqns = eqns.clone(); + for eq in new_orig_eqns.0.to_mut() { + let u = match eq.0 { + Unkn(u) => u, + _ => continue, + }; + let my_new_eqns = Eqns( + new_eqns + .0 + .iter() + .cloned() + .filter(|e| !e.1.has_unknown(u)) + .collect::>() + .into(), + ); + let r = + eq.1.clone() + .substitute(&my_new_eqns) + .distribute() + .simplify(); + more_eqns.push(Eqn(Unkn(u), r)); + } + let mut more_eqns = Eqns(more_eqns.into()); + println!("more eqns: {}", more_eqns); + */ + None +} + #[cfg(test)] mod tests { + use super::super::Scalar; use super::*; #[test] @@ -171,7 +265,7 @@ mod tests { } #[test] - fn test_eqn_solve() { + fn test_solve_eqn() { use Expr::*; let _ = env_logger::try_init(); let u1 = Unknown(1); @@ -179,22 +273,22 @@ mod tests { let e2 = Const(1.); let eqn = Eqn(e1.clone(), e2.clone()); - assert_eq!(eqn.solve(u1), Some(Const(1.))); + assert_eq!(solve_eqn(&eqn, u1), Some(Const(1.))); let eqn = Eqn(e2.clone(), e1.clone()); - assert_eq!(eqn.solve(u1), Some(Const(1.))); + assert_eq!(solve_eqn(&eqn, u1), Some(Const(1.))); let e3: Expr = Expr::from(1.) + 1. + 2.; let eqn = Eqn(e1.clone(), e3.clone()); - assert_eq!(eqn.solve(u1), Some(Const(4.))); + assert_eq!(solve_eqn(&eqn, u1), Some(Const(4.))); let e3 = Expr::from(1.) - 1.; let eqn = Eqn(e1.clone(), e3.clone()); - assert_eq!(eqn.solve(u1), Some(Const(0.))); + assert_eq!(solve_eqn(&eqn, u1), Some(Const(0.))); let e1 = Expr::from(2.) / (Expr::from(1.) - 4.); let e2 = Expr::new_minus(Const(1.), Unkn(u1)); let eqn = Eqn(e1, e2); info!("eqn: {} => {}", eqn, eqn.clone().simplify()); - let e = eqn.solve(u1).unwrap(); + let e = solve_eqn(&eqn, u1).unwrap(); assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), 5. / 3.)); @@ -208,7 +302,7 @@ mod tests { e2.clone().simplify() ); let eqn = Eqn(e1, e2); - let e = eqn.solve(u1).unwrap(); + let e = solve_eqn(&eqn, u1).unwrap(); assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), -6.)); @@ -229,7 +323,7 @@ mod tests { e2.clone().distribute().simplify() ); let eqn = Eqn(e1, e2); - let e = eqn.solve(u1).unwrap(); + let e = solve_eqn(&eqn, u1).unwrap(); assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), -8.)); @@ -240,31 +334,82 @@ mod tests { e1, e2, e1.clone().distribute().simplify(), - e2.clone().distribute().simplify().simplify() + e2.clone().distribute().simplify() ); let eqn = Eqn(e1, e2); - let e = eqn.solve(u1).unwrap(); + let e = solve_eqn(&eqn, u1).unwrap(); assert!(const_expr(e.clone()).is_some()); assert!(relative_eq!(const_expr(e.clone()).unwrap(), -9.)); } #[test] - fn test_eqns_solve() { - use Expr::*; + fn test_solve_eqn2() { + let _ = env_logger::try_init(); + + let u1 = Unknown(1); + let e1 = Expr::Unkn(u1); + let e2 = (u1 * 2.) - 2.; + info!( + "e1==e2: {}=={} => {}=={}", + e1, + e2, + e1.clone().distribute().simplify(), + e2.clone().distribute().simplify(), + ); + let eqn = Eqn(e1, e2); + let e = solve_eqn(&eqn, u1).unwrap(); + assert!(const_expr(e.clone()).is_some()); + assert!(relative_eq!(const_expr(e.clone()).unwrap(), 2.)); + } + + #[test] + fn test_solve_equations() { + let _ = env_logger::try_init(); + + use Expr::*; + + let x = Unknown(1); + let y = Unknown(2); + let t1 = Unknown(3); + let t2 = Unknown(4); + + let eqns = Eqns( + vec![ + Eqn::new(x.into(), t1 * 1.), + Eqn::new(y.into(), t1 / 2.), + Eqn::new(x.into(), Const(0.0) + t2 / 2.), + Eqn::new(y.into(), t2 / 2.), + ] + .into(), + ); + println!("eqns: {}", eqns); + let sol = solve_eqns(&eqns, &[t1, t2]).unwrap(); + println!("sols: {}", sol); + } + + #[test] + fn test_solve_equations2() { + let _ = env_logger::try_init(); + + use Expr::*; let x = Unknown(1); let y = Unknown(2); let t1 = Unknown(3); let t2 = Unknown(4); - let eqns = Eqns(vec![ - Eqn::new(x.into(), t1 / 2.), - Eqn::new(y.into(), t1 / 2.), - Eqn::new(x.into(), Const(1.0) - t2 / 2.), - Eqn::new(y.into(), t2 / 2.), - ]); + let eqns = Eqns( + vec![ + Eqn::new(x.into(), t1 * 1.), + Eqn::new(y.into(), t1 / 2.), + Eqn::new(x.into(), Const(1.0) + t2 / 1.), + Eqn::new(y.into(), t2 / 2.), + ] + .into(), + ); println!("eqns: {}", eqns); - let sol = eqns.solve(&[t1, t2]).unwrap(); + let sol = solve_eqns(&eqns, &[t1, t2]).unwrap(); + println!("sols: {}", sol); } } diff --git a/src/math/expr.rs b/src/math/expr.rs index 692c5dd..e6c410f 100644 --- a/src/math/expr.rs +++ b/src/math/expr.rs @@ -1,9 +1,11 @@ +use std::borrow::Borrow; use std::collections::BTreeMap; use std::fmt; -use super::eqn::Eqns; +use super::eqn::{Eqn, Eqns}; use super::unknown::{Unknown, UnknownSet, Unknowns}; use super::Scalar; +use std::f64::NAN; #[derive(Clone, Debug, PartialEq)] pub enum Expr { @@ -29,9 +31,9 @@ impl Unknowns for Exprs { } } -fn write_separated_exprs(es: &Exprs, f: &mut fmt::Formatter, sep: &str) -> fmt::Result { - let mut is_first = true; +fn write_separated_exprs(es: &[Expr], f: &mut fmt::Formatter, sep: &str) -> fmt::Result { write!(f, "(")?; + let mut is_first = es.len() > 1; for e in es { if is_first { is_first = false; @@ -66,16 +68,24 @@ fn sum_fold(l: Expr, r: Expr) -> Expr { if comm.is_empty() { Expr::new_sum(Product(l), Product(r)) } else { - Expr::new_product(Product(comm), Expr::new_sum(Product(l), Product(r))) + Expr::new_product(Product(comm), Expr::new_sum(Product(l), Product(r)).collapse()) } } (Product(mut l), r) | (r, Product(mut l)) => { let comm = remove_term(&mut l, &r); match comm { - Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))), + Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))).collapse(), None => Expr::new_sum(Product(l), r), } } + (Div(box ln, box ld), Div(box rn, box rd)) => { + if ld == rd { + Expr::new_div(Expr::new_sum(ln, rn), ld).collapse() + } else { + Expr::new_div(Expr::new_sum(Expr::new_product(ln, rd.clone()), Expr::new_product(rn, ld.clone())), + Expr::new_product(ld, rd)).collapse() + } + } (l, r) => Expr::new_sum(l, r), } } @@ -84,15 +94,16 @@ fn group_sum(es: Exprs) -> Exprs { use Expr::*; let mut common: BTreeMap = BTreeMap::new(); for e in es { + match e { + Const(c) if relative_eq!(c, 0.) => { + continue; + } + _ => (), + }; let unkns = e.unknowns(); match common.get_mut(&unkns) { None => { - match e { - Const(c) if relative_eq!(c, 0.) => (), - e => { - common.insert(unkns, e); - } - }; + common.insert(unkns, e); } Some(existing) => { match existing { @@ -110,7 +121,14 @@ fn group_sum(es: Exprs) -> Exprs { for c in common.values() { trace!("group sum value: {}", c); } - common.into_iter().map(|(_, v)| v).collect() + common + .into_iter() + .map(|(_, v)| v) + .filter(|e| match e { + Const(c) if relative_eq!(*c, 0.) => false, + _ => true, + }) + .collect() } fn product_fold(l: Expr, r: Expr) -> Expr { @@ -255,25 +273,25 @@ impl Expr { Expr::new_div(Expr::Const(1.), den) } - pub fn is_zero(self) -> bool { + pub fn is_zero(&self) -> bool { use Expr::*; - match self.simplify() { + match self.clone().simplify() { Const(c) => relative_eq!(c, 0.), _ => false, } } - pub fn is_one(self) -> bool { + pub fn is_one(&self) -> bool { use Expr::*; - match self.simplify() { + match self.clone().simplify() { Const(c) => relative_eq!(c, 1.), _ => false, } } - pub fn evaluate_with(self, eqns: &Eqns) -> Expr { + pub fn substitute<'a>(self, eqns: &Eqns<'a>) -> Expr { use Expr::*; - for eqn in &eqns.0 { + for eqn in (&eqns.0 as &Borrow<[Eqn]>).borrow() { if self == eqn.0 { return eqn.1.clone(); } @@ -281,29 +299,129 @@ impl Expr { match self { Sum(mut es) => { for e in &mut es { - *e = e.clone().evaluate_with(eqns); + *e = e.clone().substitute(eqns); } Sum(es) } Product(mut es) => { for e in &mut es { - *e = e.clone().evaluate_with(eqns); + *e = e.clone().substitute(eqns); } Product(es) } Neg(mut e) => { - *e = e.evaluate_with(eqns); + *e = e.substitute(eqns); Neg(e) } Div(mut num, mut den) => { - *num = num.evaluate_with(eqns); - *den = den.evaluate_with(eqns); + *num = num.substitute(eqns); + *den = den.substitute(eqns); Div(num, den) } other => other, } } + pub fn collapse(self) -> Expr { + use Expr::*; + match self { + Sum(es) => { + let mut new_es: Vec<_> = es + .into_iter() + .map(|e| e.collapse()) + .flat_map(|e| match e { + Sum(more_es) => more_es, + other => vec![other], + }) + .collect(); + + let consts = new_es.drain_filter(|e| match e { + Const(_) => true, + _ => false + }).fold(Const(0.), |l, r| match (l, r) { + (Const(lc), Const(rc)) => Const(lc + rc), + _ => unreachable!(), + }); + new_es.push(consts); + + match new_es.len() { + 0 => Const(0.), // none + 1 => new_es.into_iter().next().unwrap(), // one + _ => Sum(new_es), // many + } + } + Product(es) => { + let new_es: Vec<_> = es + .into_iter() + .map(|e| e.collapse()) + .flat_map(|e| match e { + Product(more_es) => more_es, + other => vec![other], + }) + .collect(); + match new_es.len() { + 0 => Const(1.), // none + 1 => new_es.into_iter().next().unwrap(), // one + _ => { + if new_es.iter().any(|e| e.is_zero()) { + Const(0.) + } else { + Product(new_es) + } + }, // many + } + } + Neg(mut v) => { + *v = v.collapse(); + match v { + box Const(c) => Const(-c), + box Neg(v) => *v, + box Product(mut es) => { + es.push(Const(-1.)); + Product(es).collapse() + } + e => Product(vec![Const(-1.), *e]).collapse(), + } + } + Div(mut num, mut den) => { + *num = num.collapse(); + *den = den.collapse(); + match (num, den) { + (box Const(num), box Const(den)) => Const(num / den), + (box Const(num), den) => { + if relative_eq!(num, 0.) { + Const(0.) + } else { + Div(Box::new(Const(num)), den) + } + } + (num, box Const(den)) => { + if relative_eq!(den, 1.) { + *num + } else { + Expr::new_product(*num, Const(1. / den)).collapse() + } + } + (num, box Div(dennum, denden)) => { + Div(Box::new(Product(vec![*num, *denden])), dennum).collapse() + } + (box Product(mut es), box den) => match es.remove_item(&den) { + Some(_) => Product(es), + None => Expr::new_div(Product(es), den), + }, + (num, den) => { + if num == den { + Expr::Const(1.) + } else { + Div(num, den) + } + } + } + } + e => e, + } + } + pub fn simplify(self) -> Expr { use Expr::*; match self { @@ -362,7 +480,7 @@ impl Expr { es.push(Const(-1.)); Product(es).simplify() } - e => Product(vec![Const(-1.), *e]), + e => Product(vec![Const(-1.), *e]).simplify(), } } Div(mut num, mut den) => { @@ -375,14 +493,14 @@ impl Expr { if relative_eq!(den, 1.) { *num } else { - Expr::new_product(*num, Const(1. / den)) + Expr::new_product(*num, Const(1. / den)).simplify() } } (num, box Div(dennum, denden)) => { Div(Box::new(Product(vec![*num, *denden])), dennum).simplify() } (box Product(mut es), box den) => match es.remove_item(&den) { - Some(_) => Product(es), + Some(_) => Product(es).simplify(), None => Expr::new_div(Product(es), den), }, (num, den) => { @@ -394,6 +512,10 @@ impl Expr { } } } + Const(c) => if c.is_nan() { + println!("NAN!"); + Const(c) + } else { Const(c) }, e => e, } } @@ -411,34 +533,34 @@ impl Expr { res } Product(es) => distribute_product_sums(es), - Div(mut num, mut den) => { - *num = num.distribute(); - *den = den.distribute(); - match (num, den) { - (box Sum(es), box den) => Sum(es - .into_iter() - .map(|e| Expr::new_div(e, den.clone())) - .collect()), - (mut num, mut den) => Div(num, den), - } - } + Div(num, den) => match (num, den) { + (box Sum(es), box den) => Sum(es + .into_iter() + .map(|e| Expr::new_div(e, den.clone()).distribute()) + .collect()), + (num, den) => Div(num, den), + }, Neg(v) => match v { - // box Sum(mut l, mut r) => { - // *l = Neg(l.clone()).distribute(); - // *r = Neg(r.clone()).distribute(); - // Sum(l, r) - // } - // box Product(mut l, r) => { - // *l = Neg(l.clone()).distribute(); - // Product(l, r) - // } + box Const(c) => Const(-c), + box Sum(mut es) => { + for e in &mut es { + *e = Expr::new_neg(e.clone()).distribute(); + } + Sum(es) + } + box Product(mut es) => { + for e in &mut es { + *e = e.clone().distribute(); + } + es.push(Const(-1.)); + Product(es) + } box Neg(v) => v.distribute(), box Div(mut num, mut den) => { - *num = Neg(num.clone()).distribute(); - *den = Neg(den.clone()).distribute(); - Div(num, den) + *num = Neg(num.clone()); + Div(num, den).distribute() } - e => Neg(e), + e => Neg(Box::new(e.distribute())), }, e => e, } diff --git a/src/math/region.rs b/src/math/region.rs index bfdb573..97dd1a9 100644 --- a/src/math/region.rs +++ b/src/math/region.rs @@ -11,7 +11,7 @@ pub trait GenericRegion { fn full() -> Self; fn intersection(self, other: Self) -> Self; fn simplify(self) -> Self; - fn evaluate_with(self, eqns: &eqn::Eqns) -> Self; + fn substitute(self, eqns: &eqn::Eqns) -> Self; } pub trait Region: GenericRegion { @@ -63,12 +63,12 @@ impl GenericRegion for Region1 { } } - fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + fn substitute(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)), + Singleton(n) => Singleton(n.substitute(eqns)), + Range(l, u) => Range(l.substitute(eqns), u.substitute(eqns)), + Intersection(r1, r2) => r1.substitute(eqns).intersection(r2.substitute(eqns)), other => other, } } @@ -162,7 +162,7 @@ impl Line2 { } pub fn evaluate(&self, t: Value) -> Point2 { - self.start.clone() + self.dir.clone() * t + self.start.clone() + self.dir * t } pub fn evaluate_extent(&self) -> Option> { @@ -182,7 +182,7 @@ impl Line2 { pub fn nearest(&self, p: &Point2) -> Point2 { // rotate angle 90 degrees - let perp_dir = self.dir.clone() + Rot2::cardinal(1); + let perp_dir = self.dir + Rot2::cardinal(1); let perp = Line2::new(p.clone(), perp_dir, Region1::Full); match self.intersect(&perp) { Region2::Singleton(np) => np, @@ -193,7 +193,7 @@ impl Line2 { pub fn intersect(&self, other: &Line2) -> Region2 { // if the two lines are parallel... - let dirs = self.dir.clone() - other.dir.clone(); + let dirs = self.dir - other.dir; if relative_eq!(dirs.sin(), 0.) { let starts = self.dir.conj() * (other.start.clone() - self.start.clone()); return if starts.y.simplify().is_zero() { @@ -208,16 +208,16 @@ impl Line2 { let (a, b) = (self, other); let (a_0, a_v, b_0, b_v) = ( a.start.clone(), - a.dir.clone(), + a.dir, b.start.clone(), - b.dir.clone(), + b.dir, ); let (a_c, a_s, b_c, b_s) = (a_v.cos(), a_v.sin(), b_v.cos(), b_v.sin()); - let t_b = (a_0.x.clone() * a_s.clone() - - a_0.y.clone() * a_c.clone() - - b_0.x.clone() * a_s.clone() - + b_0.y.clone() * a_c.clone()) - / (a_s.clone() * b_c.clone() - a_c.clone() * b_s.clone()); + let t_b = (a_0.x.clone() * a_s + - a_0.y.clone() * a_c + - b_0.x.clone() * a_s + + b_0.y.clone() * a_c) + / (a_s * b_c - a_c * b_s); // Region2::Singleton(b.evaluate(t_b)) trace!("intersect a: {}, b: {}, t_b = {}", a, b, t_b); let res = Region2::Line(b.clone().with_extent(Region1::Singleton(t_b.simplify()))); @@ -242,11 +242,11 @@ impl Line2 { Region2::Line(new_l) } - pub fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + pub fn substitute(self, eqns: &eqn::Eqns) -> Self { Line2 { - start: self.start.evaluate_with(eqns), + start: self.start.substitute(eqns), dir: self.dir, - extent: self.extent.evaluate_with(eqns), + extent: self.extent.substitute(eqns), } } } @@ -300,12 +300,12 @@ impl GenericRegion for Region2 { } } - fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { + fn substitute(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)), + Singleton(n) => Singleton(n.substitute(eqns)), + Line(l) => Line(l.substitute(eqns)), + Intersection(r1, r2) => r1.substitute(eqns).intersection(r2.substitute(eqns)), other => other, } } diff --git a/src/math/vec.rs b/src/math/vec.rs index f7e5304..8681e1f 100644 --- a/src/math/vec.rs +++ b/src/math/vec.rs @@ -98,10 +98,10 @@ impl Point2 { } } - pub fn evaluate_with(self, eqns: &Eqns) -> Self { + pub fn substitute(self, eqns: &Eqns) -> Self { Self { - x: self.x.evaluate_with(eqns), - y: self.y.evaluate_with(eqns), + x: self.x.substitute(eqns), + y: self.y.substitute(eqns), } } } @@ -184,8 +184,8 @@ impl Rot2 { pub fn from_angle(angle: Scalar) -> Self { Self { - cos: angle.cos().into(), - sin: angle.sin().into(), + cos: angle.cos(), + sin: angle.sin(), } } @@ -195,22 +195,10 @@ impl Rot2 { pub fn cardinal(index: i64) -> Self { match index % 4 { - 0 => Rot2 { - cos: (1.).into(), - sin: (0.).into(), - }, - 1 => Rot2 { - cos: (0.).into(), - sin: (1.).into(), - }, - 2 => Rot2 { - cos: (-1.).into(), - sin: (0.).into(), - }, - 3 => Rot2 { - cos: (0.).into(), - sin: (-1.).into(), - }, + 0 => Rot2 { cos: 1., sin: 0. }, + 1 => Rot2 { cos: 0., sin: 1. }, + 2 => Rot2 { cos: -1., sin: 0. }, + 3 => Rot2 { cos: 0., sin: -1. }, _ => unreachable!(), } } @@ -266,7 +254,7 @@ impl ops::Add for Rot2 { type Output = Rot2; fn add(self, rhs: Rot2) -> Rot2 { Rot2 { - cos: self.cos.clone() * rhs.cos.clone() - self.sin.clone() * rhs.sin.clone(), + cos: self.cos * rhs.cos - self.sin * rhs.sin, sin: self.cos * rhs.sin + self.sin * rhs.cos, } } @@ -276,7 +264,7 @@ impl ops::Sub for Rot2 { type Output = Rot2; fn sub(self, rhs: Rot2) -> Rot2 { Rot2 { - cos: self.cos.clone() * rhs.cos.clone() + self.sin.clone() * rhs.sin.clone(), + cos: self.cos * rhs.cos + self.sin * rhs.sin, sin: self.sin * rhs.cos - self.cos * rhs.sin, } } diff --git a/src/relation.rs b/src/relation.rs index 032167e..017d7ae 100644 --- a/src/relation.rs +++ b/src/relation.rs @@ -58,7 +58,7 @@ impl PointAngle { Self::new( p1, p2, - Rot2::from_cos_sin_unchecked((1.).into(), (0.).into()), + Rot2::from_cos_sin_unchecked(1., 0.), ) } @@ -66,7 +66,7 @@ impl PointAngle { Self::new( p1, p2, - Rot2::from_cos_sin_unchecked((0.).into(), (1.).into()), + Rot2::from_cos_sin_unchecked(0., 1.), ) } } @@ -76,7 +76,7 @@ impl Relation for PointAngle { use Region2::*; let (mut p1, mut p2) = (self.p1.borrow_mut(), self.p2.borrow_mut()); let constrain_line = |p1: &Point2, p2: &mut PointEntity| { - let line = Region2::Line(Line2::new(p1.clone(), self.angle.clone(), Region1::Full)); + let line = Region2::Line(Line2::new(p1.clone(), self.angle, Region1::Full)); trace!( "PointAngle line: {}, p2 constraint: {}", line, @@ -92,7 +92,7 @@ impl Relation for PointAngle { (Singleton(p1), Singleton(p2)) => { // if the angle p1 and p2 form is parallel to self.angle, the result // will have a y component of 0 - let r = self.angle.clone().conj() * (p2.clone() - p1.clone()); + let r = self.angle.conj() * (p2.clone() - p1.clone()); trace!("angle.cos: {}", r.x); // if relative_eq!(r.y, 0.) { ResolveResult::Constrained