1- use std:: dbg;
2-
31use crate :: math:: { Point , Real , Vector , DIM } ;
42use crate :: query:: { PointProjection , PointQuery , PointQueryWithLocation } ;
53use crate :: shape:: { FeatureId , Segment , Triangle , TrianglePointLocation } ;
@@ -57,60 +55,20 @@ impl PointQueryWithLocation for Triangle {
5755 type Location = TrianglePointLocation ;
5856
5957 #[ inline]
60- fn project_local_point_and_get_location (
61- & self ,
62- pt : & Point < Real > ,
63- solid : bool ,
64- ) -> ( PointProjection , Self :: Location ) {
58+ fn triangle ( & self , pt : & Point < Real > , solid : bool ) -> ( PointProjection , Self :: Location ) {
6559 // To understand the ideas, consider reading the slides below
6660 // https://box2d.org/files/ErinCatto_GJK_GDC2010.pdf
6761
6862 let a = self . a ;
6963 let b = self . b ;
7064 let c = self . c ;
7165
72- // Additional checks for same point triangles
73- // TODO: Check for flat triangles (collinear points) ?
74- if a == b || b == c {
75- let pos = Segment :: new ( a, c) . project_local_point_and_get_location ( pt, solid) ;
76-
77- return (
78- pos. 0 ,
79- match pos. 1 {
80- crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
81- TrianglePointLocation :: OnVertex ( if v == 1 { 2 } else { 0 } )
82- }
83- crate :: shape:: SegmentPointLocation :: OnEdge ( v) => TrianglePointLocation :: OnEdge (
84- // could be 0 or 1, but we're on a flat triangle which is a bit degenerate.
85- 1 , v,
86- ) ,
87- } ,
88- ) ;
89- }
90- if a == c {
91- let pos = Segment :: new ( a, b) . project_local_point_and_get_location ( pt, solid) ;
92-
93- return (
94- pos. 0 ,
95- match pos. 1 {
96- crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
97- TrianglePointLocation :: OnVertex ( v)
98- }
99- crate :: shape:: SegmentPointLocation :: OnEdge ( v) => TrianglePointLocation :: OnEdge (
100- // could be 1 or 2, but we're on a flat triangle which is a bit degenerate.
101- 0 , v,
102- ) ,
103- } ,
104- ) ;
105- }
106-
10766 let ab = b - a;
10867 let ac = c - a;
10968 let ap = pt - a;
110- std :: dbg! ( ab , ac , ap ) ;
69+
11170 let ab_ap = ab. dot ( & ap) ;
11271 let ac_ap = ac. dot ( & ap) ;
113- std:: dbg!( ab_ap, ac_ap) ;
11472
11573 if ab_ap <= 0.0 && ac_ap <= 0.0 {
11674 // Voronoï region of `a`.
@@ -120,7 +78,6 @@ impl PointQueryWithLocation for Triangle {
12078 let bp = pt - b;
12179 let ab_bp = ab. dot ( & bp) ;
12280 let ac_bp = ac. dot ( & bp) ;
123- std:: dbg!( bp, ab_bp, ac_bp) ;
12481
12582 if ab_bp >= 0.0 && ac_bp <= ab_bp {
12683 // Voronoï region of `b`.
@@ -130,7 +87,6 @@ impl PointQueryWithLocation for Triangle {
13087 let cp = pt - c;
13188 let ab_cp = ab. dot ( & cp) ;
13289 let ac_cp = ac. dot ( & cp) ;
133- std:: dbg!( cp, ab_cp, ac_cp) ;
13490
13591 if ac_cp >= 0.0 && ab_cp <= ac_cp {
13692 // Voronoï region of `c`.
@@ -256,23 +212,73 @@ impl PointQueryWithLocation for Triangle {
256212 ) ;
257213 }
258214 ProjectionInfo :: OnFace ( face_side, va, vb, vc) => {
259- // Voronoï region of the face.
260- if DIM != 2 {
261- // NOTE: in some cases, numerical instability
262- // may result in the denominator being zero
263- // when the triangle is nearly degenerate.
264- if va + vb + vc != 0.0 {
265- let denom = 1.0 / ( va + vb + vc) ;
266- let v = vb * denom;
267- let w = vc * denom;
268- let bcoords = [ 1.0 - v - w, v, w] ;
269- let res = a + ab * v + ac * w;
270-
215+ let inv_denom = va + vb + vc;
216+ if inv_denom == 0.0 {
217+ // The triangle is degenerate (the three points are collinear).
218+ // So we find the longest segment and project point on it.
219+
220+ // TODO: this can probably be optimized using data we already have ?
221+ let length_sq_ab = ab. magnitude_squared ( ) ;
222+ let length_sq_ac = ac. magnitude_squared ( ) ;
223+ let length_sq_bc = bc. magnitude_squared ( ) ;
224+
225+ if length_sq_ab >= length_sq_ac && length_sq_ab >= length_sq_bc {
226+ // AB is longest edge.
227+ let pos =
228+ Segment :: new ( a, b) . project_local_point_and_get_location ( pt, solid) ;
229+ return (
230+ pos. 0 ,
231+ match pos. 1 {
232+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
233+ TrianglePointLocation :: OnVertex ( v)
234+ }
235+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
236+ TrianglePointLocation :: OnEdge ( 0 , v)
237+ }
238+ } ,
239+ ) ;
240+ } else if length_sq_ac >= length_sq_ab && length_sq_ac >= length_sq_bc {
241+ // AC is longest edge.
242+ let pos =
243+ Segment :: new ( a, c) . project_local_point_and_get_location ( pt, solid) ;
244+ return (
245+ pos. 0 ,
246+ match pos. 1 {
247+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
248+ TrianglePointLocation :: OnVertex ( v)
249+ }
250+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
251+ TrianglePointLocation :: OnEdge ( 1 , v)
252+ }
253+ } ,
254+ ) ;
255+ } else {
256+ // BC is longest edge.
257+ let pos =
258+ Segment :: new ( b, c) . project_local_point_and_get_location ( pt, solid) ;
271259 return (
272- compute_result ( pt, res) ,
273- TrianglePointLocation :: OnFace ( face_side as u32 , bcoords) ,
260+ pos. 0 ,
261+ match pos. 1 {
262+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
263+ TrianglePointLocation :: OnVertex ( v)
264+ }
265+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
266+ TrianglePointLocation :: OnEdge ( 2 , v)
267+ }
268+ } ,
274269 ) ;
275270 }
271+ } else if DIM != 2 {
272+ let denom = 1.0 / inv_denom;
273+ let v = vb * denom;
274+ let w = vc * denom;
275+ let bcoords = [ 1.0 - v - w, v, w] ;
276+ let res = a + ab * v + ac * w;
277+
278+ return (
279+ compute_result ( pt, res) ,
280+ TrianglePointLocation :: OnFace ( face_side as u32 , bcoords) ,
281+ ) ;
276282 }
277283 }
278284 }
@@ -286,11 +292,11 @@ impl PointQueryWithLocation for Triangle {
286292 )
287293 } else {
288294 // We have to project on the closest edge.
295+
289296 // TODO: this might be optimizable.
290297 // TODO: be careful with numerical errors.
291298 let v = ab_ap / ( ab_ap - ab_bp) ; // proj on ab = a + ab * v
292299 let w = ac_ap / ( ac_ap - ac_cp) ; // proj on ac = a + ac * w
293- dbg ! ( ( ac_bp - ab_bp) / ( ac_bp - ab_bp + ab_cp - ac_cp) ) ;
294300 let u = ( ac_bp - ab_bp) / ( ac_bp - ab_bp + ab_cp - ac_cp) ; // proj on bc = b + bc * u
295301
296302 let bc = c - b;
0 commit comments