Compare commits
	
		
			1 Commits
		
	
	
		
			jtran/unit
			...
			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
	