Lots of work to make equation solving work better
This commit is contained in:
		
							parent
							
								
									dc674dbce0
								
							
						
					
					
						commit
						461088da3a
					
				@ -96,19 +96,22 @@ fn remove_term(terms: &mut Vec<Expr>, term: &Expr) -> Option<Expr> {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn sum_fold(l: Expr, r: Expr) -> Expr {
 | 
					fn sum_fold(l: Expr, r: Expr) -> Expr {
 | 
				
			||||||
    use itertools::Itertools;
 | 
					 | 
				
			||||||
    use Expr::*;
 | 
					    use Expr::*;
 | 
				
			||||||
    match (l, r) {
 | 
					    match (l, r) {
 | 
				
			||||||
        (Const(lc), Const(rc)) => Const(lc + rc),
 | 
					        (Const(lc), Const(rc)) => Const(lc + rc),
 | 
				
			||||||
        (Const(c), o) | (o, Const(c)) if relative_eq!(c, 0.) => o,
 | 
					        (Const(c), o) | (o, Const(c)) if relative_eq!(c, 0.) => o,
 | 
				
			||||||
        (Product(mut l), Product(mut r)) => {
 | 
					        (Product(mut l), Product(mut r)) => {
 | 
				
			||||||
            let comm = remove_common_terms(&mut l, &mut r);
 | 
					            let comm = remove_common_terms(&mut l, &mut r);
 | 
				
			||||||
            Expr::new_product(Sum(comm), Expr::new_sum(Product(l), Product(r))).simplify()
 | 
					            if comm.is_empty() {
 | 
				
			||||||
 | 
					                Expr::new_sum(Product(l), Product(r))
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Expr::new_product(Product(comm), Expr::new_sum(Product(l), Product(r)))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        (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.))).simplify(),
 | 
					                Some(_) => Expr::new_product(r, Expr::new_sum(Product(l), Const(1.))),
 | 
				
			||||||
                None => Expr::new_sum(Product(l), r),
 | 
					                None => Expr::new_sum(Product(l), r),
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -143,6 +146,9 @@ 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).collect()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -159,44 +165,49 @@ fn product_fold(l: Expr, r: Expr) -> Expr {
 | 
				
			|||||||
                Expr::Div(Box::new(Expr::Product(vec![*num, mul])), den).simplify()
 | 
					                Expr::Div(Box::new(Expr::Product(vec![*num, mul])), den).simplify()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        (Product(mut ls), Product(mut rs)) => {
 | 
				
			||||||
 | 
					            ls.append(&mut rs);
 | 
				
			||||||
 | 
					            Product(ls)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        (Product(mut ps), o) | (o, Product(mut ps)) => {
 | 
				
			||||||
 | 
					            ps.push(o);
 | 
				
			||||||
 | 
					            Product(ps)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        (l, r) => Expr::new_product(l, r),
 | 
					        (l, r) => Expr::new_product(l, r),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn group_product(es: Exprs) -> Exprs {
 | 
					fn group_product(es: Exprs) -> Exprs {
 | 
				
			||||||
    use Expr::*;
 | 
					    use Expr::*;
 | 
				
			||||||
    // let mut common: BTreeMap<UnknownSet, Expr> = BTreeMap::new();
 | 
					    let es2 = es.clone();
 | 
				
			||||||
    let mut common: Option<Expr> = None;
 | 
					    let mut consts: Option<Scalar> = None;
 | 
				
			||||||
 | 
					    let mut other = Exprs::new();
 | 
				
			||||||
    for e in es {
 | 
					    for e in es {
 | 
				
			||||||
        let unkns = e.unknowns();
 | 
					        let unkns = e.unknowns();
 | 
				
			||||||
        // match common.get_mut(&unkns) {
 | 
					        match e { 
 | 
				
			||||||
        match &mut common {
 | 
					            Const(c) => match consts {
 | 
				
			||||||
            None => {
 | 
					                None => consts = Some(c),
 | 
				
			||||||
                match e {
 | 
					                Some(cs) => consts = Some(c * cs),
 | 
				
			||||||
                    Const(c) if relative_eq!(c, 1.) => (),
 | 
					 | 
				
			||||||
                    e => {
 | 
					 | 
				
			||||||
                        // common.insert(unkns, e);
 | 
					 | 
				
			||||||
                        common = Some(e);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Some(existing) => {
 | 
					            e => {
 | 
				
			||||||
                match existing {
 | 
					                other.push(e)
 | 
				
			||||||
                    // Product(ref mut es) => {
 | 
					 | 
				
			||||||
                        // already failed at merging, so just add it to the list
 | 
					 | 
				
			||||||
                        // es.push(e);
 | 
					 | 
				
			||||||
                    // }
 | 
					 | 
				
			||||||
                    other => *other = product_fold(other.clone(), e),
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // common.into_iter().map(|(_, v)| v).collect()
 | 
					    if let Some(cs) = consts { 
 | 
				
			||||||
    common.into_iter().collect()
 | 
					        if relative_eq!(cs, 0.0) {
 | 
				
			||||||
 | 
					            other.clear();
 | 
				
			||||||
 | 
					            other.push(Const(0.0))
 | 
				
			||||||
 | 
					        } else if relative_ne!(cs, 1.0) {
 | 
				
			||||||
 | 
					            other.push(Const(cs)) 
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    trace!("group product: {:?} => {:?}", es2, other);
 | 
				
			||||||
 | 
					    other
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn distribute_product_sums(mut es: Exprs) -> Expr {
 | 
					fn distribute_product_sums(mut es: Exprs) -> Expr {
 | 
				
			||||||
    trace!("distribute_product_sums: {}", Product(es.clone()));
 | 
					    let es_pre = es.clone();
 | 
				
			||||||
    use itertools::Itertools;
 | 
					    use itertools::Itertools;
 | 
				
			||||||
    use Expr::*;
 | 
					    use Expr::*;
 | 
				
			||||||
    for e in &mut es {
 | 
					    for e in &mut es {
 | 
				
			||||||
@ -209,14 +220,14 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
        .map(|e| {
 | 
					        .map(|e| {
 | 
				
			||||||
            trace!("sum in product: {}", e);
 | 
					            trace!("sum in product: {}", e);
 | 
				
			||||||
            match e {
 | 
					            match e.simplify() {
 | 
				
			||||||
                Sum(es) => es,
 | 
					                Sum(es) => es,
 | 
				
			||||||
                _ => unreachable!(),
 | 
					                o => vec![o],
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    let products: Vec<_> = sums.multi_cartesian_product().collect();
 | 
					    let products: Vec<_> = sums.multi_cartesian_product().collect();
 | 
				
			||||||
    if products.is_empty() {
 | 
					    if products.is_empty() {
 | 
				
			||||||
        trace!("no sums to distribute");
 | 
					        trace!("distribute_product_sums: no sums to distribute");
 | 
				
			||||||
        return Product(es);
 | 
					        return Product(es);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let sums = products
 | 
					    let sums = products
 | 
				
			||||||
@ -227,7 +238,9 @@ fn distribute_product_sums(mut es: Exprs) -> Expr {
 | 
				
			|||||||
            Product(prod)
 | 
					            Product(prod)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .collect();
 | 
					        .collect();
 | 
				
			||||||
    Sum(sums)
 | 
					    let res = Sum(sums);
 | 
				
			||||||
 | 
					    trace!("distribute_product_sums: {} => {}", Product(es_pre), res);
 | 
				
			||||||
 | 
					    res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Unknowns for Expr {
 | 
					impl Unknowns for Expr {
 | 
				
			||||||
@ -336,6 +349,7 @@ impl Expr {
 | 
				
			|||||||
        use Expr::*;
 | 
					        use Expr::*;
 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Sum(es) => {
 | 
					            Sum(es) => {
 | 
				
			||||||
 | 
					                let pre_new_es = es.clone();
 | 
				
			||||||
                let mut new_es: Vec<_> = es
 | 
					                let mut new_es: Vec<_> = es
 | 
				
			||||||
                    .into_iter()
 | 
					                    .into_iter()
 | 
				
			||||||
                    .map(|e| e.simplify())
 | 
					                    .map(|e| e.simplify())
 | 
				
			||||||
@ -344,7 +358,6 @@ impl Expr {
 | 
				
			|||||||
                        other => vec![other],
 | 
					                        other => vec![other],
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .collect();
 | 
					                    .collect();
 | 
				
			||||||
                let pre_new_es = new_es.clone();
 | 
					 | 
				
			||||||
                new_es = group_sum(new_es);
 | 
					                new_es = group_sum(new_es);
 | 
				
			||||||
                trace!(
 | 
					                trace!(
 | 
				
			||||||
                    "simplify sum {} => {}",
 | 
					                    "simplify sum {} => {}",
 | 
				
			||||||
@ -359,6 +372,7 @@ impl Expr {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Product(es) => {
 | 
					            Product(es) => {
 | 
				
			||||||
 | 
					                let pre_new_es = es.clone();
 | 
				
			||||||
                let new_es: Vec<_> = es
 | 
					                let new_es: Vec<_> = es
 | 
				
			||||||
                    .into_iter()
 | 
					                    .into_iter()
 | 
				
			||||||
                    .map(|e| e.simplify())
 | 
					                    .map(|e| e.simplify())
 | 
				
			||||||
@ -367,7 +381,6 @@ impl Expr {
 | 
				
			|||||||
                        other => vec![other],
 | 
					                        other => vec![other],
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .collect();
 | 
					                    .collect();
 | 
				
			||||||
                let pre_new_es = new_es.clone();
 | 
					 | 
				
			||||||
                let new_es = group_product(new_es);
 | 
					                let new_es = group_product(new_es);
 | 
				
			||||||
                trace!(
 | 
					                trace!(
 | 
				
			||||||
                    "simplify product {} => {}",
 | 
					                    "simplify product {} => {}",
 | 
				
			||||||
@ -388,7 +401,7 @@ impl Expr {
 | 
				
			|||||||
                    box Neg(v) => *v,
 | 
					                    box Neg(v) => *v,
 | 
				
			||||||
                    box Product(mut es) => {
 | 
					                    box Product(mut es) => {
 | 
				
			||||||
                        es.push(Const(-1.));
 | 
					                        es.push(Const(-1.));
 | 
				
			||||||
                        Product(es)
 | 
					                        Product(es).simplify()
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    e => Product(vec![Const(-1.), *e]),
 | 
					                    e => Product(vec![Const(-1.), *e]),
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -428,13 +441,15 @@ impl Expr {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn distribute(self) -> Expr {
 | 
					    pub fn distribute(self) -> Expr {
 | 
				
			||||||
        use Expr::*;
 | 
					        use Expr::*;
 | 
				
			||||||
        trace!("distribute {}", self);
 | 
					 | 
				
			||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Sum(mut es) => {
 | 
					            Sum(mut es) => {
 | 
				
			||||||
 | 
					                let es_pre = es.clone();
 | 
				
			||||||
                for e in &mut es {
 | 
					                for e in &mut es {
 | 
				
			||||||
                    *e = e.clone().distribute();
 | 
					                    *e = e.clone().distribute();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Sum(es)
 | 
					                let res = Sum(es);
 | 
				
			||||||
 | 
					                trace!("distribute sum {} => {}", Sum(es_pre), res);
 | 
				
			||||||
 | 
					                res
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Product(es) => distribute_product_sums(es),
 | 
					            Product(es) => distribute_product_sums(es),
 | 
				
			||||||
            Div(mut num, mut den) => {
 | 
					            Div(mut num, mut den) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -165,7 +165,7 @@ pub struct Line2 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl fmt::Display for Line2 {
 | 
					impl fmt::Display for Line2 {
 | 
				
			||||||
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
					    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
				
			||||||
        write!(f, "{{ (x, y) = {} + {} * {} }}", self.start, self.dir, self.extent)
 | 
					        write!(f, "{{ <x, y> = {} + {} * {} }}", self.start, self.dir, self.extent)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -146,7 +146,7 @@ use std::fmt;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl<T: fmt::Display> fmt::Display for Point2<T> {
 | 
					impl<T: fmt::Display> fmt::Display for Point2<T> {
 | 
				
			||||||
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
					  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
				
			||||||
    write!(f, "({}, {})", self.x, self.y)
 | 
					    write!(f, "<{}, {}>", self.x, self.y)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -158,7 +158,7 @@ pub struct Rot2 {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl fmt::Display for Rot2 {
 | 
					impl fmt::Display for Rot2 {
 | 
				
			||||||
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
					  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
				
			||||||
    write!(f, "({}, {})", self.cos, self.sin)
 | 
					    write!(f, "<{}, {}>", self.cos, self.sin)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -167,6 +167,14 @@ impl Rot2 {
 | 
				
			|||||||
    Self { cos, sin }
 | 
					    Self { cos, sin }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pub fn up() -> Self {
 | 
				
			||||||
 | 
					    Self { cos: 0., sin: 1. }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pub fn right() -> Self {
 | 
				
			||||||
 | 
					    Self { cos: 1., sin: 0. }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pub fn from_cos_sin(cos: Scalar, sin: Scalar) -> Self {
 | 
					  pub fn from_cos_sin(cos: Scalar, sin: Scalar) -> Self {
 | 
				
			||||||
    Vec2 { x: cos, y: sin }.into()
 | 
					    Vec2 { x: cos, y: sin }.into()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -218,6 +226,10 @@ impl Rot2 {
 | 
				
			|||||||
      sin: -self.sin,
 | 
					      sin: -self.sin,
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  pub fn dot(self, v: Vec2<Value>) -> Value {
 | 
				
			||||||
 | 
					    v.x * self.cos + v.y * self.sin
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<Vec2<Scalar>> for Rot2 {
 | 
					impl From<Vec2<Scalar>> for Rot2 {
 | 
				
			||||||
 | 
				
			|||||||
@ -64,7 +64,9 @@ impl Relation for PointAngle {
 | 
				
			|||||||
        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.clone(), Region1::Full));
 | 
				
			||||||
 | 
					            trace!("PointAngle line: {}, p2 constraint: {}", line, p2.pos.constraints());
 | 
				
			||||||
            let new_constraint = p2.pos.constraints().clone().intersection(line).simplify();
 | 
					            let new_constraint = p2.pos.constraints().clone().intersection(line).simplify();
 | 
				
			||||||
 | 
					            trace!("PointAngle new_constraint: {}", new_constraint);
 | 
				
			||||||
            p2.pos.reconstrain(new_constraint);
 | 
					            p2.pos.reconstrain(new_constraint);
 | 
				
			||||||
            ResolveResult::from_r2(p2.pos.constraints())
 | 
					            ResolveResult::from_r2(p2.pos.constraints())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@ -74,7 +76,7 @@ impl Relation for PointAngle {
 | 
				
			|||||||
                // 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.clone().conj() * (p2.clone() - p1.clone());
 | 
				
			||||||
                println!("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
 | 
				
			||||||
                // } else {
 | 
					                // } else {
 | 
				
			||||||
@ -88,34 +90,29 @@ impl Relation for PointAngle {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub enum Axis {
 | 
					 | 
				
			||||||
    Vertical,
 | 
					 | 
				
			||||||
    Horizontal,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct AlignedDistance {
 | 
					pub struct AlignedDistance {
 | 
				
			||||||
    pub p1: PointRef,
 | 
					    pub p1: PointRef,
 | 
				
			||||||
    pub p2: PointRef,
 | 
					    pub p2: PointRef,
 | 
				
			||||||
    pub axis: Axis,
 | 
					    pub angle: Rot2,
 | 
				
			||||||
    pub distance: Scalar,
 | 
					    pub distance: Scalar,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl AlignedDistance {
 | 
					impl AlignedDistance {
 | 
				
			||||||
    pub fn new(p1: PointRef, p2: PointRef, axis: Axis, distance: Scalar) -> Self {
 | 
					    pub fn new(p1: PointRef, p2: PointRef, angle: Rot2, distance: Scalar) -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            p1,
 | 
					            p1,
 | 
				
			||||||
            p2,
 | 
					            p2,
 | 
				
			||||||
            axis,
 | 
					            angle,
 | 
				
			||||||
            distance,
 | 
					            distance,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_vertical(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
 | 
					    pub fn new_vertical(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
 | 
				
			||||||
        Self::new(p1, p2, Axis::Vertical, distance)
 | 
					        Self::new(p1, p2, Rot2::up(), distance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn new_horizontal(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
 | 
					    pub fn new_horizontal(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
 | 
				
			||||||
        Self::new(p1, p2, Axis::Horizontal, distance)
 | 
					        Self::new(p1, p2, Rot2::right(), distance)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -124,27 +121,20 @@ impl Relation for AlignedDistance {
 | 
				
			|||||||
        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 angle = match self.axis {
 | 
					            let angle = self.angle + Rot2::up();
 | 
				
			||||||
                Axis::Horizontal => Rot2::from_cos_sin_unchecked((0.).into(), (1.).into()),
 | 
					            let line = Region2::Line(Line2::new(p1.clone(), angle, Region1::Full)).simplify();
 | 
				
			||||||
                Axis::Vertical => Rot2::from_cos_sin_unchecked((1.).into(), (0.).into()),
 | 
					            trace!("AlignedDistance line: {}, p2 constraint: {}", line, p2.pos.constraints());
 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            let line = Region2::Line(Line2::new(p1.clone(), angle, Region1::Full));
 | 
					 | 
				
			||||||
            let new_constraint = p2.pos.constraints().clone().intersection(line).simplify();
 | 
					            let new_constraint = p2.pos.constraints().clone().intersection(line).simplify();
 | 
				
			||||||
 | 
					            trace!("AlignedDistance new_constraint: {}", new_constraint);
 | 
				
			||||||
            p2.pos.reconstrain(new_constraint);
 | 
					            p2.pos.reconstrain(new_constraint);
 | 
				
			||||||
            ResolveResult::from_r2(p2.pos.constraints())
 | 
					            ResolveResult::from_r2(p2.pos.constraints())
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        let offset: Vec2<Scalar> = match self.axis {
 | 
					        let offset: Vec2<Scalar> = self.angle * self.distance;
 | 
				
			||||||
            Axis::Horizontal => Vec2::new(self.distance.into(), (0.).into()),
 | 
					 | 
				
			||||||
            Axis::Vertical => Vec2::new((0.).into(), self.distance.into()),
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        match (&mut p1.pos.constraints(), &mut p2.pos.constraints()) {
 | 
					        match (&mut p1.pos.constraints(), &mut p2.pos.constraints()) {
 | 
				
			||||||
            (Empty, _) | (_, Empty) => ResolveResult::Overconstrained,
 | 
					            (Empty, _) | (_, Empty) => ResolveResult::Overconstrained,
 | 
				
			||||||
            (Singleton(p1), Singleton(p2)) => {
 | 
					            (Singleton(p1), Singleton(p2)) => {
 | 
				
			||||||
                let r = p2.clone() - p1.clone();
 | 
					                let r = p2.clone() - p1.clone();
 | 
				
			||||||
                let d = match self.axis {
 | 
					                let d = self.angle.dot(r);
 | 
				
			||||||
                    Axis::Horizontal => r.x,
 | 
					 | 
				
			||||||
                    Axis::Vertical => r.y,
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                // if relative_eq!(d, self.distance) {
 | 
					                // if relative_eq!(d, self.distance) {
 | 
				
			||||||
                    ResolveResult::Constrained
 | 
					                    ResolveResult::Constrained
 | 
				
			||||||
                // } else {
 | 
					                // } else {
 | 
				
			||||||
@ -157,3 +147,9 @@ impl Relation for AlignedDistance {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Midpoint {
 | 
				
			||||||
 | 
					    pub p1: PointRef,
 | 
				
			||||||
 | 
					    pub p2: PointRef,
 | 
				
			||||||
 | 
					    pub mid: PointRef,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user