Browse Source

add AlignedDistance relation

master
Alex Mikhalev 6 years ago
parent
commit
d09f239a72
  1. 9
      src/main.rs
  2. 72
      src/relation.rs

9
src/main.rs

@ -32,12 +32,9 @@ fn main() { @@ -32,12 +32,9 @@ fn main() {
};
let c2 = relation::PointAngle::new_vertical(p1.clone(), p2.clone());
let c3 = relation::PointAngle::new_horizontal(p2.clone(), p3.clone());
// let c4 = relation::PointAngle::new_horizontal(p1.clone(), p3.clone());
let mut relations: Vec<Box<dyn Relation>> = vec![
Box::new(c1),
Box::new(c2),
Box::new(c3), /*, Box::new(c4)*/
];
let c4 = relation::AlignedDistance::new_vertical(p1.clone(), p2.clone(), 12.);
let mut relations: Vec<Box<dyn Relation>> =
vec![Box::new(c1), Box::new(c2), Box::new(c3), Box::new(c4)];
let mut constrained: Vec<Box<dyn Relation>> = Vec::new();
let mut any_underconstrained = true;
let mut any_constrained = true;

72
src/relation.rs

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
use crate::entity::{Point as PointEntity, PointRef};
use crate::math::{Line2, Point2, Region1, Region2, Rot2};
use crate::math::{Line2, Vec2, Point2, Region1, Region2, Rot2, Scalar};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ResolveResult {
@ -86,3 +86,73 @@ impl Relation for PointAngle { @@ -86,3 +86,73 @@ impl Relation for PointAngle {
}
}
}
pub enum Axis {
Vertical,
Horizontal,
}
pub struct AlignedDistance {
pub p1: PointRef,
pub p2: PointRef,
pub axis: Axis,
pub distance: Scalar,
}
impl AlignedDistance {
pub fn new(p1: PointRef, p2: PointRef, axis: Axis, distance: Scalar) -> Self {
Self {
p1,
p2,
axis,
distance,
}
}
pub fn new_vertical(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
Self::new(p1, p2, Axis::Vertical, distance)
}
pub fn new_horizontal(p1: PointRef, p2: PointRef, distance: Scalar) -> Self {
Self::new(p1, p2, Axis::Horizontal, distance)
}
}
impl Relation for AlignedDistance {
fn resolve(&self) -> ResolveResult {
use Region2::*;
let (mut p1, mut p2) = (self.p1.borrow_mut(), self.p2.borrow_mut());
let constrain_line = |p1: Point2, p2: &mut PointEntity| {
let angle = match self.axis {
Axis::Horizontal => Rot2::from_cos_sin_unchecked(0., 1.),
Axis::Vertical => Rot2::from_cos_sin_unchecked(1., 0.),
};
let line = Region2::Line(Line2::new(p1, angle, Region1::Full));
let new_constraint = p2.pos.constraints().intersect(&line);
p2.pos.reconstrain(new_constraint);
ResolveResult::from_r2(p2.pos.constraints())
};
let offset = match self.axis {
Axis::Horizontal => Vec2::new(self.distance, 0.),
Axis::Vertical => Vec2::new(0., self.distance),
};
match (&mut p1.pos.constraints(), &mut p2.pos.constraints()) {
(Empty, _) | (_, Empty) => ResolveResult::Overconstrained,
(Singleton(p1), Singleton(p2)) => {
let r = p2 - p1;
let d = match self.axis {
Axis::Horizontal => r.x,
Axis::Vertical => r.y,
};
if relative_eq!(d, self.distance) {
ResolveResult::Constrained
} else {
ResolveResult::Overconstrained
}
}
(Singleton(pos), _) => constrain_line(pos + offset, &mut *p2),
(_, Singleton(pos)) => constrain_line(pos - offset, &mut *p1),
_ => ResolveResult::Underconstrained,
}
}
}

Loading…
Cancel
Save