Skip to content

Commit

Permalink
Prefer line-length constraints with cardinality
Browse files Browse the repository at this point in the history
  • Loading branch information
Tom committed Dec 10, 2023
1 parent 26cf198 commit 96b4448
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 16 deletions.
208 changes: 208 additions & 0 deletions drawing/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1083,4 +1083,212 @@ mod tests {
*amt == 0.5,
));
}

#[test]
fn applying_horizontal_sets_line_length_cardinality_positive() {
let mut data = Data::default();
data.load(SerializedDrawing {
features: vec![
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 0.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 5.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "line".to_string(),
using_idx: vec![0, 1],
..SerializedFeature::default()
},
],
constraints: vec![SerializedConstraint {
kind: "length".to_string(),
feature_idx: vec![2],
amt: 5.0,
..SerializedConstraint::default()
}],
..SerializedDrawing::default()
})
.unwrap();

// Simulate creating a horizontal constraint
let line_fk = data.features_iter().map(|(fk, _f)| fk).nth(2).unwrap();
let mut tools = crate::tools::Toolbar::default();
crate::Handler::default().handle(
&mut data,
&mut tools,
crate::handler::ToolResponse::NewLineCardinalConstraint(line_fk, true), // true = horizontal
);

// Make sure that line length constraint got updated with an axis
assert!(matches!(
data.constraints.iter().next().unwrap().1,
Constraint::LineLength(_, c_fk, _amt, Some((Axis::LeftRight, false)), ..)
if c_fk == &line_fk,
));
}

#[test]
fn applying_horizontal_sets_line_length_cardinality_negative() {
let mut data = Data::default();
data.load(SerializedDrawing {
features: vec![
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 0.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 5.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "line".to_string(),
using_idx: vec![1, 0],
..SerializedFeature::default()
},
],
constraints: vec![SerializedConstraint {
kind: "length".to_string(),
feature_idx: vec![2],
amt: 5.0,
..SerializedConstraint::default()
}],
..SerializedDrawing::default()
})
.unwrap();

// Simulate creating a horizontal constraint
let line_fk = data.features_iter().map(|(fk, _f)| fk).nth(2).unwrap();
let mut tools = crate::tools::Toolbar::default();
crate::Handler::default().handle(
&mut data,
&mut tools,
crate::handler::ToolResponse::NewLineCardinalConstraint(line_fk, true), // true = horizontal
);

// Make sure that line length constraint got updated with an axis
assert!(matches!(
data.constraints.iter().next().unwrap().1,
Constraint::LineLength(_, c_fk, _amt, Some((Axis::LeftRight, true)), ..)
if c_fk == &line_fk,
));
}

#[test]
fn applying_line_length_to_horizontal_sets_cardinality_positive() {
let mut data = Data::default();
data.load(SerializedDrawing {
features: vec![
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 0.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 5.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "line".to_string(),
using_idx: vec![0, 1],
..SerializedFeature::default()
},
],
constraints: vec![SerializedConstraint {
kind: "horizontal".to_string(),
feature_idx: vec![2],
..SerializedConstraint::default()
}],
..SerializedDrawing::default()
})
.unwrap();

// Simulate creating a line length constraint
let line_fk = data.features_iter().map(|(fk, _f)| fk).nth(2).unwrap();
let mut tools = crate::tools::Toolbar::default();
crate::Handler::default().handle(
&mut data,
&mut tools,
crate::handler::ToolResponse::NewLineLengthConstraint(line_fk),
);

// Make sure that the only constraint is the line length constraint we want
assert!(data.constraints.iter().len() == 1);
assert!(matches!(
data.constraints.iter().next().unwrap().1,
Constraint::LineLength(_, c_fk, amt, Some((Axis::LeftRight, false)), ..)
if c_fk == &line_fk && *amt == 5.0,
));
}

#[test]
fn applying_line_length_to_horizontal_sets_cardinality_negative() {
let mut data = Data::default();
data.load(SerializedDrawing {
features: vec![
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: 0.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "pt".to_string(),
using_idx: vec![],
x: -5.0,
y: 0.0,
..SerializedFeature::default()
},
SerializedFeature {
kind: "line".to_string(),
using_idx: vec![0, 1],
..SerializedFeature::default()
},
],
constraints: vec![SerializedConstraint {
kind: "horizontal".to_string(),
feature_idx: vec![2],
..SerializedConstraint::default()
}],
..SerializedDrawing::default()
})
.unwrap();

// Simulate creating a line length constraint
let line_fk = data.features_iter().map(|(fk, _f)| fk).nth(2).unwrap();
let mut tools = crate::tools::Toolbar::default();
crate::Handler::default().handle(
&mut data,
&mut tools,
crate::handler::ToolResponse::NewLineLengthConstraint(line_fk),
);

// Make sure that the only constraint is the line length constraint we want
assert!(data.constraints.iter().len() == 1);
assert!(matches!(
data.constraints.iter().next().unwrap().1,
Constraint::LineLength(_, c_fk, amt, Some((Axis::LeftRight, true)), ..)
if c_fk == &line_fk && *amt == 5.0,
));
}
}
96 changes: 81 additions & 15 deletions drawing/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,38 +130,104 @@ impl Handler {
};

let d = p1.distance(p2);
let mut cardinality: Option<(Axis, bool)> = None;

// If we are dimensioning a line which already has a cardinality, remove the
// cardinality constraint and just roll it into our length constraint.
for ck in drawing.constraints_by_feature(&k).into_iter() {
match drawing.constraints.get_mut(ck) {
Some(Constraint::LineAlongCardinal(_, _, axis, ..)) => {
cardinality = Some((
axis.clone(),
match axis {
Axis::TopBottom => p1.y > p2.y,
Axis::LeftRight => p1.x > p2.x,
},
));
drawing.delete_constraint(ck);
}
_ => {}
}
}

drawing.add_constraint(Constraint::LineLength(
ConstraintMeta::default(),
k,
d,
None,
cardinality,
DimensionDisplay { x: 0., y: 35.0 },
));

tools.clear();
}
_ => {}
},
ToolResponse::NewLineCardinalConstraint(k, is_horizontal) => {
match drawing.features.get(k) {
Some(Feature::LineSegment(_, _f1, _f2)) => {
// TODO: Delete/modify existing constraints that would clash, if any
let want_axis = if is_horizontal {
Axis::LeftRight
} else {
Axis::TopBottom
};
let (p1, p2) = match drawing.features.get(k) {
Some(Feature::LineSegment(_, f1, f2)) => {
let (f1, f2) = (
drawing.features.get(*f1).unwrap(),
drawing.features.get(*f2).unwrap(),
);
match (f1, f2) {
(Feature::Point(_, x1, y1), Feature::Point(_, x2, y2)) => {
(egui::Pos2 { x: *x1, y: *y1 }, egui::Pos2 { x: *x2, y: *y2 })
}
_ => panic!("unexpected subkey types: {:?} & {:?}", f1, f2),
}
}
_ => unreachable!(),
};

drawing.add_constraint(Constraint::LineAlongCardinal(
ConstraintMeta::default(),
k,
if is_horizontal {
Axis::LeftRight
// Delete any existing Cardinal constraint that were opposite
let clashing_constraints: Vec<_> = drawing
.constraints_by_feature(&k)
.into_iter()
.filter_map(|ck| match drawing.constraints.get(ck) {
Some(Constraint::LineAlongCardinal(_, _, axis, ..)) => {
if axis != &want_axis {
Some(ck)
} else {
Axis::TopBottom
},
));
None
}
}
_ => None,
})
.collect();
for ck in clashing_constraints {
drawing.delete_constraint(ck);
}

tools.clear();
// Instead of making a new constraint, setup cardinality on a distance
// constraint if one exists.
for ck in drawing.constraints_by_feature(&k).into_iter() {
match drawing.constraints.get_mut(ck) {
Some(Constraint::LineLength(_, _fk, _dist, cardinality, ..)) => {
*cardinality = Some((
want_axis.clone(),
match want_axis {
Axis::TopBottom => p1.y > p2.y,
Axis::LeftRight => p1.x > p2.x,
},
));
drawing.changed_in_ui();
tools.clear();
return;
}
_ => {}
}
_ => {}
}

drawing.add_constraint(Constraint::LineAlongCardinal(
ConstraintMeta::default(),
k,
want_axis,
));
tools.clear();
}
ToolResponse::NewPointLerp(p_fk, l_fk) => {
match (drawing.features.get(p_fk), drawing.features.get(l_fk)) {
Expand Down
1 change: 0 additions & 1 deletion liquid-cad/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
* New tools:
* Circle
* Fix instability with parallel tool
* Make horizontal/vertical tool applied to a dimensioned line just set its cardinality & vice versa
* Allow equal constraints to optionally be a ratio

### Testing locally
Expand Down

0 comments on commit 96b4448

Please sign in to comment.