parry2d/query/point/
point_segment.rs1use crate::math::Vector;
2use crate::query::{PointProjection, PointQuery, PointQueryWithLocation};
3use crate::shape::{FeatureId, Segment, SegmentPointLocation};
4
5impl PointQuery for Segment {
6 #[inline]
7 fn project_local_point(&self, pt: Vector, solid: bool) -> PointProjection {
8 self.project_local_point_and_get_location(pt, solid).0
9 }
10
11 #[inline]
12 fn project_local_point_and_get_feature(&self, pt: Vector) -> (PointProjection, FeatureId) {
13 let (proj, loc) = self.project_local_point_and_get_location(pt, false);
14 let feature = match loc {
15 SegmentPointLocation::OnVertex(i) => FeatureId::Vertex(i),
16 SegmentPointLocation::OnEdge(..) => {
17 #[cfg(feature = "dim2")]
18 {
19 let dir = self.scaled_direction();
20 let dpt = pt - proj.point;
21 if dpt.perp_dot(dir) >= 0.0 {
22 FeatureId::Face(0)
23 } else {
24 FeatureId::Face(1)
25 }
26 }
27
28 #[cfg(feature = "dim3")]
29 {
30 FeatureId::Edge(0)
31 }
32 }
33 };
34
35 (proj, feature)
36 }
37
38 }
41
42impl PointQueryWithLocation for Segment {
43 type Location = SegmentPointLocation;
44
45 #[inline]
46 fn project_local_point_and_get_location(
47 &self,
48 pt: Vector,
49 _: bool,
50 ) -> (PointProjection, Self::Location) {
51 let ab = self.b - self.a;
52 let ap = pt - self.a;
53 let ab_ap = ab.dot(ap);
54 let sqnab = ab.length_squared();
55
56 let proj;
57 let location;
58
59 if ab_ap <= 0.0 {
60 location = SegmentPointLocation::OnVertex(0);
62 proj = self.a;
63 } else if ab_ap >= sqnab {
64 location = SegmentPointLocation::OnVertex(1);
66 proj = self.b;
67 } else {
68 assert!(sqnab != 0.0);
69
70 let u = ab_ap / sqnab;
72 let bcoords = [1.0 - u, u];
73 location = SegmentPointLocation::OnEdge(bcoords);
74 proj = self.a + ab * u;
75 }
76
77 let inside = relative_eq!(proj, pt);
79
80 (PointProjection::new(inside, proj), location)
81 }
82}