Another project
0

Configure Feed

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

at main 2.4 kB View raw
1use bone_types::{Aabb3, ChordHeightTolerance, Length, Parameter, Point3, Tolerance, Vec3}; 2use serde::{Deserialize, Serialize}; 3use uom::si::length::millimeter; 4 5use crate::KernelError; 6use crate::closest::ClosestPoint3; 7use crate::curve3::{Curve3, Curve3Kind}; 8 9#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] 10#[serde(deny_unknown_fields)] 11pub struct Line3 { 12 start: Point3, 13 end: Point3, 14} 15 16impl Line3 { 17 pub fn new(start: Point3, end: Point3, 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 new_unchecked(start: Point3, end: Point3) -> Self { 26 Self { start, end } 27 } 28 29 #[must_use] 30 pub const fn start(self) -> Point3 { 31 self.start 32 } 33 34 #[must_use] 35 pub const fn end(self) -> Point3 { 36 self.end 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 as_kind(self) -> Curve3Kind { 46 Curve3Kind::Line(self) 47 } 48} 49 50impl Curve3 for Line3 { 51 fn evaluate(&self, t: Parameter) -> Point3 { 52 let (sx, sy, sz) = self.start.coords_mm(); 53 let (ex, ey, ez) = self.end.coords_mm(); 54 let u = t.value(); 55 Point3::from_mm(sx + u * (ex - sx), sy + u * (ey - sy), sz + u * (ez - sz)) 56 } 57 58 fn derivative(&self, _t: Parameter) -> Vec3 { 59 self.end - self.start 60 } 61 62 fn bounding_box(&self) -> Aabb3 { 63 Aabb3::from_corners(self.start, self.end) 64 } 65 66 fn closest_point(&self, p: Point3, _tolerance: Tolerance) -> ClosestPoint3 { 67 let d = self.end - self.start; 68 let v = p - self.start; 69 let len_sq = d.norm_squared_mm2(); 70 let t = (v.dot_mm2(d) / len_sq).clamp(0.0, 1.0); 71 let point = self.evaluate(Parameter::new(t)); 72 let dist_mm = (p - point).norm_mm(); 73 ClosestPoint3::new(Parameter::new(t), point, Length::new::<millimeter>(dist_mm)) 74 } 75 76 fn tessellate(&self, _tolerance: ChordHeightTolerance) -> Vec<Point3> { 77 vec![self.start, self.end] 78 } 79} 80 81impl core::fmt::Display for Line3 { 82 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 83 write!(f, "line3{{ {} -> {} }}", self.start, self.end) 84 } 85}