Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions crates/benchup-app/src/construction_guide_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ fn selected_guides_render_a_distinct_highlight() {
}

#[test]
fn tape_guide_follows_the_tape_from_an_edge_and_supports_exact_entry_and_undo() {
fn tape_guide_from_an_edge_is_parallel_to_it_and_supports_exact_entry_and_undo() {
let mut h = Harness::new();
h.app
.doc
Expand All @@ -157,14 +157,16 @@ fn tape_guide_follows_the_tape_from_an_edge_and_supports_exact_entry_and_undo()
);
let tape_direction = h.app.snap.unwrap().point.normalize();
assert!(tape_direction.x > 0.1 && tape_direction.y < -0.1);
// Dragging away from a horizontal edge offsets a horizontal guide.
let preview = h.app.measurement_guide().unwrap();
assert!(preview.direction.unwrap().distance(tape_direction) < 1e-6);
assert!(preview.direction.unwrap().dot(DVec3::X).abs() > 1. - 1e-6);
h.app.length_input = "250mm".into();
h.key(Key::Enter);
let guide = h.app.doc.model.guides.values().next().unwrap();
assert!(guide.direction.unwrap().distance(tape_direction) < 1e-6);
assert!(guide.origin.distance(tape_direction * 0.25) < 1e-6);
assert!(guide.origin.cross(guide.direction.unwrap()).length() < 1e-6);
assert!(guide.direction.unwrap().dot(DVec3::X).abs() > 1. - 1e-6);
// Exact entry is the perpendicular offset from the edge.
assert!((guide.origin.y + 0.25).abs() < 1e-6);
assert!(guide.origin.z.abs() < 1e-6);
assert_eq!(h.app.doc.model.edges, geometry.edges);
assert_eq!(h.app.doc.model.vertices, geometry.vertices);
assert!(h.app.doc.model.faces.is_empty());
Expand Down
19 changes: 16 additions & 3 deletions crates/benchup-app/src/measurement_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ pub(super) struct Measurement {
impl BenchUpApp {
/// Use the same infinite line for the live preview and the saved guide.
pub(super) fn measurement_guide(&self) -> Option<benchup_core::ConstructionGuide> {
self.measurement.as_ref()?;
let reference = self.measurement.as_ref()?.reference_direction;
let points = self.measurement_points();
let (origin, direction) = match (self.tool, points.as_slice()) {
(Tool::TapeMeasure, [start, end]) => (*end, (*end - *start).try_normalize()?),
// Like SketchUp, a tape started on an edge offsets a guide parallel
// to that edge; from a point it extends along the tape.
(Tool::TapeMeasure, [start, end]) => (
*end,
reference.or_else(|| (*end - *start).try_normalize())?,
),
(Tool::Protractor, [center, _, end]) => (*center, (*end - *center).try_normalize()?),
_ => return None,
};
Expand Down Expand Up @@ -130,7 +135,15 @@ impl BenchUpApp {
.copied()
.or(self.snap.map(|s| s.point))
.ok_or(tr!("measurement_tools.move_the_pointer_to_choose_a_direction_first"))?;
let direction = (endpoint - origin)
let mut tape = endpoint - origin;
// An edge-parallel guide is placed at the typed perpendicular offset.
if let Some(reference) = m.reference_direction {
let offset = tape - reference * tape.dot(reference);
if offset.length() > 1e-7 {
tape = offset;
}
}
let direction = tape
.try_normalize()
.ok_or(tr!("measurement_tools.move_the_pointer_to_choose_a_direction_first"))?;
Ok(origin + direction * length)
Expand Down
Loading