Another project
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.5 kB View raw
1use bone_types::{Length, Parameter, Point2, Tolerance, UnitVec2, Vec2}; 2use uom::si::length::millimeter; 3 4use crate::KernelError; 5use crate::aabb::Aabb2; 6use crate::closest::ClosestPoint2; 7use crate::curvature::Curvature; 8use crate::curve2::{Curve2, Curve2Kind}; 9 10#[derive(Copy, Clone, Debug, PartialEq)] 11pub struct Line2 { 12 start: Point2, 13 end: Point2, 14} 15 16impl Line2 { 17 pub fn new(start: Point2, end: Point2, tolerance: Tolerance) -> Result<Self, KernelError> { 18 if (end - start).norm_mm() < tolerance.value() { 19 return Err(KernelError::DegenerateLine); 20 } 21 Ok(Self { start, end }) 22 } 23 24 #[must_use] 25 pub const fn start(self) -> Point2 { 26 self.start 27 } 28 29 #[must_use] 30 pub const fn end(self) -> Point2 { 31 self.end 32 } 33 34 #[must_use] 35 pub fn length(self) -> Length { 36 (self.end - self.start).norm() 37 } 38 39 #[must_use] 40 pub fn length_mm(self) -> f64 { 41 (self.end - self.start).norm_mm() 42 } 43 44 #[must_use] 45 pub fn unit_direction(self) -> UnitVec2 { 46 let (dx, dy) = (self.end - self.start).coords_mm(); 47 let len = (dx * dx + dy * dy).sqrt(); 48 UnitVec2::new_unchecked(dx / len, dy / len) 49 } 50} 51 52impl Curve2 for Line2 { 53 fn evaluate(&self, t: Parameter) -> Point2 { 54 let (sx, sy) = self.start.coords_mm(); 55 let (ex, ey) = self.end.coords_mm(); 56 let u = t.value(); 57 Point2::from_mm(sx + u * (ex - sx), sy + u * (ey - sy)) 58 } 59 60 fn derivative(&self, _t: Parameter) -> Vec2 { 61 self.end - self.start 62 } 63 64 fn tangent(&self, _t: Parameter) -> UnitVec2 { 65 self.unit_direction() 66 } 67 68 fn curvature(&self, _t: Parameter) -> Curvature { 69 Curvature::ZERO 70 } 71 72 fn bounding_box(&self) -> Aabb2 { 73 Aabb2::from_corners(self.start, self.end) 74 } 75 76 fn closest_point(&self, p: Point2, _tolerance: Tolerance) -> ClosestPoint2 { 77 let d = self.end - self.start; 78 let v = p - self.start; 79 let len_sq = d.norm_squared_mm2(); 80 let t = (v.dot_mm2(d) / len_sq).clamp(0.0, 1.0); 81 let point = self.evaluate(Parameter::new(t)); 82 let dist_mm = (p - point).norm_mm(); 83 ClosestPoint2::new(Parameter::new(t), point, Length::new::<millimeter>(dist_mm)) 84 } 85 86 fn as_kind(&self) -> Curve2Kind { 87 Curve2Kind::Line(*self) 88 } 89} 90 91impl core::fmt::Display for Line2 { 92 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 93 write!(f, "line2{{ {} -> {} }}", self.start, self.end) 94 } 95}