1use crate::*;
4use super::*;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7#[expect(clippy::module_name_repetitions)]
8pub struct Distance2 <S> {
9 distance_squared : NonNegative <S>,
10 distance : Option <NonNegative <S>>,
11 nearest_a : Point2 <S>,
12 nearest_b : Point2 <S>
13}
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16#[expect(clippy::module_name_repetitions)]
17pub struct Distance3 <S> {
18 distance_squared : NonNegative <S>,
19 distance : Option <NonNegative <S>>,
20 nearest_a : Point3 <S>,
21 nearest_b : Point3 <S>
22}
23
24pub fn nearest_triangle2_point2 <S : OrderedField> (
31 _triangle : Triangle2 <S>, _point : Point2 <S>
32) -> Triangle2Point <S> {
33 unimplemented!("TODO: nearest triangle2 point2")
34}
35
36pub fn nearest_line2_point2 <S> (line : frame::Line2 <S>, point : Point2 <S>)
38 -> Line2Point <S>
39where S : OrderedRing {
40 let ab = line.basis;
41 let av = point - line.origin;
42 let ab2 = ab.self_dot();
43 let ab_dot_av = ab.dot (av);
44 let t = ab_dot_av / *ab2;
45 let tab = *ab * t;
46 let at = line.origin + tab;
47 (t, at)
48}
49
50pub fn nearest_segment2_point2 <S> (segment : Segment2 <S>, point : Point2 <S>)
52 -> Segment2Point <S>
53where S : OrderedField {
54 use num::One;
55 let (t, point) = nearest_line2_point2 (segment.into(), point);
56 if t < S::zero() {
57 (Normalized::zero(), segment.point_a())
58 } else if t > S::one() {
59 (Normalized::one(), segment.point_b())
60 } else {
61 (Normalized::unchecked (t), point)
62 }
63}
64
65pub fn nearest_triangle3_triangle3 <S> (
72 _triangle_a : Triangle3 <S>, _triangle_b : Triangle3 <S>
73) -> (Triangle3Point <S>, Triangle3Point <S>) {
74 unimplemented!("TODO: nearest triangle3 triangle3")
75}
76
77pub fn nearest_triangle3_line3 <S> (triangle : Triangle3 <S>, line : frame::Line3 <S>)
81 -> (Triangle3Point <S>, Line3Point <S>)
82where S : Real + approx::RelativeEq <Epsilon=S> {
83 let edge1 = triangle.point_b() - triangle.point_a();
86 let edge2 = triangle.point_c() - triangle.point_a();
87 let n = edge1.cross (edge2);
88 let dir = line.basis;
89 let n_dot_dir = n.dot (*dir);
90 if n_dot_dir.abs() > S::zero() {
91 let diff = line.origin - triangle.point_a();
93 let n_dot_diff = n.dot (diff);
94 let intersect = -n_dot_diff / n_dot_dir;
95 let y = line.origin + *dir * intersect;
96 let tri0_to_y = y - triangle.point_a();
97 let e1_dot_e1 = edge1.dot (edge1);
98 let e1_dot_e2 = edge1.dot (edge2);
99 let e2_dot_e2 = edge2.dot (edge2);
100 let e1_dot_tri0_to_y = edge1.dot (tri0_to_y);
101 let e2_dot_tri0_to_y = edge2.dot (tri0_to_y);
102 let det = e1_dot_e1 * e2_dot_e2 - e1_dot_e2 * e1_dot_e2;
103 let b1 = (e2_dot_e2 * e1_dot_tri0_to_y - e1_dot_e2 * e2_dot_tri0_to_y) / det;
104 let b2 = (e1_dot_e1 * e2_dot_tri0_to_y - e1_dot_e2 * e1_dot_tri0_to_y) / det;
105 let b0 = S::one() - b1 - b2;
106 if b0 >= S::zero() && b1 >= S::zero() && b2 >= S::zero() {
107 if cfg!(debug_assertions) {
109 approx::assert_relative_eq!(triangle.point_a() + edge1 * b1 + edge2 * b2, y,
110 epsilon = S::default_epsilon() * S::two().powi (36),
111 max_relative = S::default_max_relative() * S::two().powi (36));
112 }
113 return (
114 ([b1, b2].map (Normalized::unchecked), y),
115 (intersect, y) )
116 }
117 }
118 let mut i0 = 2;
120 let mut i1 = 0;
121 let mut i2 = 1;
122 let mut lowest_dist_sq = None;
123 let mut p0 = S::zero();
124 let mut barycentric = [Normalized::zero(), Normalized::zero(), Normalized::zero()];
125 let triangle_points = triangle.points();
126 while i1 < 3 {
127 let segment = Segment3::noisy (triangle_points[i0], triangle_points[i1]);
128 let ((s0, p_line), (s1, p_seg)) = nearest_line3_segment3 (line, segment);
129 let dist_sq = (p_seg - p_line).self_dot();
130 if lowest_dist_sq.is_none_or (|lowest| dist_sq < lowest) {
131 lowest_dist_sq = Some (dist_sq);
132 p0 = s0;
133 barycentric[i0] = s1;
136 barycentric[i1] = Normalized::zero();
137 barycentric[i2] = Normalized::unchecked (S::one() - *s1);
138 }
139 i2 = i0;
140 i0 = i1;
141 i1 += 1;
142 }
143 let point_tri = triangle.point_a() + edge1 * barycentric[0] + edge2 * barycentric[1];
144 let point_line = line.origin + *dir * p0;
145 ( ([barycentric[0], barycentric[1]], point_tri),
146 (p0, point_line))
147}
148
149pub fn nearest_triangle3_segment3 <S> (triangle : Triangle3 <S>, segment : Segment3 <S>)
153 -> (Triangle3Point <S>, Segment3Point <S>)
154where S : Real + approx::RelativeEq <Epsilon=S> {
155 use num::One;
156 let (out_tri, (r, near_line)) =
157 nearest_triangle3_line3 (triangle, segment.affine_line());
158 if r < S::zero() {
159 let point_a = segment.point_a();
160 let out_tri = nearest_triangle3_point3 (triangle, point_a);
161 (out_tri, (Normalized::zero(), point_a))
162 } else if r > S::one() {
163 let point_b = segment.point_b();
164 let out_tri = nearest_triangle3_point3 (triangle, point_b);
165 (out_tri, (Normalized::one(), point_b))
166 } else {
167 (out_tri, (Normalized::unchecked (r), near_line))
168 }
169}
170
171pub fn nearest_triangle3_point3 <S> (triangle : Triangle3 <S>, point : Point3 <S>)
174 -> Triangle3Point <S>
175where S : OrderedField {
176 let d = triangle.point_a() - point;
179 let edge0 = triangle.point_b() - triangle.point_a();
180 let edge1 = triangle.point_c() - triangle.point_a();
181 let e00 = edge0.magnitude_squared();
182 let e01 = edge1.dot (edge0);
183 let e11 = edge1.magnitude_squared();
184 let de0 = d.dot (edge0);
185 let de1 = d.dot (edge1);
186 let det = (e00 * e11 - e01 * e01).abs();
187 let mut s = e01 * de1 - e11 * de0;
188 let mut t = e01 * de0 - e00 * de1;
189 if s + t <= det {
191 if s < S::zero() {
192 if t < S::zero() {
193 if de0 < S::zero() {
195 t = S::zero();
196 if -de0 > e00 {
197 s = S::one()
198 } else {
199 s = -de0 / e00
200 }
201 } else {
202 s = S::zero();
203 if de1 > S::zero() {
204 t = S::zero()
205 } else if -de1 >= e11 {
206 t = S::one()
207 } else {
208 t = -de1 / e11
209 }
210 }
211 } else {
212 s = S::zero();
214 if de1 > S::zero() {
215 t = S::zero()
216 } else if -de1 >= e11 {
217 t = S::one()
218 } else {
219 t = -de1 / e11
220 }
221 }
222 } else if t < S::zero() {
223 t = S::zero();
225 if de0 >= S::zero() {
226 s = S::zero()
227 } else if -de0 >= e00 {
228 s = S::one()
229 } else {
230 s = -de0 / e00
231 }
232 } else {
233 let idet = S::one() / det;
236 s *= idet;
237 t *= idet;
238 }
239 } else if s < S::zero() {
240 let tmp0 = e01 + de0;
242 let tmp1 = e11 + de1;
243 if tmp1 > tmp0 {
244 let numer = tmp1 - tmp0;
245 let denom = e00 - S::two() * e01 + e11;
246 if numer >= denom {
247 s = S::one();
248 t = S::zero();
249 } else {
250 s = numer / denom;
251 t = S::one() - s;
252 }
253 } else {
254 s = S::zero();
255 if tmp1 <= S::zero() {
256 t = S::one()
257 } else if de1 >= S::zero() {
258 t = S::zero()
259 } else {
260 t = -de1 / e11
261 }
262 }
263 } else if t < S::zero() {
264 let tmp0 = e01 + de1;
266 let tmp1 = e00 + de0;
267 if tmp1 > tmp0 {
268 let numer = tmp1 - tmp0;
269 let denom = e00 - S::two() * e01 + e11;
270 if numer >= denom {
271 t = S::one();
272 s = S::zero();
273 } else {
274 t = numer / denom;
275 s = S::one() - t;
276 }
277 } else {
278 t = S::zero();
279 if tmp1 <= S::zero() {
280 s = S::one()
281 } else if de0 >= S::zero() {
282 s = S::zero()
283 } else {
284 s = -de0 / e00
285 }
286 }
287 } else {
288 let numer = e11 + de1 - e01 - de0;
290 if numer <= S::zero() {
291 s = S::zero();
292 t = S::one();
293 } else {
294 let denom = e00 - S::two() * e01 + e11;
295 if numer >= denom {
296 s = S::one();
297 t = S::zero();
298 } else {
299 s = numer / denom;
300 t = S::one() - s;
301 }
302 }
303 }
304 let nearest = triangle.point_a() + edge0 * s + edge1 * t;
305 ([s, t].map (Normalized::unchecked), nearest)
306}
307
308pub fn nearest_line3_line3 <S> (line_a : frame::Line3 <S>, line_b : frame::Line3 <S>)
310 -> (Line3Point <S>, Line3Point <S>)
311where S : OrderedField {
312 let line_a_vec = line_a.basis;
315 let line_b_vec = line_b.basis;
316 let diff = line_a.origin - line_b.origin;
317 let a00 = line_a_vec.magnitude_squared();
318 let a01 = -line_a_vec.dot (*line_b_vec);
319 let a11 = line_b_vec.magnitude_squared();
320 let b0 = line_a_vec.dot (diff);
321 let det = S::max (a00 * a11 - a01 * a01, S::zero());
322 let (s0, s1) = if det > S::zero() {
323 let b1 = -line_b_vec.dot (diff);
324 ( (a01 * b1 - a11 * b0) / det,
325 (a01 * b0 - a00 * b1) / det )
326 } else {
327 (-b0 / a00, S::zero())
328 };
329 let nearest_a = line_a.origin + *line_a_vec * s0;
330 let nearest_b = line_b.origin + *line_b_vec * s1;
331 ((s0, nearest_a), (s1, nearest_b))
332}
333
334pub fn nearest_line3_segment3 <S> (line : frame::Line3 <S>, segment : Segment3 <S>)
336 -> (Line3Point <S>, Segment3Point <S>)
337where S : OrderedField {
338 let line_dir = line.basis;
341 let seg_dir = segment.vector();
342 let diff = line.origin - segment.point_a();
343 let a00 = line_dir.magnitude_squared();
344 let a01 = -line_dir.dot (*seg_dir);
345 let a11 = seg_dir.magnitude_squared();
346 let b0 = line_dir.dot (diff);
347 let det = S::max (a00 * a11 - a01 * a01, S::zero());
348 let s0;
349 let mut s1;
350 if det > S::zero() {
351 let b1 = -seg_dir.dot (diff);
353 s1 = a01 * b0 - a00 * b1;
354 if s1 >= S::zero() {
355 if s1 <= det {
356 s0 = (a01 * b1 - a11 * b0) / det;
357 s1 /= det;
358 } else {
359 s0 = -(a01 + b0) / a00;
360 s1 = S::one();
361 }
362 } else {
363 s0 = -b0 / a00;
364 s1 = S::zero();
365 }
366 } else {
367 s0 = -b0 / a00;
369 s1 = S::zero();
370 }
371 let p_line = line.origin + *line_dir * s0;
372 let p_seg = segment.point_a() + *seg_dir * s1;
373 ((s0, p_line), (Normalized::unchecked (s1), p_seg))
374}
375
376pub fn nearest_line3_point3 <S> (line : frame::Line3 <S>, point : Point3 <S>)
378 -> Line3Point <S>
379where S : OrderedRing {
380 let ab = line.basis;
381 let av = point.0 - line.origin.0;
382 let ab2 = ab.magnitude_squared();
383 let ab_dot_av = ab.dot (av);
384 let t = ab_dot_av / ab2;
385 let tab = *ab * t;
386 let at = line.origin + tab;
387 (t, at)
388}
389
390pub fn nearest_segment3_segment3 <S : Real> (
392 _segment_a : Segment3 <S>, _segment_b : Segment3 <S>
393) -> (Segment3Point <S>, Segment3Point <S>) {
394 unimplemented!("TODO: nearest segment3 segment3")
395}
396
397pub fn nearest_segment3_point3 <S> (segment : Segment3 <S>, point : Point3 <S>)
399 -> Segment3Point <S>
400where S : OrderedField {
401 use num::One;
402 let (t, point) = nearest_line3_point3 (segment.affine_line(), point);
403 if t < S::zero() {
404 (Normalized::zero(), segment.point_a())
405 } else if t > S::one() {
406 (Normalized::one(), segment.point_b())
407 } else {
408 (Normalized::unchecked (t), point)
409 }
410}
411
412impl <S : Ring> Distance2 <S> {
413 pub const fn nearest_a (&self) -> Point2 <S> {
414 self.nearest_a
415 }
416 pub const fn nearest_b (&self) -> Point2 <S> {
417 self.nearest_b
418 }
419 pub const fn distance_squared (&self) -> NonNegative <S> {
420 self.distance_squared
421 }
422 pub fn distance (&mut self) -> NonNegative <S> where S : Sqrt {
423 self.distance.unwrap_or_else (|| {
424 let distance = self.distance_squared.sqrt();
425 self.distance = Some (distance);
426 distance
427 })
428 }
429
430 pub fn segment_point (segment : Segment2 <S>, point : Point2 <S>) -> Self
431 where S : OrderedField
432 {
433 let (_, nearest_a) = nearest_segment2_point2 (segment, point);
434 let distance_squared = (point - nearest_a).norm_squared();
435 Distance2 { distance_squared, distance: None, nearest_a, nearest_b: point }
436 }
437
438 pub fn line_point (line : frame::Line2 <S>, point : Point2 <S>) -> Self
439 where S : OrderedField
440 {
441 let (_, nearest_a) = nearest_line2_point2 (line, point);
442 let distance_squared = (point - nearest_a).norm_squared();
443 Distance2 { distance_squared, distance: None, nearest_a, nearest_b: point }
444 }
445
446 pub fn triangle_point (triangle : Triangle2 <S>, point : Point2 <S>) -> Self
447 where S : OrderedField
448 {
449 let (_, nearest_a) = nearest_triangle2_point2 (triangle, point);
450 let distance_squared = (point - nearest_a).norm_squared();
451 Distance2 { distance_squared, distance: None, nearest_a, nearest_b: point }
452 }
453}
454
455impl <S : Ring> Distance3 <S> {
456 pub const fn nearest_a (&self) -> Point3 <S> {
457 self.nearest_a
458 }
459 pub const fn nearest_b (&self) -> Point3 <S> {
460 self.nearest_b
461 }
462 pub const fn distance_squared (&self) -> NonNegative <S> {
463 self.distance_squared
464 }
465 pub fn distance (&mut self) -> NonNegative <S> where S : Sqrt {
466 self.distance.unwrap_or_else (|| {
467 let distance = self.distance_squared.sqrt();
468 self.distance = Some (distance);
469 distance
470 })
471 }
472
473 pub fn segment_point (segment : Segment3 <S>, point : Point3 <S>) -> Self
474 where S : OrderedField
475 {
476 let (_, nearest_a) = nearest_segment3_point3 (segment, point);
477 let distance_squared = (point - nearest_a).norm_squared();
478 Distance3 { distance_squared, distance: None, nearest_a, nearest_b: point }
479 }
480
481 pub fn segment_segment (segment_a : Segment3 <S>, segment_b : Segment3 <S>) -> Self
482 where S : Real
483 {
484 let ((_, nearest_a), (_, nearest_b)) =
485 nearest_segment3_segment3 (segment_a, segment_b);
486 let distance_squared = (nearest_b - nearest_a).norm_squared();
487 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
488 }
489
490 pub fn line_point (line : frame::Line3 <S>, point : Point3 <S>) -> Self
491 where S : OrderedField
492 {
493 let (_, nearest_a) = nearest_line3_point3 (line, point);
494 let distance_squared = (point - nearest_a).norm_squared();
495 Distance3 { distance_squared, distance: None, nearest_a, nearest_b: point }
496 }
497
498 pub fn line_segment (line : frame::Line3 <S>, segment : Segment3 <S>) -> Self
499 where S : OrderedField
500 {
501 let ((_, nearest_a), (_, nearest_b)) = nearest_line3_segment3 (line, segment);
502 let distance_squared = (nearest_b - nearest_a).norm_squared();
503 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
504 }
505
506 pub fn line_line (line_a : frame::Line3 <S>, line_b : frame::Line3 <S>) -> Self
507 where S : OrderedField
508 {
509 let ((_, nearest_a), (_, nearest_b)) = nearest_line3_line3 (line_a, line_b);
510 let distance_squared = (nearest_b - nearest_a).norm_squared();
511 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
512 }
513
514 pub fn triangle_point (triangle : Triangle3 <S>, point : Point3 <S>) -> Self
515 where S : OrderedField
516 {
517 let (_, nearest_a) = nearest_triangle3_point3 (triangle, point);
518 let distance_squared = (point - nearest_a).norm_squared();
519 Distance3 { distance_squared, distance: None, nearest_a, nearest_b: point }
520 }
521
522 pub fn triangle_segment (triangle : Triangle3 <S>, segment : Segment3 <S>) -> Self
523 where S : Real + approx::RelativeEq <Epsilon=S>
524 {
525 let ((_, nearest_a), (_, nearest_b)) =
526 nearest_triangle3_segment3 (triangle, segment);
527 let distance_squared = (nearest_b - nearest_a).norm_squared();
528 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
529 }
530
531 pub fn triangle_line (triangle : Triangle3 <S>, line : frame::Line3 <S>) -> Self
532 where S : Real + approx::RelativeEq <Epsilon=S>
533 {
534 let ((_, nearest_a), (_, nearest_b)) = nearest_triangle3_line3 (triangle, line);
535 let distance_squared = (nearest_b - nearest_a).norm_squared();
536 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
537 }
538
539 pub fn triangle_triangle (triangle_a : Triangle3 <S>, triangle_b : Triangle3 <S>)
540 -> Self
541 where S : OrderedField {
542 let ((_, nearest_a), (_, nearest_b)) =
543 nearest_triangle3_triangle3 (triangle_a, triangle_b);
544 let distance_squared = (nearest_b - nearest_a).norm_squared();
545 Distance3 { distance_squared, distance: None, nearest_a, nearest_b }
546 }
547}
548
549#[cfg(test)]
550mod tests {
551 use super::*;
552
553 #[test]
554 fn nearest_line_segment_3d() {
555 let line = Segment3::noisy (
556 [0.0, 0.0, 0.0].into(),
557 [1.0, 1.0, 0.0].into()
558 ).affine_line();
559 let segment = Segment3::noisy (
560 [0.0, -1.0, 0.0].into(),
561 [1.0, -1.0, 0.0].into());
562 let ((s0, p_line), (s1, p_seg)) = nearest_line3_segment3 (line, segment);
563 assert_eq!(s0, -0.5);
564 assert_eq!(*s1, 0.0);
565 assert_eq!(p_line, [-0.5, -0.5, 0.0].into());
566 assert_eq!(p_seg, [0.0, -1.0, 0.0].into());
567 let segment = Segment3::noisy (
568 [0.0, -1.0, 0.0].into(),
569 [1.0, 0.0, 0.0].into());
570 let ((s0, p_line), (s1, p_seg)) = nearest_line3_segment3 (line, segment);
571 assert_eq!(s0, -0.5);
572 assert_eq!(*s1, 0.0);
573 assert_eq!(p_line, [-0.5, -0.5, 0.0].into());
574 assert_eq!(p_seg, [0.0, -1.0, 0.0].into());
575 }
576
577 #[test]
578 fn nearest_triangle_line_3d() {
579 let triangle = Triangle3::noisy (
580 [-1.0, -1.0, 0.0].into(),
581 [ 1.0, -1.0, 0.0].into(),
582 [ 0.0, 1.0, 0.0].into());
583 let line = Segment3::noisy (
584 [-2.0, -2.0, 0.0].into(),
585 [-2.0, -2.0, 1.0].into()
586 ).affine_line();
587 let (([t0, t1], p_tri), (s0, p_line)) = nearest_triangle3_line3 (triangle, line);
588 assert_eq!((*t0, *t1), (0.0, 0.0));
589 assert_eq!(p_tri, [-1.0, -1.0, 0.0].into());
590 assert_eq!(s0, 0.0);
591 assert_eq!(p_line, [-2.0, -2.0, 0.0].into());
592 let line = Segment3::noisy (
593 [ 2.0, -2.0, 0.0].into(),
594 [ 2.0, -2.0, 1.0].into()
595 ).affine_line();
596 let (([t0, t1], p_tri), (s0, p_line)) = nearest_triangle3_line3 (triangle, line);
597 assert_eq!((*t0, *t1), (1.0, 0.0));
598 assert_eq!(p_tri, [1.0, -1.0, 0.0].into());
599 assert_eq!(s0, 0.0);
600 assert_eq!(p_line, [2.0, -2.0, 0.0].into());
601 let line = Segment3::noisy (
602 [0.0, 2.0, 0.0].into(),
603 [0.0, 2.0, 1.0].into()
604 ).affine_line();
605 let (([t0, t1], p_tri), (s0, p_line)) = nearest_triangle3_line3 (triangle, line);
606 assert_eq!((*t0, *t1), (0.0, 1.0));
607 assert_eq!(p_tri, [0.0, 1.0, 0.0].into());
608 assert_eq!(s0, 0.0);
609 assert_eq!(p_line, [0.0, 2.0, 0.0].into());
610 let line = Segment3::noisy (
611 [0.0, -2.0, 0.0].into(),
612 [0.0, -2.0, 1.0].into()
613 ).affine_line();
614 let (([t0, t1], p_tri), (s0, p_line)) = nearest_triangle3_line3 (triangle, line);
615 assert_eq!((*t0, *t1), (0.5, 0.0));
616 assert_eq!(p_tri, [0.0, -1.0, 0.0].into());
617 assert_eq!(s0, 0.0);
618 assert_eq!(p_line, [0.0, -2.0, 0.0].into());
619 }
620}