Compare commits
1 Commits
v0.35.0
...
mike/secon
Author | SHA1 | Date | |
---|---|---|---|
828a53f215 |
@ -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,
|
||||
|
@ -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(
|
||||
|
Reference in New Issue
Block a user