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,19 @@ 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) ;
11169 let ab_ap = ab. dot ( & ap) ;
11270 let ac_ap = ac. dot ( & ap) ;
113- std:: dbg!( ab_ap, ac_ap) ;
11471
11572 if ab_ap <= 0.0 && ac_ap <= 0.0 {
11673 // Voronoï region of `a`.
@@ -120,7 +77,6 @@ impl PointQueryWithLocation for Triangle {
12077 let bp = pt - b;
12178 let ab_bp = ab. dot ( & bp) ;
12279 let ac_bp = ac. dot ( & bp) ;
123- std:: dbg!( bp, ab_bp, ac_bp) ;
12480
12581 if ab_bp >= 0.0 && ac_bp <= ab_bp {
12682 // Voronoï region of `b`.
@@ -130,7 +86,6 @@ impl PointQueryWithLocation for Triangle {
13086 let cp = pt - c;
13187 let ab_cp = ab. dot ( & cp) ;
13288 let ac_cp = ac. dot ( & cp) ;
133- std:: dbg!( cp, ab_cp, ac_cp) ;
13489
13590 if ac_cp >= 0.0 && ab_cp <= ac_cp {
13691 // Voronoï region of `c`.
@@ -256,23 +211,73 @@ impl PointQueryWithLocation for Triangle {
256211 ) ;
257212 }
258213 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-
214+ let inv_denom = va + vb + vc;
215+ if inv_denom == 0.0 {
216+ // The triangle is degenerate (the three points are collinear).
217+ // So we find the longest segment and project point on it.
218+
219+ // TODO: this can probably be optimized using data we already have ?
220+ let length_sq_ab = ab. magnitude_squared ( ) ;
221+ let length_sq_ac = ac. magnitude_squared ( ) ;
222+ let length_sq_bc = bc. magnitude_squared ( ) ;
223+
224+ if length_sq_ab >= length_sq_ac && length_sq_ab >= length_sq_bc {
225+ // AB is longest edge.
226+ let pos =
227+ Segment :: new ( a, b) . project_local_point_and_get_location ( pt, solid) ;
228+ return (
229+ pos. 0 ,
230+ match pos. 1 {
231+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
232+ TrianglePointLocation :: OnVertex ( v)
233+ }
234+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
235+ TrianglePointLocation :: OnEdge ( 0 , v)
236+ }
237+ } ,
238+ ) ;
239+ } else if length_sq_ac >= length_sq_ab && length_sq_ac >= length_sq_bc {
240+ // AC is longest edge.
241+ let pos =
242+ Segment :: new ( a, c) . project_local_point_and_get_location ( pt, solid) ;
271243 return (
272- compute_result ( pt, res) ,
273- TrianglePointLocation :: OnFace ( face_side as u32 , bcoords) ,
244+ pos. 0 ,
245+ match pos. 1 {
246+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
247+ TrianglePointLocation :: OnVertex ( v)
248+ }
249+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
250+ TrianglePointLocation :: OnEdge ( 1 , v)
251+ }
252+ } ,
253+ ) ;
254+ } else {
255+ // BC is longest edge.
256+ let pos =
257+ Segment :: new ( b, c) . project_local_point_and_get_location ( pt, solid) ;
258+ return (
259+ pos. 0 ,
260+ match pos. 1 {
261+ crate :: shape:: SegmentPointLocation :: OnVertex ( v) => {
262+ TrianglePointLocation :: OnVertex ( v)
263+ }
264+ crate :: shape:: SegmentPointLocation :: OnEdge ( v) => {
265+ TrianglePointLocation :: OnEdge ( 2 , v)
266+ }
267+ } ,
274268 ) ;
275269 }
270+ } else if DIM != 2 {
271+ let denom = 1.0 / inv_denom;
272+ let v = vb * denom;
273+ let w = vc * denom;
274+ let bcoords = [ 1.0 - v - w, v, w] ;
275+ let res = a + ab * v + ac * w;
276+
277+ return (
278+ compute_result ( pt, res) ,
279+ TrianglePointLocation :: OnFace ( face_side as u32 , bcoords) ,
280+ ) ;
276281 }
277282 }
278283 }
@@ -286,11 +291,11 @@ impl PointQueryWithLocation for Triangle {
286291 )
287292 } else {
288293 // We have to project on the closest edge.
294+
289295 // TODO: this might be optimizable.
290296 // TODO: be careful with numerical errors.
291297 let v = ab_ap / ( ab_ap - ab_bp) ; // proj on ab = a + ab * v
292298 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) ) ;
294299 let u = ( ac_bp - ab_bp) / ( ac_bp - ab_bp + ab_cp - ac_cp) ; // proj on bc = b + bc * u
295300
296301 let bc = c - b;
0 commit comments