diff --git a/src/wasm-lib/kcl/src/executor.rs b/src/wasm-lib/kcl/src/executor.rs index a0865fa32..5d713e384 100644 --- a/src/wasm-lib/kcl/src/executor.rs +++ b/src/wasm-lib/kcl/src/executor.rs @@ -348,7 +348,7 @@ impl SourceRange { } } -#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, ts_rs::TS, JsonSchema)] +#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy, ts_rs::TS, JsonSchema)] #[ts(export)] pub struct Point2d { pub x: f64, @@ -379,6 +379,16 @@ impl From for kittycad::types::Point2D { } } +impl Point2d { + pub const ZERO: Self = Self { x: 0.0, y: 0.0 }; + pub fn scale(self, scalar: f64) -> Self { + Self { + x: self.x * scalar, + y: self.y * scalar, + } + } +} + #[derive(Debug, Deserialize, Serialize, PartialEq, Clone, ts_rs::TS, JsonSchema)] #[ts(export)] pub struct Point3d { diff --git a/src/wasm-lib/kcl/src/std/segment.rs b/src/wasm-lib/kcl/src/std/segment.rs index 3c67aa61a..3606d0e4b 100644 --- a/src/wasm-lib/kcl/src/std/segment.rs +++ b/src/wasm-lib/kcl/src/std/segment.rs @@ -7,7 +7,7 @@ use schemars::JsonSchema; use crate::{ errors::{KclError, KclErrorDetails}, executor::{MemoryItem, SketchGroup}, - std::{utils::get_angle, Args}, + std::{utils::Angle, Args}, }; /// Returns the segment end of x. @@ -174,9 +174,9 @@ fn inner_segment_angle(segment_name: &str, sketch_group: SketchGroup, args: &mut })?; let line = path.get_base(); - let result = get_angle(&line.from, &line.to); + let result = Angle::between(line.from.into(), line.to.into()); - Ok(result) + Ok(result.degrees()) } /// Returns the angle to match the given length for x. diff --git a/src/wasm-lib/kcl/src/std/sketch.rs b/src/wasm-lib/kcl/src/std/sketch.rs index 1f05b54b8..540929815 100644 --- a/src/wasm-lib/kcl/src/std/sketch.rs +++ b/src/wasm-lib/kcl/src/std/sketch.rs @@ -15,6 +15,8 @@ use crate::{ }, }; +use super::utils::Angle; + /// Data to draw a line to a point. #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[ts(export)] @@ -392,13 +394,13 @@ fn inner_angled_line_of_x_length( AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]), }; - let to = get_y_component(angle, length); + let to = get_y_component(Angle::from_degrees(angle), length); let new_sketch_group = inner_line( if let AngledLineData::AngleWithTag { tag, .. } = data { - LineData::PointWithTag { to, tag } + LineData::PointWithTag { to: to.into(), tag } } else { - LineData::Point(to) + LineData::Point(to.into()) }, sketch_group, args, @@ -487,13 +489,13 @@ fn inner_angled_line_of_y_length( AngledLineData::AngleAndLength(angle_and_length) => (angle_and_length[0], angle_and_length[1]), }; - let to = get_x_component(angle, length); + let to = get_x_component(Angle::from_degrees(angle), length); let new_sketch_group = inner_line( if let AngledLineData::AngleWithTag { tag, .. } = data { - LineData::PointWithTag { to, tag } + LineData::PointWithTag { to: to.into(), tag } } else { - LineData::Point(to) + LineData::Point(to.into()) }, sketch_group, args, @@ -588,16 +590,16 @@ fn inner_angled_line_that_intersects( let from = sketch_group.get_coords_from_paths()?; let to = intersection_with_parallel_line( - &[intersect_path.from, intersect_path.to], + &[intersect_path.from.into(), intersect_path.to.into()], data.offset.unwrap_or_default(), data.angle, - from.into(), + from, ); let line_to_data = if let Some(tag) = data.tag { - LineToData::PointWithTag { to, tag } + LineToData::PointWithTag { to: to.into(), tag } } else { - LineToData::Point(to) + LineToData::Point(to.into()) }; let new_sketch_group = inner_line_to(line_to_data, sketch_group, args)?; @@ -766,7 +768,7 @@ pub fn arc(args: &mut Args) -> Result { name = "arc", }] fn inner_arc(data: ArcData, sketch_group: SketchGroup, args: &mut Args) -> Result { - let from = sketch_group.get_coords_from_paths()?; + let from: Point2d = sketch_group.get_coords_from_paths()?; let (center, angle_start, angle_end, radius, end) = match &data { ArcData::AnglesAndRadiusWithTag { @@ -775,23 +777,27 @@ fn inner_arc(data: ArcData, sketch_group: SketchGroup, args: &mut Args) -> Resul radius, .. } => { - let (center, end) = arc_center_and_end(&from, *angle_start, *angle_end, *radius); - (center, *angle_start, *angle_end, *radius, end) + 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); + (center, a_start, a_end, *radius, end) } ArcData::AnglesAndRadius { angle_start, angle_end, radius, } => { - let (center, end) = arc_center_and_end(&from, *angle_start, *angle_end, *radius); - (center, *angle_start, *angle_end, *radius, end) + 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); + (center, a_start, a_end, *radius, end) } ArcData::CenterToRadiusWithTag { center, to, radius, .. } => { - let (angle_start, angle_end) = arc_angles(&from, ¢er.into(), &to.into(), *radius, args.source_range)?; + let (angle_start, angle_end) = arc_angles(from, center.into(), to.into(), *radius, args.source_range)?; (center.into(), angle_start, angle_end, *radius, to.into()) } ArcData::CenterToRadius { center, to, radius } => { - let (angle_start, angle_end) = arc_angles(&from, ¢er.into(), &to.into(), *radius, args.source_range)?; + let (angle_start, angle_end) = arc_angles(from, center.into(), to.into(), *radius, args.source_range)?; (center.into(), angle_start, angle_end, *radius, to.into()) } }; @@ -803,8 +809,8 @@ fn inner_arc(data: ArcData, sketch_group: SketchGroup, args: &mut Args) -> Resul ModelingCmd::ExtendPath { path: sketch_group.id, segment: kittycad::types::PathSegment::Arc { - angle_start, - angle_end, + angle_start: angle_start.degrees(), + angle_end: angle_end.degrees(), center: center.into(), radius, }, diff --git a/src/wasm-lib/kcl/src/std/utils.rs b/src/wasm-lib/kcl/src/std/utils.rs index 6d3582b08..3eb4b2a57 100644 --- a/src/wasm-lib/kcl/src/std/utils.rs +++ b/src/wasm-lib/kcl/src/std/utils.rs @@ -1,30 +1,85 @@ +use std::f64::consts::PI; + use crate::{ errors::{KclError, KclErrorDetails}, executor::{Point2d, SourceRange}, }; -pub fn get_angle(a: &[f64; 2], b: &[f64; 2]) -> f64 { - let x = b[0] - a[0]; - let y = b[1] - a[1]; - normalise_angle(y.atan2(x).to_degrees()) +#[derive(Clone, Copy, Default, PartialOrd, PartialEq, Debug)] +pub struct Angle { + degrees: f64, } -pub fn normalise_angle(angle: f64) -> f64 { - let result = ((angle % 360.0) + 360.0) % 360.0; - if result > 180.0 { - result - 360.0 - } else { - result +impl Angle { + const ZERO: Self = Self { degrees: 0.0 }; + /// Make an angle of the given degrees. + pub fn from_degrees(degrees: f64) -> Self { + Self { degrees } + } + /// Make an angle of the given radians. + pub fn from_radians(radians: f64) -> Self { + Self::from_degrees(radians.to_degrees()) + } + /// Get the angle in degrees + pub fn degrees(&self) -> f64 { + self.degrees + } + /// Get the angle in radians + pub fn radians(&self) -> f64 { + self.degrees.to_radians() + } + /// Get the angle between these points + pub fn between(a: Point2d, b: Point2d) -> Self { + let x = b.x - a.x; + let y = b.y - a.y; + Self::from_radians(y.atan2(x)).normalize() + } + /// Normalize the angle + pub fn normalize(self) -> Self { + let angle = self.degrees(); + let result = ((angle % 360.0) + 360.0) % 360.0; + Self::from_degrees(if result > 180.0 { result - 360.0 } else { result }) + } + /// Gives the ▲-angle between from and to angles (shortest path), use radians. + /// + /// Sign of the returned angle denotes direction, positive means counterClockwise 🔄 + /// # Examples + /// + /// ``` + /// use std::f64::consts::PI; + /// use kcl_lib::std::utils::Angle; + /// + /// assert_eq!( + /// Angle::delta(Angle::from_radians(PI / 8.0), Angle::from_radians(PI / 4.0)), + /// Angle::from_radians(PI / 8.0) + /// ); + /// ``` + #[allow(dead_code)] + pub fn delta(from_angle: Self, to_angle: Self) -> Self { + let norm_from_angle = normalize_rad(from_angle.radians()); + let norm_to_angle = normalize_rad(to_angle.radians()); + let provisional = norm_to_angle - norm_from_angle; + + if provisional > -PI && provisional <= PI { + return Angle::from_radians(provisional); + } + if provisional > PI { + return Angle::from_radians(provisional - 2.0 * PI); + } + if provisional < -PI { + return Angle::from_radians(provisional + 2.0 * PI); + } + Angle::ZERO } } #[allow(dead_code)] -pub fn clockwise_sign(points: &[[f64; 2]]) -> i32 { +pub fn clockwise_sign(points: &[Point2d]) -> i32 { let mut sum = 0.0; for i in 0..points.len() { let current_point = points[i]; let next_point = points[(i + 1) % points.len()]; - sum += (next_point[0] - current_point[0]) * (next_point[1] + current_point[1]); + sum += (next_point.x - current_point.x) * (next_point.y + current_point.y); } if sum >= 0.0 { 1 @@ -35,139 +90,145 @@ pub fn clockwise_sign(points: &[[f64; 2]]) -> i32 { #[allow(dead_code)] pub fn normalize_rad(angle: f64) -> f64 { - let draft = angle % (2.0 * std::f64::consts::PI); + let draft = angle % (2.0 * PI); if draft < 0.0 { - draft + 2.0 * std::f64::consts::PI + draft + 2.0 * PI } else { draft } } -/// Gives the ▲-angle between from and to angles (shortest path), use radians. -/// -/// Sign of the returned angle denotes direction, positive means counterClockwise 🔄 -/// # Examples -/// -/// ``` -/// assert_eq!( -/// kcl_lib::std::utils::delta_angle(std::f64::consts::PI / 8.0, std::f64::consts::PI / 4.0), -/// std::f64::consts::PI / 8.0 -/// ); -/// ``` -#[allow(dead_code)] -pub fn delta_angle(from_angle: f64, to_angle: f64) -> f64 { - let norm_from_angle = normalize_rad(from_angle); - let norm_to_angle = normalize_rad(to_angle); - let provisional = norm_to_angle - norm_from_angle; - - if provisional > -std::f64::consts::PI && provisional <= std::f64::consts::PI { - return provisional; - } - if provisional > std::f64::consts::PI { - return provisional - 2.0 * std::f64::consts::PI; - } - if provisional < -std::f64::consts::PI { - return provisional + 2.0 * std::f64::consts::PI; - } - 0.0 -} - /// Calculates the distance between two points. /// /// # Examples /// /// ``` +/// use kcl_lib::executor::Point2d; +/// /// assert_eq!( -/// kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[0.0, 5.0]), +/// kcl_lib::std::utils::distance_between_points(Point2d::ZERO, Point2d{x: 0.0, y: 5.0}), /// 5.0 /// ); /// assert_eq!( -/// kcl_lib::std::utils::distance_between_points(&[0.0, 0.0], &[3.0, 4.0]), +/// kcl_lib::std::utils::distance_between_points(Point2d::ZERO, Point2d{x: 3.0, y: 4.0}), /// 5.0 /// ); /// ``` #[allow(dead_code)] -pub fn distance_between_points(point_a: &[f64; 2], point_b: &[f64; 2]) -> f64 { - let x1 = point_a[0]; - let y1 = point_a[1]; - let x2 = point_b[0]; - let y2 = point_b[1]; +pub fn distance_between_points(point_a: Point2d, point_b: Point2d) -> f64 { + let x1 = point_a.x; + let y1 = point_a.y; + let x2 = point_b.x; + let y2 = point_b.y; ((y2 - y1).powi(2) + (x2 - x1).powi(2)).sqrt() } -pub fn calculate_intersection_of_two_lines(line1: &[[f64; 2]; 2], line2_angle: f64, line2_point: [f64; 2]) -> [f64; 2] { - let line2_point_b = [ - line2_point[0] + f64::cos(line2_angle.to_radians()) * 10.0, - line2_point[1] + f64::sin(line2_angle.to_radians()) * 10.0, - ]; +pub fn calculate_intersection_of_two_lines(line1: &[Point2d; 2], line2_angle: f64, line2_point: Point2d) -> Point2d { + let line2_point_b = Point2d { + x: line2_point.x + f64::cos(line2_angle.to_radians()) * 10.0, + y: line2_point.y + f64::sin(line2_angle.to_radians()) * 10.0, + }; intersect(line1[0], line1[1], line2_point, line2_point_b) } -pub fn intersect(p1: [f64; 2], p2: [f64; 2], p3: [f64; 2], p4: [f64; 2]) -> [f64; 2] { - let slope = |p1: [f64; 2], p2: [f64; 2]| (p1[1] - p2[1]) / (p1[0] - p2[0]); - let constant = |p1: [f64; 2], p2: [f64; 2]| p1[1] - slope(p1, p2) * p1[0]; - let get_y = |for_x: f64, p1: [f64; 2], p2: [f64; 2]| slope(p1, p2) * for_x + constant(p1, p2); +pub fn intersect(p1: Point2d, p2: Point2d, p3: Point2d, p4: Point2d) -> Point2d { + let slope = |p1: Point2d, p2: Point2d| (p1.y - p2.y) / (p1.x - p2.x); + let constant = |p1: Point2d, p2: Point2d| p1.y - slope(p1, p2) * p1.x; + let get_y = |for_x: f64, p1: Point2d, p2: Point2d| slope(p1, p2) * for_x + constant(p1, p2); - if p1[0] == p2[0] { - return [p1[0], get_y(p1[0], p3, p4)]; + if p1.x == p2.x { + return Point2d { + x: p1.x, + y: get_y(p1.x, p3, p4), + }; } - if p3[0] == p4[0] { - return [p3[0], get_y(p3[0], p1, p2)]; + if p3.x == p4.x { + return Point2d { + x: p3.x, + y: get_y(p3.x, p1, p2), + }; } let x = (constant(p3, p4) - constant(p1, p2)) / (slope(p1, p2) - slope(p3, p4)); let y = get_y(x, p1, p2); - [x, y] + Point2d { x, y } } pub fn intersection_with_parallel_line( - line1: &[[f64; 2]; 2], + line1: &[Point2d; 2], line1_offset: f64, line2_angle: f64, - line2_point: [f64; 2], -) -> [f64; 2] { + line2_point: Point2d, +) -> Point2d { calculate_intersection_of_two_lines(&offset_line(line1_offset, line1[0], line1[1]), line2_angle, line2_point) } -fn offset_line(offset: f64, p1: [f64; 2], p2: [f64; 2]) -> [[f64; 2]; 2] { - if p1[0] == p2[0] { - let direction = (p1[1] - p2[1]).signum(); - return [[p1[0] + offset * direction, p1[1]], [p2[0] + offset * direction, p2[1]]]; +fn offset_line(offset: f64, p1: Point2d, p2: Point2d) -> [Point2d; 2] { + if p1.x == p2.x { + let direction = (p1.y - p2.y).signum(); + return [ + Point2d { + x: p1.x + offset * direction, + y: p1.y, + }, + Point2d { + x: p2.x + offset * direction, + y: p2.y, + }, + ]; } - if p1[1] == p2[1] { - let direction = (p2[0] - p1[0]).signum(); - return [[p1[0], p1[1] + offset * direction], [p2[0], p2[1] + offset * direction]]; + if p1.y == p2.y { + let direction = (p2.x - p1.x).signum(); + return [ + Point2d { + x: p1.x, + y: p1.y + offset * direction, + }, + Point2d { + x: p2.x, + y: p2.y + offset * direction, + }, + ]; } - let x_offset = offset / f64::sin(f64::atan2(p1[1] - p2[1], p1[0] - p2[0])); - [[p1[0] + x_offset, p1[1]], [p2[0] + x_offset, p2[1]]] + let x_offset = offset / f64::sin(f64::atan2(p1.y - p2.y, p1.x - p2.x)); + [ + Point2d { + x: p1.x + x_offset, + y: p1.y, + }, + Point2d { + x: p2.x + x_offset, + y: p2.y, + }, + ] } -pub fn get_y_component(angle_degree: f64, x_component: f64) -> [f64; 2] { - let normalised_angle = ((angle_degree % 360.0) + 360.0) % 360.0; // between 0 and 360 - let y_component = x_component * f64::tan(normalised_angle.to_radians()); +pub fn get_y_component(angle: Angle, x: f64) -> Point2d { + let normalised_angle = ((angle.degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360 + let y = x * f64::tan(normalised_angle.to_radians()); let sign = if normalised_angle > 90.0 && normalised_angle <= 270.0 { -1.0 } else { 1.0 }; - [sign * x_component, sign * y_component] + Point2d { x, y }.scale(sign) } -pub fn get_x_component(angle_degree: f64, y_component: f64) -> [f64; 2] { - let normalised_angle = ((angle_degree % 360.0) + 360.0) % 360.0; // between 0 and 360 - let x_component = y_component / f64::tan(normalised_angle.to_radians()); +pub fn get_x_component(angle: Angle, y: f64) -> Point2d { + let normalised_angle = ((angle.degrees() % 360.0) + 360.0) % 360.0; // between 0 and 360 + let x = y / f64::tan(normalised_angle.to_radians()); let sign = if normalised_angle > 180.0 && normalised_angle <= 360.0 { -1.0 } else { 1.0 }; - [sign * x_component, sign * y_component] + Point2d { x, y }.scale(sign) } -pub fn arc_center_and_end(from: &Point2d, start_angle_deg: f64, end_angle_deg: f64, radius: f64) -> (Point2d, Point2d) { - let start_angle = start_angle_deg.to_radians(); - let end_angle = end_angle_deg.to_radians(); +pub fn arc_center_and_end(from: Point2d, start_angle: Angle, end_angle: Angle, radius: f64) -> (Point2d, Point2d) { + let start_angle = start_angle.radians(); + let end_angle = end_angle.radians(); let center = Point2d { x: -1.0 * (radius * start_angle.cos() - from.x), @@ -183,12 +244,12 @@ pub fn arc_center_and_end(from: &Point2d, start_angle_deg: f64, end_angle_deg: f } pub fn arc_angles( - from: &Point2d, - to: &Point2d, - center: &Point2d, + from: Point2d, + to: Point2d, + center: Point2d, radius: f64, source_range: SourceRange, -) -> Result<(f64, f64), KclError> { +) -> Result<(Angle, Angle), KclError> { // First make sure that the points are on the circumference of the circle. // If not, we'll return an error. if !is_on_circumference(center, from, radius) { @@ -214,13 +275,10 @@ pub fn arc_angles( let start_angle = (from.y - center.y).atan2(from.x - center.x); let end_angle = (to.y - center.y).atan2(to.x - center.x); - let start_angle_deg = start_angle.to_degrees(); - let end_angle_deg = end_angle.to_degrees(); - - Ok((start_angle_deg, end_angle_deg)) + Ok((Angle::from_radians(start_angle), Angle::from_radians(end_angle))) } -pub fn is_on_circumference(center: &Point2d, point: &Point2d, radius: f64) -> bool { +pub fn is_on_circumference(center: Point2d, point: Point2d, radius: f64) -> bool { let dx = point.x - center.x; let dy = point.y - center.y; @@ -237,7 +295,7 @@ mod tests { // Here you can bring your functions into scope use pretty_assertions::assert_eq; - use super::{get_x_component, get_y_component}; + use super::{get_x_component, get_y_component, Angle}; use crate::executor::SourceRange; static EACH_QUAD: [(i32, [i32; 2]); 12] = [ @@ -261,28 +319,28 @@ mod tests { let mut results = Vec::new(); for &(angle, expected_result) in EACH_QUAD.iter() { - let res = get_y_component(angle as f64, 1.0); - results.push([res[0].round() as i32, res[1].round() as i32]); + let res = get_y_component(Angle::from_degrees(angle as f64), 1.0); + results.push([res.x.round() as i32, res.y.round() as i32]); expected.push(expected_result); } assert_eq!(results, expected); - let result = get_y_component(0.0, 1.0); - assert_eq!(result[0] as i32, 1); - assert_eq!(result[1] as i32, 0); + let result = get_y_component(Angle::ZERO, 1.0); + assert_eq!(result.x as i32, 1); + assert_eq!(result.y as i32, 0); - let result = get_y_component(90.0, 1.0); - assert_eq!(result[0] as i32, 1); - assert!(result[1] > 100000.0); + let result = get_y_component(Angle::from_degrees(90.0), 1.0); + assert_eq!(result.x as i32, 1); + assert!(result.y > 100000.0); - let result = get_y_component(180.0, 1.0); - assert_eq!(result[0] as i32, -1); - assert!((result[1] - 0.0).abs() < f64::EPSILON); + let result = get_y_component(Angle::from_degrees(180.0), 1.0); + assert_eq!(result.x as i32, -1); + assert!((result.y - 0.0).abs() < f64::EPSILON); - let result = get_y_component(270.0, 1.0); - assert_eq!(result[0] as i32, -1); - assert!(result[1] < -100000.0); + let result = get_y_component(Angle::from_degrees(270.0), 1.0); + assert_eq!(result.x as i32, -1); + assert!(result.y < -100000.0); } #[test] @@ -291,45 +349,60 @@ mod tests { let mut results = Vec::new(); for &(angle, expected_result) in EACH_QUAD.iter() { - let res = get_x_component(angle as f64, 1.0); - results.push([res[0].round() as i32, res[1].round() as i32]); + let res = get_x_component(Angle::from_degrees(angle as f64), 1.0); + results.push([res.x.round() as i32, res.y.round() as i32]); expected.push(expected_result); } assert_eq!(results, expected); - let result = get_x_component(0.0, 1.0); - assert!(result[0] > 100000.0); - assert_eq!(result[1] as i32, 1); + let result = get_x_component(Angle::ZERO, 1.0); + assert!(result.x > 100000.0); + assert_eq!(result.y as i32, 1); - let result = get_x_component(90.0, 1.0); - assert!((result[0] - 0.0).abs() < f64::EPSILON); - assert_eq!(result[1] as i32, 1); + let result = get_x_component(Angle::from_degrees(90.0), 1.0); + assert!((result.x - 0.0).abs() < f64::EPSILON); + assert_eq!(result.y as i32, 1); - let result = get_x_component(180.0, 1.0); - assert!(result[0] < -100000.0); - assert_eq!(result[1] as i32, 1); + let result = get_x_component(Angle::from_degrees(180.0), 1.0); + assert!(result.x < -100000.0); + assert_eq!(result.y as i32, 1); - let result = get_x_component(270.0, 1.0); - assert!((result[0] - 0.0).abs() < f64::EPSILON); - assert_eq!(result[1] as i32, -1); + let result = get_x_component(Angle::from_degrees(270.0), 1.0); + assert!((result.x - 0.0).abs() < f64::EPSILON); + assert_eq!(result.y as i32, -1); } #[test] fn test_arc_center_and_end() { - let (center, end) = super::arc_center_and_end(&super::Point2d { x: 0.0, y: 0.0 }, 0.0, 90.0, 1.0); + let (center, end) = super::arc_center_and_end( + super::Point2d { x: 0.0, y: 0.0 }, + Angle::ZERO, + Angle::from_degrees(90.0), + 1.0, + ); assert_eq!(center.x.round(), -1.0); assert_eq!(center.y, 0.0); assert_eq!(end.x.round(), -1.0); assert_eq!(end.y, 1.0); - let (center, end) = super::arc_center_and_end(&super::Point2d { x: 0.0, y: 0.0 }, 0.0, 180.0, 1.0); + let (center, end) = super::arc_center_and_end( + super::Point2d { x: 0.0, y: 0.0 }, + Angle::ZERO, + Angle::from_degrees(180.0), + 1.0, + ); assert_eq!(center.x.round(), -1.0); assert_eq!(center.y, 0.0); assert_eq!(end.x.round(), -2.0); assert_eq!(end.y.round(), 0.0); - let (center, end) = super::arc_center_and_end(&super::Point2d { x: 0.0, y: 0.0 }, 0.0, 180.0, 10.0); + let (center, end) = super::arc_center_and_end( + super::Point2d { x: 0.0, y: 0.0 }, + Angle::ZERO, + Angle::from_degrees(180.0), + 10.0, + ); assert_eq!(center.x.round(), -10.0); assert_eq!(center.y, 0.0); assert_eq!(end.x.round(), -20.0); @@ -339,42 +412,42 @@ mod tests { #[test] fn test_arc_angles() { let (angle_start, angle_end) = super::arc_angles( - &super::Point2d { x: 0.0, y: 0.0 }, - &super::Point2d { x: -1.0, y: 1.0 }, - &super::Point2d { x: -1.0, y: 0.0 }, + super::Point2d { x: 0.0, y: 0.0 }, + super::Point2d { x: -1.0, y: 1.0 }, + super::Point2d { x: -1.0, y: 0.0 }, 1.0, SourceRange(Default::default()), ) .unwrap(); - assert_eq!(angle_start.round(), 0.0); - assert_eq!(angle_end.round(), 90.0); + assert_eq!(angle_start.degrees().round(), 0.0); + assert_eq!(angle_end.degrees().round(), 90.0); let (angle_start, angle_end) = super::arc_angles( - &super::Point2d { x: 0.0, y: 0.0 }, - &super::Point2d { x: -2.0, y: 0.0 }, - &super::Point2d { x: -1.0, y: 0.0 }, + super::Point2d { x: 0.0, y: 0.0 }, + super::Point2d { x: -2.0, y: 0.0 }, + super::Point2d { x: -1.0, y: 0.0 }, 1.0, SourceRange(Default::default()), ) .unwrap(); - assert_eq!(angle_start.round(), 0.0); - assert_eq!(angle_end.round(), 180.0); + assert_eq!(angle_start.degrees().round(), 0.0); + assert_eq!(angle_end.degrees().round(), 180.0); let (angle_start, angle_end) = super::arc_angles( - &super::Point2d { x: 0.0, y: 0.0 }, - &super::Point2d { x: -20.0, y: 0.0 }, - &super::Point2d { x: -10.0, y: 0.0 }, + super::Point2d { x: 0.0, y: 0.0 }, + super::Point2d { x: -20.0, y: 0.0 }, + super::Point2d { x: -10.0, y: 0.0 }, 10.0, SourceRange(Default::default()), ) .unwrap(); - assert_eq!(angle_start.round(), 0.0); - assert_eq!(angle_end.round(), 180.0); + assert_eq!(angle_start.degrees().round(), 0.0); + assert_eq!(angle_end.degrees().round(), 180.0); let result = super::arc_angles( - &super::Point2d { x: 0.0, y: 5.0 }, - &super::Point2d { x: 5.0, y: 5.0 }, - &super::Point2d { x: 10.0, y: -10.0 }, + super::Point2d { x: 0.0, y: 5.0 }, + super::Point2d { x: 5.0, y: 5.0 }, + super::Point2d { x: 10.0, y: -10.0 }, 10.0, SourceRange(Default::default()), ); @@ -384,7 +457,7 @@ mod tests { } else { panic!("Expected error"); } - assert_eq!(angle_start.round(), 0.0); - assert_eq!(angle_end.round(), 180.0); + assert_eq!(angle_start.degrees().round(), 0.0); + assert_eq!(angle_end.degrees().round(), 180.0); } }