Add 3 point arc (#5722)

* bare minimum

* start of segment util added

* remove redundant handle

* some probably buggy handling of arc handles, can fix later

* probably bug implementation of update args, but data flow through is mostly there can fix bugs after

* fix update for arc

* fix math for center handle

* fix up length indicator

* tweak math

* stub out xState logic for arc

* more progress on adding point and click, implemented more of sketchLineHelper for arc

* small unrelated tweak

* fix up draft arc bugs

* fix arc last click

* fix draft segment animation and add comment

* add draft point snapping for arcs

* add helper stuff to arc

* clone arc point and click as base for arc-three-point

* rust change for arc three point

* can draw three point arc

* make arcTo editable

* can add new three point arc, so long as it continues existing profile

* get overlays working

* make snap to for continuing profile work for three point arcs

* add draft animation

* tangent issue fix

* action rename

* tmp test fix up

* fix silly bug

* fix couple problems causing tests to fail

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* fix up

* add delet segment test for new segments

* update docs

* draft segments should look right

* add test for dragging new segment handles

* arc tools can be chained now

* make three point arc can start a new profile (not only extend existing paths)

* add test for equiping and unequiping the tool plus drawing with it

* fix console noise

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* clean up

* update rust/docs

* put toolbar mode check into fixture

* do thing for lee

* use TEST_COLORSs

* fix colors

* don't await file write

* remove commented code

* remove unneeded template strings

* power to **2

* remove magic numbers

* more string templates

* some odd bits of clean up

* arc should be enable in dev

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: namespace-profile-ubuntu-8-cores)

* add new simulation test

* fix test code from kwark migration

* issues Frank found

* fix deleting half complete ark

* fix

* small fix on dele index

* tsc post main merge

* fix up snaping to profile start

* add cross hari for three point arc

* block snapping if it's the only segment

* add tests for canceling arcTo halfway through

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Kurt Hutten
2025-03-18 11:14:12 +11:00
committed by GitHub
parent cb0470a31d
commit e17c6e272c
32 changed files with 20989 additions and 366 deletions

View File

@ -832,6 +832,19 @@ pub enum Path {
#[ts(type = "[number, number]")]
p3: [f64; 2],
},
ArcThreePoint {
#[serde(flatten)]
base: BasePath,
/// Point 1 of the arc (base on the end of previous segment)
#[ts(type = "[number, number]")]
p1: [f64; 2],
/// Point 2 of the arc (interior kwarg)
#[ts(type = "[number, number]")]
p2: [f64; 2],
/// Point 3 of the arc (end kwarg)
#[ts(type = "[number, number]")]
p3: [f64; 2],
},
/// A path that is horizontal.
Horizontal {
#[serde(flatten)]
@ -892,6 +905,7 @@ impl From<&Path> for PathType {
Path::AngledLineTo { .. } => Self::AngledLineTo,
Path::Base { .. } => Self::Base,
Path::Arc { .. } => Self::Arc,
Path::ArcThreePoint { .. } => Self::Arc,
}
}
}
@ -908,6 +922,7 @@ impl Path {
Path::Circle { base, .. } => base.geo_meta.id,
Path::CircleThreePoint { base, .. } => base.geo_meta.id,
Path::Arc { base, .. } => base.geo_meta.id,
Path::ArcThreePoint { base, .. } => base.geo_meta.id,
}
}
@ -922,6 +937,7 @@ impl Path {
Path::Circle { base, .. } => base.tag.clone(),
Path::CircleThreePoint { base, .. } => base.tag.clone(),
Path::Arc { base, .. } => base.tag.clone(),
Path::ArcThreePoint { base, .. } => base.tag.clone(),
}
}
@ -936,6 +952,7 @@ impl Path {
Path::Circle { base, .. } => base,
Path::CircleThreePoint { base, .. } => base,
Path::Arc { base, .. } => base,
Path::ArcThreePoint { base, .. } => base,
}
}
@ -985,6 +1002,10 @@ impl Path {
// TODO: Call engine utils to figure this out.
linear_distance(self.get_from(), self.get_to())
}
Self::ArcThreePoint { .. } => {
// TODO: Call engine utils to figure this out.
linear_distance(self.get_from(), self.get_to())
}
}
}
@ -999,6 +1020,7 @@ impl Path {
Path::Circle { base, .. } => Some(base),
Path::CircleThreePoint { base, .. } => Some(base),
Path::Arc { base, .. } => Some(base),
Path::ArcThreePoint { base, .. } => Some(base),
}
}
@ -1010,6 +1032,17 @@ impl Path {
center: *center,
ccw: *ccw,
},
Path::ArcThreePoint { p1, p2, p3, .. } => {
let circle_center =
crate::std::utils::calculate_circle_from_3_points([(*p1).into(), (*p2).into(), (*p3).into()]);
let radius = linear_distance(&[circle_center.center.x, circle_center.center.y], p1);
let center_point = [circle_center.center.x, circle_center.center.y];
GetTangentialInfoFromPathsResult::Circle {
center: center_point,
ccw: true,
radius,
}
}
Path::Circle {
center, ccw, radius, ..
} => GetTangentialInfoFromPathsResult::Circle {

View File

@ -252,6 +252,17 @@ pub(crate) async fn do_post_extrude(
});
Some(extrude_surface)
}
Path::ArcThreePoint { .. } => {
let extrude_surface = ExtrudeSurface::ExtrudeArc(crate::execution::ExtrudeArc {
face_id: *actual_face_id,
tag: path.get_base().tag.clone(),
geo_meta: GeoMeta {
id: path.get_base().geo_meta.id,
metadata: path.get_base().geo_meta.metadata,
},
});
Some(extrude_surface)
}
}
} else if no_engine_commands {
// Only pre-populate the extrude surface if we are in mock mode.

View File

@ -23,8 +23,8 @@ use crate::{
std::{
args::{Args, TyF64},
utils::{
arc_angles, arc_center_and_end, calculate_circle_center, get_tangential_arc_to_info, get_x_component,
get_y_component, intersection_with_parallel_line, TangentialArcInfoInput,
arc_angles, arc_center_and_end, get_tangential_arc_to_info, get_x_component, get_y_component,
intersection_with_parallel_line, TangentialArcInfoInput,
},
},
};
@ -1682,18 +1682,7 @@ pub(crate) async fn inner_arc_to(
let interior = data.interior;
let end = data.end;
// compute the center of the circle since we do not have the value returned from the engine
let center = calculate_circle_center(start, interior, end);
// compute the radius since we do not have the value returned from the engine
// Pick any of the 3 points since they all lie along the circle
let sum_of_square_differences =
(center[0] - start[0] * center[0] - start[0]) + (center[1] - start[1] * center[1] - start[1]);
let radius = sum_of_square_differences.sqrt();
let ccw = is_ccw(start, interior, end);
let current_path = Path::Arc {
let current_path = Path::ArcThreePoint {
base: BasePath {
from: from.into(),
to: data.end,
@ -1704,9 +1693,9 @@ pub(crate) async fn inner_arc_to(
metadata: args.source_range.into(),
},
},
center,
radius,
ccw,
p1: start,
p2: interior,
p3: end,
};
let mut new_sketch = sketch.clone();
@ -1719,26 +1708,6 @@ pub(crate) async fn inner_arc_to(
Ok(new_sketch)
}
/// Returns true if the three-point arc is counterclockwise. The order of
/// parameters is critical.
///
/// | end
/// | /
/// | | / interior
/// | / /
/// | | /
/// |/_____________
/// start
///
/// If the slope of the line from start to interior is less than the slope of
/// the line from start to end, the arc is counterclockwise.
fn is_ccw(start: [f64; 2], interior: [f64; 2], end: [f64; 2]) -> bool {
let t1 = (interior[0] - start[0]) * (end[1] - start[1]);
let t2 = (end[0] - start[0]) * (interior[1] - start[1]);
// If these terms are equal, the points are collinear.
t1 > t2
}
/// Data to draw a tangential arc.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, JsonSchema, ts_rs::TS)]
#[ts(export)]