Compare commits

...

1 Commits

Author SHA1 Message Date
828a53f215 stopping point 2024-10-08 18:30:02 -07:00
2 changed files with 95 additions and 7 deletions

View File

@ -21,7 +21,7 @@ use crate::{
},
std::{
utils::{
arc_angles, arc_center_and_end, get_tangent_point_from_previous_arc, get_tangential_arc_to_info,
arc_angles, arc_start_center_and_end, get_tangent_point_from_previous_arc, get_tangential_arc_to_info,
get_x_component, get_y_component, intersection_with_parallel_line, TangentialArcInfoInput,
},
Args,
@ -1485,6 +1485,17 @@ pub async fn arc(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, Kc
Ok(KclValue::new_user_val(new_sketch.meta.clone(), new_sketch))
}
/// Squared distance between two points
fn distance_squared(a: Point2d, b: Point2d) -> f64 {
let v = Point2d {
x: b.x - a.x,
y: b.y - a.y,
};
let dot = v.x * v.x + v.y * v.y;
dot
}
/// Draw a curved line segment along an imaginary circle.
/// The arc is constructed such that the current position of the sketch is
/// placed along an imaginary circle of the specified radius, at angleStart
@ -1524,9 +1535,31 @@ pub(crate) async fn inner_arc(
angle_end,
radius,
} => {
let a_start = Angle::from_degrees(*angle_start);
let a_end = Angle::from_degrees(*angle_end);
let (center, end) = arc_center_and_end(from, a_start, a_end, *radius);
let mut a_start = Angle::from_degrees(*angle_start);
let mut a_end = Angle::from_degrees(*angle_end);
//duplicating engine logic to make sure this is _exactly_ what engine is doing - mike
// if a_start.to_degrees() > a_end.to_degrees() {
// // this implies a clockwise arc, so swap the angles to a matching counter-clockwise arc
// std::mem::swap(&mut a_start, &mut a_end);
// }
let (mut start, center, mut end) = arc_start_center_and_end(from, a_start, a_end, *radius);
let desired_start = from;
let dist1 = distance_squared(start, desired_start);
let dist2 = distance_squared(end, desired_start);
#[cfg(target_arch = "wasm32")]
{
web_sys::console::log_1(&format!("testing {dist1} vs {dist2}!").into());
}
if !(dist2 < dist1) { //flipped from engine ????????????
#[cfg(target_arch = "wasm32")]
web_sys::console::log_1(&format!("swapping!").into());
std::mem::swap(&mut start, &mut end);
}
(center, a_start, a_end, *radius, end)
}
ArcData::CenterToRadius { center, to, radius } => {
@ -1671,7 +1704,7 @@ async fn inner_tangential_arc(
// but the above logic *should* capture that behavior
let start_angle = previous_end_tangent + tangent_to_arc_start_angle;
let end_angle = start_angle + offset;
let (center, to) = arc_center_and_end(from, start_angle, end_angle, radius);
let (_, center, to) = arc_start_center_and_end(from, start_angle, end_angle, radius);
args.batch_modeling_cmd(
id,

View File

@ -204,21 +204,76 @@ pub fn get_x_component(angle: Angle, y: f64) -> Point2d {
Point2d { x, y }.scale(sign)
}
pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) {
fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) {
let (_, center, end) = arc_start_center_and_end(from, start_angle, end_angle, radius);
(center, end)
}
pub fn arc_start_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d, Point2d) {
let start_angle = start_angle.to_radians();
let end_angle = end_angle.to_radians();
let eval = |t: f64, radius: f64, center: Point2d| { //UNUSED (this didn't work either for some reason.. - mike)
//HACK - using this as an example to demonstrate that even something as simple as an arc can be problematic to
//duplicate this type of logic on the frontend side because of all the little edge cases
//we must come up with a better strategy to avoid this sort of stuff in the future.
//having to manually port this sort of code directly into rust is error-prone, and
//really isn't a good usage of dev time - mike
let sin_of_pi = if ((4.0*PI).sin()).abs() > PI.sin().abs() {
4.0*PI.sin().abs()
} else {
PI.sin().abs()
};
let cos_of_pi_over_2 = if (4.5*PI).cos().abs() > (0.5*PI).sin().abs() {
(4.5*PI).cos().abs()
} else {
(0.5*PI).sin().abs()
};
let mut c = t.cos();
let mut s = t.sin();
if c.abs() <= cos_of_pi_over_2 {
c = 0.0;
s = if s < 0.0 { -1.0 } else { 1.0 };
} else if s.abs() <= sin_of_pi {
s = 0.0;
c = if c < 0.0 { -1.0 } else { 1.0 };
}
Point2d {
x: center.x + radius * c,
y: center.y + radius * s,
}
};
let center = Point2d {
x: -1.0 * (radius * start_angle.cos() - from.x),
y: -1.0 * (radius * start_angle.sin() - from.y),
};
//let start = eval(start_angle, radius, center);
//let end = eval(end_angle, radius, center);
let start = Point2d {
x: center.x + radius * start_angle.cos(),
y: center.y + radius * start_angle.sin(),
};
let end = Point2d {
x: center.x + radius * end_angle.cos(),
y: center.y + radius * end_angle.sin(),
};
(center, end)
#[cfg(target_arch = "wasm32")]
{
let start_deg = start_angle.to_degrees();
let end_deg = end_angle.to_degrees();
web_sys::console::log_1(&format!("Arc testing {start_deg:?}, {end_deg:?} -> center: {center:?}, start: {start:?} end: {end:?}").into());
}
(start, center, end)
}
pub fn arc_angles(