got more stuff to work?
This commit is contained in:
		
							parent
							
								
									067f868222
								
							
						
					
					
						commit
						ce4a662847
					
				| @ -44,7 +44,7 @@ impl<T: Clone, TRegion: Region<T> + Clone> Constrainable<T, TRegion> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn resolve_with(&mut self, eqns: &Eqns) -> bool { |     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) { |         if let Some(n) = resolved_constraints.nearest(&self.value) { | ||||||
|             self.value = n; |             self.value = n; | ||||||
|             true |             true | ||||||
| @ -54,7 +54,7 @@ impl<T: Clone, TRegion: Region<T> + Clone> Constrainable<T, TRegion> { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate_with(&mut self, eqns: &Eqns) -> bool { |     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) { |         if let Some(n) = self.constraints.nearest(&self.value) { | ||||||
|             self.value = n; |             self.value = n; | ||||||
|             true |             true | ||||||
|  | |||||||
| @ -103,7 +103,7 @@ fn main() { | |||||||
|     } |     } | ||||||
|     let e1 = Eqn::new(Expr::Unkn(u1), Expr::Const(1.)); |     let e1 = Eqn::new(Expr::Unkn(u1), Expr::Const(1.)); | ||||||
|     let e2 = Eqn::new(Expr::Unkn(u2), 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 { |     for p in &mut points { | ||||||
|         p.borrow_mut().resolve_with(&eqns); |         p.borrow_mut().resolve_with(&eqns); | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										227
									
								
								src/math/eqn.rs
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								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 std::fmt; | ||||||
| 
 | 
 | ||||||
| use super::expr::Expr; | use super::expr::Expr; | ||||||
| use super::unknown::*; | use super::unknown::*; | ||||||
| use super::Scalar; |  | ||||||
| use crate::math::expr::Expr::*; | use crate::math::expr::Expr::*; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, PartialEq)] | #[derive(Clone, Debug, PartialEq)] | ||||||
| @ -43,21 +45,23 @@ impl Eqn { | |||||||
|         Eqn(self.0.simplify(), self.1.simplify()) |         Eqn(self.0.simplify(), self.1.simplify()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn solve(&self, for_u: Unknown) -> Option<Expr> { |     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<Expr> { | ||||||
|     use Expr::*; |     use Expr::*; | ||||||
|         if !self.has_unknown(for_u) { |     if !eqn.has_unknown(for_u) { | ||||||
|         return None; |         return None; | ||||||
|     } |     } | ||||||
|         trace!("solve: {}", self); |     trace!("solve: {}", eqn); | ||||||
|         let (l, r) = ( |     let (mut l, mut r) = (eqn.0.clone().distribute().simplify(), eqn.1.clone().distribute().simplify()); | ||||||
|             self.0 |     if l == r { | ||||||
|                 .clone().distribute() |         return None | ||||||
|                 .simplify(), |     }; | ||||||
|             self.1 |     l = (l - r).distribute().simplify(); | ||||||
|                 .clone().distribute() |     r = Expr::Const(0.); | ||||||
|                 .simplify(), |  | ||||||
|         ); |  | ||||||
|         let (mut l, mut r) = ord_by_unkn(l, r, for_u)?; |  | ||||||
|     loop { |     loop { | ||||||
|         trace!("solve iter: {} == {}", l, r); |         trace!("solve iter: {} == {}", l, r); | ||||||
|         let (new_l, new_r): (Expr, Expr) = match l { |         let (new_l, new_r): (Expr, Expr) = match l { | ||||||
| @ -69,8 +73,12 @@ impl Eqn { | |||||||
|                     return None; |                     return None; | ||||||
|                 } |                 } | ||||||
|                 ( |                 ( | ||||||
|                         Sum(us).simplify(), |                     us.into_iter().next().unwrap(), | ||||||
|                         Expr::new_minus(r, Sum(not_us)).simplify(), |                     if not_us.len() == 0 { | ||||||
|  |                         r | ||||||
|  |                     } else { | ||||||
|  |                         Expr::new_minus(r, Sum(not_us)) | ||||||
|  |                     }, | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|             Product(es) => { |             Product(es) => { | ||||||
| @ -80,8 +88,12 @@ impl Eqn { | |||||||
|                     return None; |                     return None; | ||||||
|                 } |                 } | ||||||
|                 ( |                 ( | ||||||
|                         Product(us).simplify(), |                     us.into_iter().next().unwrap(), | ||||||
|                         Expr::new_div(r, Product(not_us)).simplify(), |                     if not_us.len() == 0 { | ||||||
|  |                         r | ||||||
|  |                     } else { | ||||||
|  |                         Expr::new_div(r, Product(not_us)) | ||||||
|  |                     }, | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|             Neg(v) => (*v, Expr::new_neg(r)), |             Neg(v) => (*v, Expr::new_neg(r)), | ||||||
| @ -96,9 +108,8 @@ impl Eqn { | |||||||
|             } |             } | ||||||
|             Const(_) => return None, |             Const(_) => return None, | ||||||
|         }; |         }; | ||||||
|             l = new_l; |         l = new_l.distribute().simplify(); | ||||||
|             r = new_r; |         r = new_r.distribute().simplify(); | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -109,9 +120,9 @@ impl fmt::Display for Eqn { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, PartialEq)] | #[derive(Clone, Debug, PartialEq)] | ||||||
| pub struct Eqns(pub Vec<Eqn>); | pub struct Eqns<'a>(pub Cow<'a, [Eqn]>); | ||||||
| 
 | 
 | ||||||
| impl Unknowns for Eqns { | impl<'a> Unknowns for Eqns<'a> { | ||||||
|     fn unknowns(&self) -> UnknownSet { |     fn unknowns(&self) -> UnknownSet { | ||||||
|         self.0.iter().flat_map(|eqn: &Eqn| eqn.unknowns()).collect() |         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 { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         write!(f, "{{ "); |         write!(f, "{{ ")?; | ||||||
|         let mut first = true; |         let mut first = true; | ||||||
|         for eq in &self.0 { |         for eq in (&self.0 as &Borrow<[Eqn]>).borrow() { | ||||||
|             if first { |             if first { | ||||||
|                 first = false; |                 first = false; | ||||||
|             } else { |             } else { | ||||||
| @ -139,8 +150,91 @@ impl fmt::Display for Eqns { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn solve_eqns<'a>(eqns: &Eqns<'a>, for_vars: &[Unknown]) -> Option<Eqns<'static>> { | ||||||
|  |     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::<Unknown, Vec<Expr>>::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<Eqn> = 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<Eqn> = 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::<Vec<_>>() | ||||||
|  |                 .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)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|  |     use super::super::Scalar; | ||||||
|     use super::*; |     use super::*; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -171,7 +265,7 @@ mod tests { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_eqn_solve() { |     fn test_solve_eqn() { | ||||||
|         use Expr::*; |         use Expr::*; | ||||||
|         let _ = env_logger::try_init(); |         let _ = env_logger::try_init(); | ||||||
|         let u1 = Unknown(1); |         let u1 = Unknown(1); | ||||||
| @ -179,22 +273,22 @@ mod tests { | |||||||
|         let e2 = Const(1.); |         let e2 = Const(1.); | ||||||
| 
 | 
 | ||||||
|         let eqn = Eqn(e1.clone(), e2.clone()); |         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()); |         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 e3: Expr = Expr::from(1.) + 1. + 2.; | ||||||
|         let eqn = Eqn(e1.clone(), e3.clone()); |         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 e3 = Expr::from(1.) - 1.; | ||||||
|         let eqn = Eqn(e1.clone(), e3.clone()); |         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 e1 = Expr::from(2.) / (Expr::from(1.) - 4.); | ||||||
|         let e2 = Expr::new_minus(Const(1.), Unkn(u1)); |         let e2 = Expr::new_minus(Const(1.), Unkn(u1)); | ||||||
|         let eqn = Eqn(e1, e2); |         let eqn = Eqn(e1, e2); | ||||||
|         info!("eqn: {} => {}", eqn, eqn.clone().simplify()); |         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!(const_expr(e.clone()).is_some()); | ||||||
|         assert!(relative_eq!(const_expr(e.clone()).unwrap(), 5. / 3.)); |         assert!(relative_eq!(const_expr(e.clone()).unwrap(), 5. / 3.)); | ||||||
| 
 | 
 | ||||||
| @ -208,7 +302,7 @@ mod tests { | |||||||
|             e2.clone().simplify() |             e2.clone().simplify() | ||||||
|         ); |         ); | ||||||
|         let eqn = Eqn(e1, e2); |         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!(const_expr(e.clone()).is_some()); | ||||||
|         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -6.)); |         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -6.)); | ||||||
| 
 | 
 | ||||||
| @ -229,7 +323,7 @@ mod tests { | |||||||
|             e2.clone().distribute().simplify() |             e2.clone().distribute().simplify() | ||||||
|         ); |         ); | ||||||
|         let eqn = Eqn(e1, e2); |         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!(const_expr(e.clone()).is_some()); | ||||||
|         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -8.)); |         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -8.)); | ||||||
| 
 | 
 | ||||||
| @ -240,16 +334,38 @@ mod tests { | |||||||
|             e1, |             e1, | ||||||
|             e2, |             e2, | ||||||
|             e1.clone().distribute().simplify(), |             e1.clone().distribute().simplify(), | ||||||
|             e2.clone().distribute().simplify().simplify() |             e2.clone().distribute().simplify() | ||||||
|         ); |         ); | ||||||
|         let eqn = Eqn(e1, e2); |         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!(const_expr(e.clone()).is_some()); | ||||||
|         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -9.)); |         assert!(relative_eq!(const_expr(e.clone()).unwrap(), -9.)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_eqns_solve() { |     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::*; |         use Expr::*; | ||||||
| 
 | 
 | ||||||
|         let x = Unknown(1); |         let x = Unknown(1); | ||||||
| @ -257,14 +373,43 @@ mod tests { | |||||||
|         let t1 = Unknown(3); |         let t1 = Unknown(3); | ||||||
|         let t2 = Unknown(4); |         let t2 = Unknown(4); | ||||||
| 
 | 
 | ||||||
|         let eqns = Eqns(vec![ |         let eqns = Eqns( | ||||||
|             Eqn::new(x.into(), t1 / 2.), |             vec![ | ||||||
|  |                 Eqn::new(x.into(), t1 * 1.), | ||||||
|                 Eqn::new(y.into(), t1 / 2.), |                 Eqn::new(y.into(), t1 / 2.), | ||||||
|             Eqn::new(x.into(), Const(1.0) - t2 / 2.), |                 Eqn::new(x.into(), Const(0.0) + t2 / 2.), | ||||||
|                 Eqn::new(y.into(), t2 / 2.), |                 Eqn::new(y.into(), t2 / 2.), | ||||||
|         ]); |             ] | ||||||
|  |             .into(), | ||||||
|  |         ); | ||||||
|         println!("eqns: {}", eqns); |         println!("eqns: {}", eqns); | ||||||
|         let sol = eqns.solve(&[t1, t2]).unwrap(); |         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 * 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 = solve_eqns(&eqns, &[t1, t2]).unwrap(); | ||||||
|  |         println!("sols: {}", sol); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										214
									
								
								src/math/expr.rs
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								src/math/expr.rs
									
									
									
									
									
								
							| @ -1,9 +1,11 @@ | |||||||
|  | use std::borrow::Borrow; | ||||||
| use std::collections::BTreeMap; | use std::collections::BTreeMap; | ||||||
| use std::fmt; | use std::fmt; | ||||||
| 
 | 
 | ||||||
| use super::eqn::Eqns; | use super::eqn::{Eqn, Eqns}; | ||||||
| use super::unknown::{Unknown, UnknownSet, Unknowns}; | use super::unknown::{Unknown, UnknownSet, Unknowns}; | ||||||
| use super::Scalar; | use super::Scalar; | ||||||
|  | use std::f64::NAN; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug, PartialEq)] | #[derive(Clone, Debug, PartialEq)] | ||||||
| pub enum Expr { | 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 { | fn write_separated_exprs(es: &[Expr], f: &mut fmt::Formatter, sep: &str) -> fmt::Result { | ||||||
|     let mut is_first = true; |  | ||||||
|     write!(f, "(")?; |     write!(f, "(")?; | ||||||
|  |     let mut is_first = es.len() > 1; | ||||||
|     for e in es { |     for e in es { | ||||||
|         if is_first { |         if is_first { | ||||||
|             is_first = false; |             is_first = false; | ||||||
| @ -66,16 +68,24 @@ fn sum_fold(l: Expr, r: Expr) -> Expr { | |||||||
|             if comm.is_empty() { |             if comm.is_empty() { | ||||||
|                 Expr::new_sum(Product(l), Product(r)) |                 Expr::new_sum(Product(l), Product(r)) | ||||||
|             } else { |             } 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)) => { |         (Product(mut l), r) | (r, Product(mut l)) => { | ||||||
|             let comm = remove_term(&mut l, &r); |             let comm = remove_term(&mut l, &r); | ||||||
|             match comm { |             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), |                 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), |         (l, r) => Expr::new_sum(l, r), | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -84,16 +94,17 @@ fn group_sum(es: Exprs) -> Exprs { | |||||||
|     use Expr::*; |     use Expr::*; | ||||||
|     let mut common: BTreeMap<UnknownSet, Expr> = BTreeMap::new(); |     let mut common: BTreeMap<UnknownSet, Expr> = BTreeMap::new(); | ||||||
|     for e in es { |     for e in es { | ||||||
|  |         match e { | ||||||
|  |             Const(c) if relative_eq!(c, 0.) => { | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  |             _ => (), | ||||||
|  |         }; | ||||||
|         let unkns = e.unknowns(); |         let unkns = e.unknowns(); | ||||||
|         match common.get_mut(&unkns) { |         match common.get_mut(&unkns) { | ||||||
|             None => { |             None => { | ||||||
|                 match e { |  | ||||||
|                     Const(c) if relative_eq!(c, 0.) => (), |  | ||||||
|                     e => { |  | ||||||
|                 common.insert(unkns, e); |                 common.insert(unkns, e); | ||||||
|             } |             } | ||||||
|                 }; |  | ||||||
|             } |  | ||||||
|             Some(existing) => { |             Some(existing) => { | ||||||
|                 match existing { |                 match existing { | ||||||
|                     Sum(ref mut es) => { |                     Sum(ref mut es) => { | ||||||
| @ -110,7 +121,14 @@ fn group_sum(es: Exprs) -> Exprs { | |||||||
|     for c in common.values() { |     for c in common.values() { | ||||||
|         trace!("group sum value: {}", c); |         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 { | fn product_fold(l: Expr, r: Expr) -> Expr { | ||||||
| @ -255,25 +273,25 @@ impl Expr { | |||||||
|         Expr::new_div(Expr::Const(1.), den) |         Expr::new_div(Expr::Const(1.), den) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn is_zero(self) -> bool { |     pub fn is_zero(&self) -> bool { | ||||||
|         use Expr::*; |         use Expr::*; | ||||||
|         match self.simplify() { |         match self.clone().simplify() { | ||||||
|             Const(c) => relative_eq!(c, 0.), |             Const(c) => relative_eq!(c, 0.), | ||||||
|             _ => false, |             _ => false, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn is_one(self) -> bool { |     pub fn is_one(&self) -> bool { | ||||||
|         use Expr::*; |         use Expr::*; | ||||||
|         match self.simplify() { |         match self.clone().simplify() { | ||||||
|             Const(c) => relative_eq!(c, 1.), |             Const(c) => relative_eq!(c, 1.), | ||||||
|             _ => false, |             _ => false, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate_with(self, eqns: &Eqns) -> Expr { |     pub fn substitute<'a>(self, eqns: &Eqns<'a>) -> Expr { | ||||||
|         use Expr::*; |         use Expr::*; | ||||||
|         for eqn in &eqns.0 { |         for eqn in (&eqns.0 as &Borrow<[Eqn]>).borrow() { | ||||||
|             if self == eqn.0 { |             if self == eqn.0 { | ||||||
|                 return eqn.1.clone(); |                 return eqn.1.clone(); | ||||||
|             } |             } | ||||||
| @ -281,29 +299,129 @@ impl Expr { | |||||||
|         match self { |         match self { | ||||||
|             Sum(mut es) => { |             Sum(mut es) => { | ||||||
|                 for e in &mut es { |                 for e in &mut es { | ||||||
|                     *e = e.clone().evaluate_with(eqns); |                     *e = e.clone().substitute(eqns); | ||||||
|                 } |                 } | ||||||
|                 Sum(es) |                 Sum(es) | ||||||
|             } |             } | ||||||
|             Product(mut es) => { |             Product(mut es) => { | ||||||
|                 for e in &mut es { |                 for e in &mut es { | ||||||
|                     *e = e.clone().evaluate_with(eqns); |                     *e = e.clone().substitute(eqns); | ||||||
|                 } |                 } | ||||||
|                 Product(es) |                 Product(es) | ||||||
|             } |             } | ||||||
|             Neg(mut e) => { |             Neg(mut e) => { | ||||||
|                 *e = e.evaluate_with(eqns); |                 *e = e.substitute(eqns); | ||||||
|                 Neg(e) |                 Neg(e) | ||||||
|             } |             } | ||||||
|             Div(mut num, mut den) => { |             Div(mut num, mut den) => { | ||||||
|                 *num = num.evaluate_with(eqns); |                 *num = num.substitute(eqns); | ||||||
|                 *den = den.evaluate_with(eqns); |                 *den = den.substitute(eqns); | ||||||
|                 Div(num, den) |                 Div(num, den) | ||||||
|             } |             } | ||||||
|             other => other, |             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 { |     pub fn simplify(self) -> Expr { | ||||||
|         use Expr::*; |         use Expr::*; | ||||||
|         match self { |         match self { | ||||||
| @ -362,7 +480,7 @@ impl Expr { | |||||||
|                         es.push(Const(-1.)); |                         es.push(Const(-1.)); | ||||||
|                         Product(es).simplify() |                         Product(es).simplify() | ||||||
|                     } |                     } | ||||||
|                     e => Product(vec![Const(-1.), *e]), |                     e => Product(vec![Const(-1.), *e]).simplify(), | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             Div(mut num, mut den) => { |             Div(mut num, mut den) => { | ||||||
| @ -375,14 +493,14 @@ impl Expr { | |||||||
|                         if relative_eq!(den, 1.) { |                         if relative_eq!(den, 1.) { | ||||||
|                             *num |                             *num | ||||||
|                         } else { |                         } else { | ||||||
|                             Expr::new_product(*num, Const(1. / den)) |                             Expr::new_product(*num, Const(1. / den)).simplify() | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     (num, box Div(dennum, denden)) => { |                     (num, box Div(dennum, denden)) => { | ||||||
|                         Div(Box::new(Product(vec![*num, *denden])), dennum).simplify() |                         Div(Box::new(Product(vec![*num, *denden])), dennum).simplify() | ||||||
|                     } |                     } | ||||||
|                     (box Product(mut es), box den) => match es.remove_item(&den) { |                     (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), |                         None => Expr::new_div(Product(es), den), | ||||||
|                     }, |                     }, | ||||||
|                     (num, den) => { |                     (num, den) => { | ||||||
| @ -394,6 +512,10 @@ impl Expr { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             Const(c) => if c.is_nan() { | ||||||
|  |                 println!("NAN!"); | ||||||
|  |                 Const(c) | ||||||
|  |             } else { Const(c) }, | ||||||
|             e => e, |             e => e, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -411,34 +533,34 @@ impl Expr { | |||||||
|                 res |                 res | ||||||
|             } |             } | ||||||
|             Product(es) => distribute_product_sums(es), |             Product(es) => distribute_product_sums(es), | ||||||
|             Div(mut num, mut den) => { |             Div(num, den) => match (num, den) { | ||||||
|                 *num = num.distribute(); |  | ||||||
|                 *den = den.distribute(); |  | ||||||
|                 match (num, den) { |  | ||||||
|                 (box Sum(es), box den) => Sum(es |                 (box Sum(es), box den) => Sum(es | ||||||
|                     .into_iter() |                     .into_iter() | ||||||
|                         .map(|e| Expr::new_div(e, den.clone())) |                     .map(|e| Expr::new_div(e, den.clone()).distribute()) | ||||||
|                     .collect()), |                     .collect()), | ||||||
|                     (mut num, mut den) => Div(num, den), |                 (num, den) => Div(num, den), | ||||||
|                 } |             }, | ||||||
|             } |  | ||||||
|             Neg(v) => match v { |             Neg(v) => match v { | ||||||
|                 // box Sum(mut l, mut r) => {
 |                 box Const(c) => Const(-c), | ||||||
|                 //     *l = Neg(l.clone()).distribute();
 |                 box Sum(mut es) => { | ||||||
|                 //     *r = Neg(r.clone()).distribute();
 |                     for e in &mut es { | ||||||
|                 //     Sum(l, r)
 |                         *e = Expr::new_neg(e.clone()).distribute(); | ||||||
|                 // }
 |                     } | ||||||
|                 // box Product(mut l, r) => {
 |                     Sum(es) | ||||||
|                 //     *l = Neg(l.clone()).distribute();
 |                 } | ||||||
|                 //     Product(l, r)
 |                 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 Neg(v) => v.distribute(), | ||||||
|                 box Div(mut num, mut den) => { |                 box Div(mut num, mut den) => { | ||||||
|                     *num = Neg(num.clone()).distribute(); |                     *num = Neg(num.clone()); | ||||||
|                     *den = Neg(den.clone()).distribute(); |                     Div(num, den).distribute() | ||||||
|                     Div(num, den) |  | ||||||
|                 } |                 } | ||||||
|                 e => Neg(e), |                 e => Neg(Box::new(e.distribute())), | ||||||
|             }, |             }, | ||||||
|             e => e, |             e => e, | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ pub trait GenericRegion { | |||||||
|     fn full() -> Self; |     fn full() -> Self; | ||||||
|     fn intersection(self, other: Self) -> Self; |     fn intersection(self, other: Self) -> Self; | ||||||
|     fn simplify(self) -> Self; |     fn simplify(self) -> Self; | ||||||
|     fn evaluate_with(self, eqns: &eqn::Eqns) -> Self; |     fn substitute(self, eqns: &eqn::Eqns) -> Self; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait Region<T>: GenericRegion { | pub trait Region<T>: 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::*; |         use Region1::*; | ||||||
|         match self { |         match self { | ||||||
|             Singleton(n) => Singleton(n.evaluate_with(eqns)), |             Singleton(n) => Singleton(n.substitute(eqns)), | ||||||
|             Range(l, u) => Range(l.evaluate_with(eqns), u.evaluate_with(eqns)), |             Range(l, u) => Range(l.substitute(eqns), u.substitute(eqns)), | ||||||
|             Intersection(r1, r2) => r1.evaluate_with(eqns).intersection(r2.evaluate_with(eqns)), |             Intersection(r1, r2) => r1.substitute(eqns).intersection(r2.substitute(eqns)), | ||||||
|             other => other, |             other => other, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -162,7 +162,7 @@ impl Line2 { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate(&self, t: Value) -> Point2<Value> { |     pub fn evaluate(&self, t: Value) -> Point2<Value> { | ||||||
|         self.start.clone() + self.dir.clone() * t |         self.start.clone() + self.dir * t | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate_extent(&self) -> Option<Point2<Value>> { |     pub fn evaluate_extent(&self) -> Option<Point2<Value>> { | ||||||
| @ -182,7 +182,7 @@ impl Line2 { | |||||||
| 
 | 
 | ||||||
|     pub fn nearest(&self, p: &Point2<Value>) -> Point2<Value> { |     pub fn nearest(&self, p: &Point2<Value>) -> Point2<Value> { | ||||||
|         // rotate angle 90 degrees
 |         // 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); |         let perp = Line2::new(p.clone(), perp_dir, Region1::Full); | ||||||
|         match self.intersect(&perp) { |         match self.intersect(&perp) { | ||||||
|             Region2::Singleton(np) => np, |             Region2::Singleton(np) => np, | ||||||
| @ -193,7 +193,7 @@ impl Line2 { | |||||||
| 
 | 
 | ||||||
|     pub fn intersect(&self, other: &Line2) -> Region2 { |     pub fn intersect(&self, other: &Line2) -> Region2 { | ||||||
|         // if the two lines are parallel...
 |         // 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.) { |         if relative_eq!(dirs.sin(), 0.) { | ||||||
|             let starts = self.dir.conj() * (other.start.clone() - self.start.clone()); |             let starts = self.dir.conj() * (other.start.clone() - self.start.clone()); | ||||||
|             return if starts.y.simplify().is_zero() { |             return if starts.y.simplify().is_zero() { | ||||||
| @ -208,16 +208,16 @@ impl Line2 { | |||||||
|         let (a, b) = (self, other); |         let (a, b) = (self, other); | ||||||
|         let (a_0, a_v, b_0, b_v) = ( |         let (a_0, a_v, b_0, b_v) = ( | ||||||
|             a.start.clone(), |             a.start.clone(), | ||||||
|             a.dir.clone(), |             a.dir, | ||||||
|             b.start.clone(), |             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 (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() |         let t_b = (a_0.x.clone() * a_s | ||||||
|             - a_0.y.clone() * a_c.clone() |             - a_0.y.clone() * a_c | ||||||
|             - b_0.x.clone() * a_s.clone() |             - b_0.x.clone() * a_s | ||||||
|             + b_0.y.clone() * a_c.clone()) |             + b_0.y.clone() * a_c) | ||||||
|             / (a_s.clone() * b_c.clone() - a_c.clone() * b_s.clone()); |             / (a_s * b_c - a_c * b_s); | ||||||
|         // Region2::Singleton(b.evaluate(t_b))
 |         // Region2::Singleton(b.evaluate(t_b))
 | ||||||
|         trace!("intersect a: {}, b: {}, t_b = {}", a, b, 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()))); |         let res = Region2::Line(b.clone().with_extent(Region1::Singleton(t_b.simplify()))); | ||||||
| @ -242,11 +242,11 @@ impl Line2 { | |||||||
|         Region2::Line(new_l) |         Region2::Line(new_l) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate_with(self, eqns: &eqn::Eqns) -> Self { |     pub fn substitute(self, eqns: &eqn::Eqns) -> Self { | ||||||
|         Line2 { |         Line2 { | ||||||
|             start: self.start.evaluate_with(eqns), |             start: self.start.substitute(eqns), | ||||||
|             dir: self.dir, |             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::*; |         use Region2::*; | ||||||
|         match self { |         match self { | ||||||
|             Singleton(n) => Singleton(n.evaluate_with(eqns)), |             Singleton(n) => Singleton(n.substitute(eqns)), | ||||||
|             Line(l) => Line(l.evaluate_with(eqns)), |             Line(l) => Line(l.substitute(eqns)), | ||||||
|             Intersection(r1, r2) => r1.evaluate_with(eqns).intersection(r2.evaluate_with(eqns)), |             Intersection(r1, r2) => r1.substitute(eqns).intersection(r2.substitute(eqns)), | ||||||
|             other => other, |             other => other, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -98,10 +98,10 @@ impl Point2<Value> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn evaluate_with(self, eqns: &Eqns) -> Self { |     pub fn substitute(self, eqns: &Eqns) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             x: self.x.evaluate_with(eqns), |             x: self.x.substitute(eqns), | ||||||
|             y: self.y.evaluate_with(eqns), |             y: self.y.substitute(eqns), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -184,8 +184,8 @@ impl Rot2 { | |||||||
| 
 | 
 | ||||||
|     pub fn from_angle(angle: Scalar) -> Self { |     pub fn from_angle(angle: Scalar) -> Self { | ||||||
|         Self { |         Self { | ||||||
|             cos: angle.cos().into(), |             cos: angle.cos(), | ||||||
|             sin: angle.sin().into(), |             sin: angle.sin(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -195,22 +195,10 @@ impl Rot2 { | |||||||
| 
 | 
 | ||||||
|     pub fn cardinal(index: i64) -> Self { |     pub fn cardinal(index: i64) -> Self { | ||||||
|         match index % 4 { |         match index % 4 { | ||||||
|             0 => Rot2 { |             0 => Rot2 { cos: 1., sin: 0. }, | ||||||
|                 cos: (1.).into(), |             1 => Rot2 { cos: 0., sin: 1. }, | ||||||
|                 sin: (0.).into(), |             2 => Rot2 { cos: -1., sin: 0. }, | ||||||
|             }, |             3 => Rot2 { cos: 0., sin: -1. }, | ||||||
|             1 => Rot2 { |  | ||||||
|                 cos: (0.).into(), |  | ||||||
|                 sin: (1.).into(), |  | ||||||
|             }, |  | ||||||
|             2 => Rot2 { |  | ||||||
|                 cos: (-1.).into(), |  | ||||||
|                 sin: (0.).into(), |  | ||||||
|             }, |  | ||||||
|             3 => Rot2 { |  | ||||||
|                 cos: (0.).into(), |  | ||||||
|                 sin: (-1.).into(), |  | ||||||
|             }, |  | ||||||
|             _ => unreachable!(), |             _ => unreachable!(), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -266,7 +254,7 @@ impl ops::Add<Rot2> for Rot2 { | |||||||
|     type Output = Rot2; |     type Output = Rot2; | ||||||
|     fn add(self, rhs: Rot2) -> Rot2 { |     fn add(self, rhs: Rot2) -> 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, |             sin: self.cos * rhs.sin + self.sin * rhs.cos, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -276,7 +264,7 @@ impl ops::Sub<Rot2> for Rot2 { | |||||||
|     type Output = Rot2; |     type Output = Rot2; | ||||||
|     fn sub(self, rhs: Rot2) -> Rot2 { |     fn sub(self, rhs: Rot2) -> 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, |             sin: self.sin * rhs.cos - self.cos * rhs.sin, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -58,7 +58,7 @@ impl PointAngle { | |||||||
|         Self::new( |         Self::new( | ||||||
|             p1, |             p1, | ||||||
|             p2, |             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( |         Self::new( | ||||||
|             p1, |             p1, | ||||||
|             p2, |             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::*; |         use Region2::*; | ||||||
|         let (mut p1, mut p2) = (self.p1.borrow_mut(), self.p2.borrow_mut()); |         let (mut p1, mut p2) = (self.p1.borrow_mut(), self.p2.borrow_mut()); | ||||||
|         let constrain_line = |p1: &Point2<Value>, p2: &mut PointEntity| { |         let constrain_line = |p1: &Point2<Value>, 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!( |             trace!( | ||||||
|                 "PointAngle line: {}, p2 constraint: {}", |                 "PointAngle line: {}, p2 constraint: {}", | ||||||
|                 line, |                 line, | ||||||
| @ -92,7 +92,7 @@ impl Relation for PointAngle { | |||||||
|             (Singleton(p1), Singleton(p2)) => { |             (Singleton(p1), Singleton(p2)) => { | ||||||
|                 // if the angle p1 and p2 form is parallel to self.angle, the result
 |                 // if the angle p1 and p2 form is parallel to self.angle, the result
 | ||||||
|                 // will have a y component of 0
 |                 // 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); |                 trace!("angle.cos: {}", r.x); | ||||||
|                 // if relative_eq!(r.y, 0.) {
 |                 // if relative_eq!(r.y, 0.) {
 | ||||||
|                 ResolveResult::Constrained |                 ResolveResult::Constrained | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user