1use nalgebra::{self as na, *};
2use std::cmp::{PartialOrd, Ordering};
3
4pub type Line<N> = (Point3<N>, Point3<N>);
5pub type LineRef<'a, N> = (&'a Point3<N>, &'a Point3<N>);
6pub type Plane<N> = (Point3<N>, Point3<N>, Point3<N>);
7pub type PlaneRef<'a, N> = (&'a Point3<N>, &'a Point3<N>, &'a Point3<N>);
8
9pub trait InstinctUtils {
10 fn instinct_eq(&self, other: &Self) -> bool;
12 fn instinct_gt(&self, other: &Self) -> bool;
13 fn instinct_ge(&self, other: &Self) -> bool;
14 fn instinct_lt(&self, other: &Self) -> bool;
15 fn instinct_le(&self, other: &Self) -> bool;
16
17 fn instinct_zero(&self) -> bool;
18 fn instinct_not_negative(&self) -> bool;
19 fn instinct_not_positive(&self) -> bool;
20 fn instinct_positive(&self) -> bool;
21 fn instinct_negative(&self) -> bool;
22 fn instinct_ord(&self, other: &Self) -> Ordering;
23 fn instinct_delta_ord(&self) -> Ordering;
24 fn instinct_ndelta_ord(&self) -> Ordering;
25}
26
27impl<'a, N: RealField> InstinctUtils for N {
28 fn instinct_eq(&self, other: &Self) -> bool {
29 (*self - *other).abs() <= N::default_max_relative()
30 }
31
32 fn instinct_gt(&self, other: &Self) -> bool {
33 (!self.instinct_eq(other)) && self > other
34 }
35
36 fn instinct_lt(&self, other: &Self) -> bool {
37 (!self.instinct_eq(other)) && self < other
38 }
39
40 fn instinct_ge(&self, other: &Self) -> bool {
41 self.instinct_eq(other) || self > other
42 }
43
44 fn instinct_le(&self, other: &Self) -> bool {
45 self.instinct_eq(other) || self < other
46 }
47
48 fn instinct_zero(&self) -> bool {
49 self.abs() <= N::default_max_relative()
50 }
51
52 fn instinct_not_negative(&self) -> bool {
53 self.is_positive() || self.instinct_zero()
54 }
55 fn instinct_not_positive(&self) -> bool {
56 self.is_negative() || self.instinct_zero()
57 }
58
59 fn instinct_positive(&self) -> bool {
60 self.is_positive() && !self.instinct_zero()
61 }
62 fn instinct_negative(&self) -> bool {
63 self.is_negative() && !self.instinct_zero()
64 }
65 fn instinct_ord(&self, other: &Self) -> Ordering {
66 if self.instinct_eq(other) {
68 Ordering::Equal
69 } else if self > other {
70 Ordering::Greater
71 } else {
72 Ordering::Less
73 }
74 }
75
76 fn instinct_delta_ord(&self) -> Ordering {
77 if self.instinct_zero() {
78 Ordering::Equal
79 } else if self.is_positive() {
80 Ordering::Greater
81 } else {
82 Ordering::Less
83 }
84 }
85
86 fn instinct_ndelta_ord(&self) -> Ordering {
87 self.instinct_delta_ord().reverse()
88 }
89}
90
91pub trait InstinctOrd<Rhs> {
104 fn instinct_cmp(&self, other: &Rhs) -> Ordering;
105 fn instinct_cmp_ext(&self, other: &Rhs) -> Option<Ordering>;
106}
107
108macro_rules! same_point {
110 ($self: expr, $other: expr) => {
111 $self.x.instinct_eq(&$other.x) &&
112 $self.y.instinct_eq(&$other.y) &&
113 $self.z.instinct_eq(&$other.z)
114 };
115 ($p0: expr, $p1: expr, $p2: expr) => {
116 same_point!($p0, $p1) && same_point!($p1, $p2)
117 }
118}
119
120macro_rules! same_z {
122 ($a: expr, $b: expr, $c: expr) => {
123 $a.z.instinct_eq(&$b.z) &&
124 $a.z.instinct_eq(&$c.z) &&
125 $b.z.instinct_eq(&$c.z)
126 };
127 ($p: expr) => {
128 same_z!($p.0, $p.1, $p.2)
129 }
130}
131
132macro_rules! sort_points {
134 ($self: expr, $other: expr) => {
135 if same_point!($self, $other) {
136 Ordering::Equal
137 } else {
138 $self.z.instinct_ord(&$other.z)
139 }
140 }
141}
142macro_rules! is_lines_parallel {
144 ($a: expr, $b: expr, $c: expr, $d: expr) => {
145 {
146 let v1 = ($b.coords - $a.coords).normalize();
147 let v2 = ($d.coords - $c.coords).normalize();
148 same_point!(&v1, &v2) || same_point!(&v1, -v2)
149 }
150 };
151 ($a: expr, $b: expr, $c: expr) => {
152 is_lines_parallel!($a.0, $a.1, $b, $c)
153 };
154 ($a: expr, $b: expr) => {
155 is_lines_parallel!($a.0, $a.1, $b.0, $b.1)
156 }
157}
158
159macro_rules! point_in_line {
161 ($p: expr, $l0: expr, $l1: expr) => {
162 if same_point!($p, $l0) || same_point!($p, $l1) {
163 true
164 } else {
165 let v = $p.coords - $l0.coords;
166 let v_line = $l1.coords - $l0.coords;
167 let dot = v.dot(&v_line);
168 (dot*dot).instinct_eq(&(v.norm_squared()*v_line.norm_squared()))
169 }
170 };
171 ($p: expr, $l: expr) => {
172 point_in_line!($p, $l.0, $l.1)
173 }
174}
175
176macro_rules! sort_line_points {
178 ($a: expr, $b: expr, $c: expr) => {
179 {
180 let mut list = [$a, $b, $c];
181 if !$a.x.instinct_eq(&$b.x) {
182 list.sort_unstable_by(|a, b| a.x.partial_cmp(&b.x).unwrap());
183 } else if !$a.y.instinct_eq(&$b.y) {
184 list.sort_unstable_by(|a, b| a.y.partial_cmp(&b.y).unwrap());
185 } else if !$a.z.instinct_eq(&$b.z) {
186 list.sort_unstable_by(|a, b| a.z.partial_cmp(&b.z).unwrap());
187 }
188 list
189 }
190 };
191 ($p: expr) => {
192 sort_line_points!($p.0, $p.1, $p.2)
193 }
194}
195
196macro_rules! is_plane {
198 ($p0: expr, $p1: expr, $p2: expr) => {
199 if same_point!($p0, $p1) {
200 false
201 } else {
202 !point_in_line!($p2, $p0, $p1)
203 }
204 };
205 ($p: expr) => {
206 is_plane!($p.0, $p.1, $p.2)
207 }
208}
209
210macro_rules! point_in_plane {
212 ($p: expr, $a: expr, $b: expr, $c: expr) => {
213 if same_point!($p, $a) {
214 true
215 } else {
216 let line1 = ($b.coords - $a.coords).normalize();
217 let line2 = ($c.coords - $a.coords).normalize();
218 let target = ($p.coords - $a.coords).normalize();
219
220 let normal = line1.cross(&line2);
221 normal.dot(&target).instinct_zero()
222 }
223 };
224 ($p: expr, $plane: expr) => {
225 point_in_plane!($p, $plane.0, $plane.1, $plane.2)
226 }
227}
228
229macro_rules! sort_point_and_plane {
231 ($p: expr, $a: expr, $b: expr, $c: expr) => {
232 if same_point!($p, $a) {
233 Ordering::Equal
234 } else {
235 let line1 = ($b.coords - $a.coords).normalize();
236 let line2 = ($c.coords - $a.coords).normalize();
237 let target = ($p.coords - $a.coords).normalize();
238
239 let normal = line1.cross(&line2);
240 let delta = normal.dot(&target);
241
242 if normal.z.instinct_zero() {
243 Ordering::Equal
244 } else if normal.z.is_positive() {
245 delta.instinct_delta_ord()
246 } else {
247 delta.instinct_delta_ord().reverse()
248 }
249 }
250 };
251 ($p: expr, $plane: expr) => {
252 sort_point_and_plane!($p, $plane.0, $plane.1, $plane.2)
253 }
254}
255
256macro_rules! sort_point_and_line {
258 ($p: expr, $l0: expr, $l1: expr) => {
259 (($l1.z - $l0.z) * ($p.y - $l0.y) - ($l1.y - $l0.y) * ($p.z - $l0.z))
260 .instinct_delta_ord()
261 };
262 ($p: expr, $l: expr) => {
263 sort_point_and_line!($p, $l.0, $l.1)
264 }
265}
266
267macro_rules! get_lines_normal {
269 ($a: expr, $b: expr, $c: expr, $d: expr) => {
270 {
271 let d1 = $b.coords - $a.coords;
272 let d2 = $d.coords - $c.coords;
273 let (s, t) = closest_points_line_line_parameters($a, &d1, $c, &d2);
274 let p1 = $a + d1*s;
275 let p2 = $c + d2*t;
276 p2.coords - p1.coords
277 }
278 };
279 ($a: expr, $b: expr) => {
280 get_lines_normal!($a.0, $a.1, $b.0, $b.1)
281 }
282}
283
284macro_rules! get_point_plane_normal {
286 ($p: expr, $a: expr, $b: expr, $c: expr) => {
287 {
288 let d1 = $c.coords - $b.coords;
289 let d2 = $b.coords - $a.coords;
290 let (s, t) = closest_points_line_line_parameters($p, &d1, $a, &d2);
291 let p1 = $p + d1*s;
292 let p2 = $a + d2*t;
293 p2.coords - p1.coords
294 }
295 };
296 ($p: expr, $plane: expr) => {
297 get_point_plane_normal!($p, $plane.0, $plane.1, $plane.2)
298 }
299}
300
301macro_rules! get_line_plane_joint {
304 ($l0 :expr, $l1: expr, $p0: expr, $p1: expr, $p2: expr) => {
305 {
306 let normal_0 = get_point_plane_normal!($l0, $p0, $p1, $p2);
307 let normal_1 = get_point_plane_normal!($l1, $p0, $p1, $p2);
308 let distance_0_plane = normal_0.norm();
309 let distance_1_plane = normal_1.norm();
310 if distance_0_plane.instinct_zero() {
311 $l0
312 } else if distance_1_plane.instinct_zero() {
313 $l1
314 } else {
315 $l0 + ($l1.coords - $l0.coords) * distance_0_plane /
316 (distance_0_plane + distance_1_plane)
317 }
318 }
319 };
320 ($line: expr, $plane: expr) => {
321 get_line_plane_joint!($line.0, $line.1, $plane.0, $plane.1, $plane.2)
322 }
323}
324
325macro_rules! get_side_line_plane_joint {
328 ($l0 :expr, $l1: expr, $p0: expr, $p1: expr, $p2: expr) => {
329 {
330 let normal_0 = get_point_plane_normal!($l0, $p0, $p1, $p2);
331 let normal_1 = get_point_plane_normal!($l1, $p0, $p1, $p2);
332
333 let distance_0_plane = normal_0.norm();
334 let distance_1_plane = normal_1.norm();
335 if distance_0_plane.instinct_zero() {
336 $l0
337 } else if distance_1_plane.instinct_zero() {
338 $l1
339 } else if distance_0_plane < distance_1_plane {
340 $l0 - ($l1.coords - $l0.coords) * distance_1_plane / distance_0_plane
341 } else {
342 $l1 - ($l0.coords - $l1.coords) * distance_0_plane / distance_1_plane
343 }
344 }
345 };
346 ($line: expr, $plane: expr) => {
347 get_line_plane_joint!($line.0, $line.1, $plane.0, $plane.1, $plane.2)
348 }
349}
350
351
352macro_rules! point_in_triangle {
354 ($point: expr, $p0: expr, $p1: expr, $p2: expr) => {
355 {
356 let normal_plane = ($p1.coords - $p0.coords).cross(&(
358 $p2.coords - $p0.coords)).normalize();
359
360 let cmp_normal_0 = ($p0.coords - $point.coords).cross(&normal_plane);
361 let cmp_0_1 = ($p1.coords - $point.coords).dot(&cmp_normal_0);
362 let cmp_0_2 = ($p2.coords - $point.coords).dot(&cmp_normal_0);
363 if !cmp_0_1.instinct_zero() && !cmp_0_2.instinct_zero() &&
364 cmp_0_1.is_positive() == cmp_0_2.is_negative() {
365 let cmp_normal_1 = ($p1.coords - $point.coords).cross(&normal_plane);
366 let cmp_1_0 = ($p0.coords - $point.coords).dot(&cmp_normal_1);
367 let cmp_1_2 = ($p2.coords - $point.coords).dot(&cmp_normal_1);
368 if !cmp_1_0.instinct_zero() && !cmp_1_2.instinct_zero() &&
369 cmp_1_0.is_positive() == cmp_1_2.is_negative() {
370 true
372 } else {
373 false
374 }
375 } else {
376 false
377 }
378 }
379
380 };
381 ($point: expr, $plane: expr) => {
382 point_in_triangle!($point, $plane.0, $plane.1, $plane.2)
383 }
384}
385
386macro_rules! sort_line_and_triangle {
389 ($l0 :expr, $l1: expr, $p0: expr, $p1: expr, $p2: expr) => {
390 {
391 let n_01 = get_lines_normal!($l0, $l1, $p0, $p1).z;
392 let n_02 = get_lines_normal!($l0, $l1, $p0, $p2).z;
393 if n_01.instinct_zero() && n_02.instinct_zero() {
394 Ordering::Equal
395 } else {
396 let n_12 = get_lines_normal!($l0, $l1, $p1, $p2).z;
397 let mut check: i8 = 0;
398 if !n_01.instinct_zero() {
399 if n_01.is_positive() {
400 check += 1;
401 } else {
402 check -= 1;
403 }
404 }
405 if !n_02.instinct_zero() {
406 if n_02.is_positive() {
407 check += 1;
408 } else {
409 check -= 1;
410 }
411 }
412 if !n_12.instinct_zero() {
413 if n_12.is_positive() {
414 check += 1;
415 } else {
416 check -= 1;
417 }
418 }
419 if check > 1 {
420 Ordering::Less
421 } else if check < -1 {
422 Ordering::Greater
423 } else {
424 Ordering::Equal
425 }
426 }
427 }
428 };
429 ($line: expr, $plane: expr) => {
430 sort_line_and_triangle!($line.0, $line.1, $plane.0, $plane.1, $plane.2)
431 }
432}
433
434macro_rules! sort_triangles {
436 ($a: expr, $b: expr, $c: expr, $d: expr, $e: expr, $f: expr) => {
437 {
438 let o_ab = sort_line_and_triangle!($a, $b, $d, $e, $f);
439 let o_ac = sort_line_and_triangle!($a, $c, $d, $e, $f);
440 if o_ab == o_ac {
441 o_ab
442 } else {
443 let o_bc = sort_line_and_triangle!($b, $c, $d, $e, $f);
444 let mut check: i8 = 0;
445 match o_ab {
446 Ordering::Greater => check += 1,
447 Ordering::Less => check -= 1,
448 _ => {},
449 }
450 match o_ac {
451 Ordering::Greater => check += 1,
452 Ordering::Less => check -= 1,
453 _ => {},
454 }
455 match o_bc {
456 Ordering::Greater => check += 1,
457 Ordering::Less => check -= 1,
458 _ => {},
459 }
460 if check > 1 {
461 Ordering::Greater
462 } else if check < -1 {
463 Ordering::Less
464 } else {
465 Ordering::Equal
466 }
467 }
468 }
469 };
470 ($a: expr, $b: expr) => {
471 sort_triangles!($a.0, $a.1, $a.2, $b.0, $b.1, $b.2)
472 }
473}
474
475macro_rules! reverse_cmp_ext {
477 ($self: expr, $other: expr) => {
478 match $other.instinct_cmp_ext($self) {
479 Some(res) => Some(res.reverse()),
480 None => None
481 }
482 }
483}
484
485impl<'a, N: RealField> InstinctOrd<Self> for Point3<N> {
488 fn instinct_cmp(&self, other: &Self) -> Ordering {
489 sort_points!(self, other)
491 }
492 fn instinct_cmp_ext(&self, other: &Self) -> Option<Ordering> {
493 Some(sort_points!(self, other))
495 }
496}
497
498
499impl<'a, N: RealField> InstinctOrd<LineRef<'a, N>> for Point3<N> {
504 fn instinct_cmp(&self, other: &LineRef<'a, N>) -> Ordering {
505 if other.0.z.instinct_eq(&other.1.z) {
506 sort_points!(self, &other.0)
507 } else {
508 let v = self.z;
509 let min = other.0.z.min(other.1.z);
510 let max = other.0.z.max(other.1.z);
511 if v.instinct_gt(&max) {
517 return Ordering::Greater;
518 }
519 if v.instinct_lt(&min) {
520 return Ordering::Less;
521 }
522
523 sort_point_and_line!(self, other)
532 }
533 }
534 fn instinct_cmp_ext(&self, other: &LineRef<'a, N>) -> Option<Ordering> {
535 if same_point!(&other.0, &other.1) {
537 return Some(sort_points!(self, &other.0));
538 }
539
540 if point_in_line!(self, other) {
542 return None;
543 }
544
545 Some(sort_point_and_line!(self, other))
550
551 }
552}
553
554impl<'a, N: RealField> InstinctOrd<Line<N>> for Point3<N> {
555 fn instinct_cmp(&self, other: &Line<N>) -> Ordering {
556 self.instinct_cmp(&(&other.0, &other.1))
557 }
558 fn instinct_cmp_ext(&self, other: &Line<N>) -> Option<Ordering> {
559 self.instinct_cmp_ext(&(&other.0, &other.1))
560 }
561}
562
563
564impl<'a, N: RealField> InstinctOrd<PlaneRef<'a, N>> for Point3<N> {
567 fn instinct_cmp(&self, other: &PlaneRef<'a, N>) -> Ordering {
568 if same_z!(other) {
569 return self.z.instinct_ord(&other.0.z);
570 }
571 let v = self.z;
572 let min = other.0.z.min(other.1.z).min(other.2.z);
573 let max = other.0.z.max(other.1.z).max(other.2.z);
574 if v.instinct_gt(&max) {
580 return Ordering::Greater;
581 }
582 if v.instinct_lt(&min) {
583 return Ordering::Less;
584 }
585
586 if !is_plane!(other) {
587 let line = sort_line_points!(other);
588 return self.instinct_cmp(&(line[0], line[2]));
589 }
590
591 let line1 = (other.1.coords - other.0.coords).normalize();
592 let line2 = (other.2.coords - other.0.coords).normalize();
593 let target = (self.coords - other.0.coords).normalize();
594
595 let normal = line1.cross(&line2);
596 let delta = normal.dot(&target);
597
598 if normal.z.instinct_zero() {
599 Ordering::Equal
600 } else if normal.z.is_positive() {
601 delta.instinct_delta_ord()
602 } else {
603 delta.instinct_delta_ord().reverse()
604 }
605
606 }
607 fn instinct_cmp_ext(&self, other: &PlaneRef<'a, N>) -> Option<Ordering> {
608 if !is_plane!(other) {
609 let line = sort_line_points!(other);
610 return self.instinct_cmp_ext(&(line[0], line[2]));
611 }
612
613 let line1 = (other.1.coords - other.0.coords).normalize();
614 let line2 = (other.2.coords - other.0.coords).normalize();
615 let target = (self.coords - other.0.coords).normalize();
616
617 let normal = line1.cross(&line2);
618 let delta = normal.dot(&target);
619 if delta.instinct_zero() {
620 Some(Ordering::Equal)
622 } else if normal.z.instinct_zero() {
623 Some(Ordering::Equal)
625 } else if normal.z.is_positive() {
626 Some(delta.instinct_delta_ord())
627 } else {
628 Some(delta.instinct_delta_ord().reverse())
629 }
630 }
631}
632
633impl<N: RealField> InstinctOrd<Plane<N>> for Point3<N> {
634 fn instinct_cmp(&self, other: &Plane<N>) -> Ordering {
635 self.instinct_cmp(&(&other.0, &other.1, &other.2))
636 }
637 fn instinct_cmp_ext(&self, other: &Plane<N>) -> Option<Ordering> {
638 self.instinct_cmp_ext(&(&other.0, &other.1, &other.2))
639 }
640}
641
642impl<N: RealField> InstinctOrd<Point3<N>> for Plane<N> {
643 fn instinct_cmp(&self, other: &Point3<N>) -> Ordering {
644 other.instinct_cmp(&(&self.0, &self.1, &self.2)).reverse()
645 }
646 fn instinct_cmp_ext(&self, other: &Point3<N>) -> Option<Ordering> {
647 reverse_cmp_ext!(self, other)
648 }
649}
650
651impl<'a, N: RealField> InstinctOrd<Point3<N>> for PlaneRef<'a, N> {
652 fn instinct_cmp(&self, other: &Point3<N>) -> Ordering {
653 other.instinct_cmp(self).reverse()
654 }
655 fn instinct_cmp_ext(&self, other: &Point3<N>) -> Option<Ordering> {
656 reverse_cmp_ext!(self, other)
657 }
658}
659
660
661impl<'a, N: RealField> InstinctOrd<Point3<N>> for Line<N> {
664 fn instinct_cmp(&self, other: &Point3<N>) -> Ordering {
665 other.instinct_cmp(self).reverse()
666 }
667 fn instinct_cmp_ext(&self, other: &Point3<N>) -> Option<Ordering> {
668 reverse_cmp_ext!(self, other)
669 }
670}
671
672impl<'a, N: RealField> InstinctOrd<Point3<N>> for LineRef<'a, N> {
673 fn instinct_cmp(&self, other: &Point3<N>) -> Ordering {
674 other.instinct_cmp(self).reverse()
675 }
676 fn instinct_cmp_ext(&self, other: &Point3<N>) -> Option<Ordering> {
677 reverse_cmp_ext!(self, other)
678 }
679}
680
681impl<'a, N: RealField> InstinctOrd<LineRef<'a, N>> for LineRef<'a, N> {
684 fn instinct_cmp(&self, other: &LineRef<'a, N>) -> Ordering {
685 if same_point!(self.0, self.1) {
686 return self.0.instinct_cmp(other);
687 } else if same_point!(other.0, other.1) {
688 return other.0.instinct_cmp(self).reverse();
689 }
690 let v_min = self.0.z.min(self.1.z);
691 let v_max = self.0.z.max(self.1.z);
692 let min = other.0.z.min(other.1.z);
693 let max = other.0.z.max(other.1.z);
694 if v_min.instinct_eq(&max) {
695 if v_max > max || min < v_min {
696 return Ordering::Greater;
697 }
698 } else if v_min > max {
699 return Ordering::Greater;
700 }
701
702 if v_max.instinct_eq(&min) {
703 if v_min < max || max > v_max {
704 return Ordering::Less;
705 }
706 } else if v_max < min {
707 return Ordering::Less;
708 }
709
710 let o_0 = sort_point_and_line!(self.0, other);
711 let o_1 = sort_point_and_line!(self.1, other);
712
713 if point_in_line!(self.0, other) || o_0 == Ordering::Equal {
714 println!("{}", 1);
715 self.1.instinct_cmp(other)
716 } else if point_in_line!(self.1, other) || o_1 == Ordering::Equal {
717 println!("{}", 2);
718 self.0.instinct_cmp(other)
719 } else if o_0 == o_1 {
720 println!("{}", 3);
721 o_0
722 } else {
723 println!("{}", 4);
724 get_lines_normal!(self, other).z.instinct_delta_ord().reverse()
725 }
726 }
727 fn instinct_cmp_ext(&self, other: &LineRef<'a, N>) -> Option<Ordering> {
728 if same_point!(self.0, self.1) {
729 self.0.instinct_cmp_ext(other)
730 } else if same_point!(other.0, other.1) {
731 reverse_cmp_ext!(self, other.0)
732 } else if is_lines_parallel!(self, other) {
733 if point_in_line!(self.0, other) {
734 Some(Ordering::Equal)
735 } else {
736 self.0.instinct_cmp_ext(other)
737 }
738 } else {
739 let normal = get_lines_normal!(self, other);
740 if normal.z.instinct_zero() {
741 if normal.norm().instinct_zero() {
742 None
743 } else {
744 Some(Ordering::Equal)
745 }
746 } else if normal.z.is_negative() {
747 Some(Ordering::Greater)
748 } else {
749 Some(Ordering::Less)
750 }
751 }
752 }
753}
754
755impl<'a, N: RealField> InstinctOrd<LineRef<'a, N>> for Line<N> {
756 fn instinct_cmp(&self, other: &LineRef<'a, N>) -> Ordering {
757 (&self.0, &self.1).instinct_cmp(other)
758 }
759 fn instinct_cmp_ext(&self, other: &LineRef<'a, N>) -> Option<Ordering> {
760 (&self.0, &self.1).instinct_cmp_ext(other)
761 }
762}
763
764impl<'a, N: RealField> InstinctOrd<Line<N>> for Line<N> {
765 fn instinct_cmp(&self, other: &Line<N>) -> Ordering {
766 (&self.0, &self.1).instinct_cmp(&(&other.0, &other.1))
767 }
768 fn instinct_cmp_ext(&self, other: &Line<N>) -> Option<Ordering> {
769 (&self.0, &self.1).instinct_cmp_ext(&(&other.0, &other.1))
770 }
771}
772
773impl<'a, N: RealField> InstinctOrd<Line<N>> for LineRef<'a, N> {
774 fn instinct_cmp(&self, other: &Line<N>) -> Ordering {
775 self.instinct_cmp(&(&other.0, &other.1))
776 }
777 fn instinct_cmp_ext(&self, other: &Line<N>) -> Option<Ordering> {
778 self.instinct_cmp_ext(&(&other.0, &other.1))
779 }
780}
781
782impl<'a, N: RealField> InstinctOrd<PlaneRef<'a, N>> for LineRef<'a, N> {
785 fn instinct_cmp(&self, other: &PlaneRef<'a, N>) -> Ordering {
786 if same_point!(self.0, self.1) {
787 self.0.instinct_cmp(other)
788 } else {
789 let v_min = self.0.z.min(self.1.z);
790 let v_max = self.0.z.max(self.1.z);
791 let min = other.0.z.min(other.1.z).min(other.2.z);
792 let max = other.0.z.max(other.1.z).max(other.2.z);
793 if v_min.instinct_eq(&max) {
794 if v_max > max || min < v_min {
795 return Ordering::Greater;
796 }
797 } else if v_min > max {
798 return Ordering::Greater;
799 }
800
801 if v_max.instinct_eq(&min) {
802 if v_min < max || max > v_max {
803 return Ordering::Less;
804 }
805 } else if v_max < min {
806 return Ordering::Less;
807 }
808
809 if !is_plane!(other) {
810 let line = sort_line_points!(other);
811 self.instinct_cmp(&(line[0], line[2]))
812 } else {
813 let normal_0 = get_point_plane_normal!(self.0, other);
814 let normal_1 = get_point_plane_normal!(self.1, other);
815 if normal_0.dot(&normal_1).instinct_not_negative() {
816 if normal_0.z.abs() > normal_1.z.abs() {
817 normal_0.z.instinct_delta_ord().reverse()
818 } else {
819 normal_1.z.instinct_delta_ord().reverse()
820 }
821 } else {
822 let distance_0_plane = normal_0.norm();
823 let distance_1_plane = normal_1.norm();
824
825 let joint = self.0 + (self.1.coords - self.0.coords) * distance_0_plane /
827 (distance_0_plane + distance_1_plane);
828 let normal_plane = (other.1.coords - other.0.coords).cross(&(
830 other.2.coords - other.0.coords)).normalize();
831
832 let cmp_normal_0 = (other.0.coords - joint.coords).cross(&normal_plane);
833 let cmp_0_1 = (other.1.coords - joint.coords).dot(&cmp_normal_0);
834 let cmp_0_2 = (other.2.coords - joint.coords).dot(&cmp_normal_0);
835 if !cmp_0_1.instinct_zero() && !cmp_0_2.instinct_zero() &&
836 cmp_0_1.is_positive() == cmp_0_2.is_negative() {
837 let cmp_normal_1 = (other.1.coords - joint.coords).cross(&normal_plane);
838 let cmp_1_0 = (other.0.coords - joint.coords).dot(&cmp_normal_1);
839 let cmp_1_2 = (other.2.coords - joint.coords).dot(&cmp_normal_1);
840 if !cmp_1_0.instinct_zero() && !cmp_1_2.instinct_zero() &&
841 cmp_1_0.is_positive() == cmp_1_2.is_negative() {
842 return Ordering::Equal;
844 }
845 }
846 sort_line_and_triangle!(self, other)
847 }
848 }
849 }
850 }
851 fn instinct_cmp_ext(&self, other: &PlaneRef<'a, N>) -> Option<Ordering> {
852 if same_point!(self.0, self.1) {
853 self.0.instinct_cmp_ext(other)
854 } else if !is_plane!(other) {
855 let line = sort_line_points!(other);
856 self.instinct_cmp_ext(&(line[0], line[2]))
857 } else {
858 let c_0 = point_in_plane!(self.0, other);
859 let c_1 = point_in_plane!(self.1, other);
860 if c_0 {
861 if c_1 {
862 Some(Ordering::Equal)
863 } else {
864 None
865 }
866 } else if c_1 {
867 None
868 } else {
869 let v_0 = other.0.coords - other.2.coords;
870 let v_1 = other.1.coords - other.2.coords;
871 let normal = v_0.cross(&v_1);
872 let v = self.1.coords - self.0.coords;
873 if normal.dot(&v).instinct_zero() {
874 Some(get_point_plane_normal!(self.0, other).z.instinct_delta_ord().reverse())
875 } else {
876 None
877 }
878 }
879 }
880 }
881}
882
883impl<'a, N: RealField> InstinctOrd<PlaneRef<'a, N>> for Line<N> {
884 fn instinct_cmp(&self, other: &PlaneRef<'a, N>) -> Ordering {
885 (&self.0, &self.1).instinct_cmp(other)
886 }
887 fn instinct_cmp_ext(&self, other: &PlaneRef<'a, N>) -> Option<Ordering> {
888 (&self.0, &self.1).instinct_cmp_ext(other)
889 }
890}
891
892impl<'a, N: RealField> InstinctOrd<Plane<N>> for LineRef<'a, N> {
893 fn instinct_cmp(&self, other: &Plane<N>) -> Ordering {
894 self.instinct_cmp(&(&other.0, &other.1, &other.2))
895 }
896 fn instinct_cmp_ext(&self, other: &Plane<N>) -> Option<Ordering> {
897 self.instinct_cmp_ext(&(&other.0, &other.1, &other.2))
898 }
899}
900
901impl<N: RealField> InstinctOrd<Plane<N>> for Line<N> {
902 fn instinct_cmp(&self, other: &Plane<N>) -> Ordering {
903 (&self.0, &self.1).instinct_cmp(&(&other.0, &other.1))
904 }
905 fn instinct_cmp_ext(&self, other: &Plane<N>) -> Option<Ordering> {
906 (&self.0, &self.1).instinct_cmp_ext(&(&other.0, &other.1))
907 }
908}
909
910impl<'a, N: RealField> InstinctOrd<LineRef<'a, N>> for PlaneRef<'a, N> {
911 fn instinct_cmp(&self, other: &LineRef<'a, N>) -> Ordering {
912 other.instinct_cmp(self).reverse()
913 }
914 fn instinct_cmp_ext(&self, other: &LineRef<'a, N>) -> Option<Ordering> {
915 reverse_cmp_ext!(self, other)
916 }
917}
918
919impl<'a, N: RealField> InstinctOrd<Line<N>> for PlaneRef<'a, N> {
920 fn instinct_cmp(&self, other: &Line<N>) -> Ordering {
921 (&other.0, &other.1).instinct_cmp(self).reverse()
922 }
923 fn instinct_cmp_ext(&self, other: &Line<N>) -> Option<Ordering> {
924 reverse_cmp_ext!(self, other)
925 }
926}
927
928impl<'a, N: RealField> InstinctOrd<LineRef<'a, N>> for Plane<N> {
929 fn instinct_cmp(&self, other: &LineRef<'a, N>) -> Ordering {
930 other.instinct_cmp(&(&self.0, &self.1, &self.2)).reverse()
931 }
932 fn instinct_cmp_ext(&self, other: &LineRef<'a, N>) -> Option<Ordering> {
933 reverse_cmp_ext!(self, other)
934 }
935}
936impl<N: RealField> InstinctOrd<Line<N>> for Plane<N> {
937 fn instinct_cmp(&self, other: &Line<N>) -> Ordering {
938 (&other.0, &other.1).instinct_cmp(&(&self.0, &self.1, &self.2)).reverse()
939 }
940 fn instinct_cmp_ext(&self, other: &Line<N>) -> Option<Ordering> {
941 reverse_cmp_ext!(self, other)
942 }
943}
944
945impl<'a, N: RealField> InstinctOrd<PlaneRef<'a, N>> for PlaneRef<'a, N> {
948 fn instinct_cmp(&self, other: &PlaneRef<'a, N>) -> Ordering {
949 let v_min = self.0.z.min(self.1.z).min(self.2.z);
950 let v_max = self.0.z.max(self.1.z).max(self.2.z);
951 let min = other.0.z.min(other.1.z).min(other.2.z);
952 let max = other.0.z.max(other.1.z).max(other.2.z);
953 if v_min.instinct_eq(&max) {
954 if v_max > max || min < v_min {
955 return Ordering::Greater;
956 }
957 } else if v_min > max {
958 return Ordering::Greater;
959 }
960
961 if v_max.instinct_eq(&min) {
962 if v_min < max || max > v_max {
963 return Ordering::Less;
964 }
965 } else if v_max < min {
966 return Ordering::Less;
967 }
968
969 if !is_plane!(other) {
970 let line = sort_line_points!(other);
971 (line[0], line[2]).instinct_cmp(self).reverse()
972 } else if !is_plane!(self) {
973 let line = sort_line_points!(self);
974 (line[0], line[2]).instinct_cmp(other)
975 } else {
976 macro_rules! check_normals_same_side {
977 ($a: expr, $b: expr) => {
978 if $a.dot(&$b).is_positive() {
979 if $a.z.abs() > $b.z.abs() {
980 return $a.z.instinct_delta_ord().reverse();
981 } else {
982 return $b.z.instinct_delta_ord().reverse();
983 }
984 }
985 };
986 ($a: expr, $b: expr, $c: expr) => {
987 if $a.dot(&$b).is_positive() && $a.dot(&$c).is_positive() {
988 if $a.z.abs() > $b.z.abs() && $a.z.abs() > $c.z.abs() {
989 return $a.z.instinct_delta_ord().reverse();
990 } else if $b.z.abs() > $c.z.abs() {
991 return $b.z.instinct_delta_ord().reverse();
992 } else {
993 return $c.z.instinct_delta_ord().reverse();
994 }
995 }
996 }
997 }
998
999 macro_rules! check_cross_side {
1000 ($a: expr, $na: expr, $b: expr, $nb: expr, $other: expr) => {
1001 {
1002 let joint = $a + ($b.coords - $a.coords) * $na / ($na + $nb);
1003 if point_in_triangle!(joint, $other) {
1004 return Ordering::Equal;
1005 }
1006 }
1007 }
1008 }
1009
1010 macro_rules! check_cross_or_same_side {
1011 ($a: expr, $b: expr) => {
1012 let normal_0 = get_point_plane_normal!($a.0, $b);
1013 let normal_1 = get_point_plane_normal!($a.1, $b);
1014 let normal_2 = get_point_plane_normal!($a.2, $b);
1015 let n_0 = normal_0.norm();
1016 let n_1 = normal_1.norm();
1017 let n_2 = normal_2.norm();
1018
1019 if n_0.instinct_zero() {
1020 if n_1.instinct_zero() {
1021 if n_2.instinct_zero() {
1022 return Ordering::Equal;
1023 } else {
1024 return normal_2.z.instinct_delta_ord().reverse();
1025 }
1026 } else if n_2.instinct_zero() {
1027 return normal_1.z.instinct_delta_ord().reverse();
1028 } else {
1029 check_normals_same_side!(normal_1, normal_2);
1031 check_cross_side!($a.1, n_1, $a.2, n_2, $b);
1033 }
1034 } else if n_1.instinct_zero() {
1035 if n_2.instinct_zero() {
1036 return normal_0.z.instinct_delta_ord().reverse();
1037 } else {
1038 check_normals_same_side!(normal_0, normal_2);
1040 check_cross_side!($a.0, n_0, $a.2, n_2, $b);
1042 }
1043 } else if n_2.instinct_zero() {
1044 check_normals_same_side!(normal_0, normal_1);
1046 check_cross_side!($a.0, n_0, $a.1, n_1, $b);
1048 } else {
1049 if normal_0.dot(&normal_1).is_positive() {
1052 if normal_0.dot(&normal_2).is_positive() {
1053 if normal_0.z.abs() > normal_1.z.abs()
1054 && normal_0.z.abs() > normal_2.z.abs() {
1055 return normal_0.z.instinct_delta_ord().reverse();
1056 } else if normal_1.z.abs() > normal_2.z.abs() {
1057 return normal_1.z.instinct_delta_ord().reverse();
1058 } else {
1059 return normal_2.z.instinct_delta_ord().reverse();
1060 }
1061 } else {
1062 check_cross_side!($a.0, n_0, $a.2, n_2, $b);
1064 check_cross_side!($a.1, n_1, $a.2, n_2, $b);
1066 }
1067 } else if normal_0.dot(&normal_2).is_positive() {
1068 check_cross_side!($a.0, n_0, $a.1, n_1, $b);
1070 check_cross_side!($a.1, n_1, $a.2, n_2, $b);
1072 } else {
1073 check_cross_side!($a.0, n_0, $a.1, n_1, $b);
1075 check_cross_side!($a.0, n_0, $a.2, n_2, $b);
1077 }
1078 }
1079 }
1080 }
1081 check_cross_or_same_side!(self, other);
1082 check_cross_or_same_side!(other, self);
1083
1084 sort_triangles!(self, other)
1086 }
1087 }
1088 fn instinct_cmp_ext(&self, other: &PlaneRef<'a, N>) -> Option<Ordering> {
1089 if !is_plane!(self) {
1090 let line = sort_line_points!(self);
1091 (line[0], line[2]).instinct_cmp_ext(other)
1092 } else if !is_plane!(other) {
1093 let line = sort_line_points!(other);
1094 self.instinct_cmp_ext(&(line[0], line[2]))
1095 } else {
1096 let n_0 = get_point_plane_normal!(self.0, other);
1097 let n_1 = get_point_plane_normal!(self.1, other);
1098 let n_2 = get_point_plane_normal!(self.2, other);
1099 if same_point!(&n_0, &n_1, &n_2) {
1100 Some(n_0.z.instinct_delta_ord().reverse())
1101 } else {
1102 None
1103 }
1104 }
1105 }
1106}
1107
1108impl<'a, N: RealField> InstinctOrd<Plane<N>> for PlaneRef<'a, N> {
1109 fn instinct_cmp(&self, other: &Plane<N>) -> Ordering {
1110 self.instinct_cmp(&(&other.0, &other.1, &other.2))
1111 }
1112 fn instinct_cmp_ext(&self, other: &Plane<N>) -> Option<Ordering> {
1113 self.instinct_cmp_ext(&(&other.0, &other.1, &other.2))
1114 }
1115}
1116
1117impl<'a, N: RealField> InstinctOrd<PlaneRef<'a, N>> for Plane<N> {
1118 fn instinct_cmp(&self, other: &PlaneRef<'a, N>) -> Ordering {
1119 (&self.0, &self.1, &self.2).instinct_cmp(other)
1120 }
1121 fn instinct_cmp_ext(&self, other: &PlaneRef<'a, N>) -> Option<Ordering> {
1122 (&self.0, &self.1, &self.2).instinct_cmp_ext(other)
1123 }
1124}
1125
1126impl<N: RealField> InstinctOrd<Plane<N>> for Plane<N> {
1127 fn instinct_cmp(&self, other: &Plane<N>) -> Ordering {
1128 (&self.0, &self.1, &self.2).instinct_cmp(&(&other.0, &other.1, &other.2))
1129 }
1130 fn instinct_cmp_ext(&self, other: &Plane<N>) -> Option<Ordering> {
1131 (&self.0, &self.1, &self.2).instinct_cmp_ext(&(&other.0, &other.1, &other.2))
1132 }
1133}
1134
1135
1136#[inline]
1143pub fn closest_points_line_line_parameters<N: RealField>(
1144 orig1: &Point3<N>,
1145 dir1: &Vector3<N>,
1146 orig2: &Point3<N>,
1147 dir2: &Vector3<N>,
1148) -> (N, N) {
1149 let res =
1150 closest_points_line_line_parameters_eps(orig1, dir1, orig2, dir2, N::default_epsilon());
1151 (res.0, res.1)
1152}
1153
1154#[inline]
1161pub fn closest_points_line_line_parameters_eps<N: RealField>(
1162 orig1: &Point3<N>,
1163 dir1: &Vector3<N>,
1164 orig2: &Point3<N>,
1165 dir2: &Vector3<N>,
1166 eps: N,
1167) -> (N, N, bool) {
1168 let r = *orig1 - *orig2;
1170
1171 let a = dir1.norm_squared();
1172 let e = dir2.norm_squared();
1173 let f = dir2.dot(&r);
1174
1175 let _0: N = na::zero();
1176 let _1: N = na::one();
1177
1178 if a <= eps && e <= eps {
1179 (_0, _0, false)
1180 } else if a <= eps {
1181 (_0, f / e, false)
1182 } else {
1183 let c = dir1.dot(&r);
1184 if e <= eps {
1185 (-c / a, _0, false)
1186 } else {
1187 let b = dir1.dot(dir2);
1188 let ae = a * e;
1189 let bb = b * b;
1190 let denom = ae - bb;
1191
1192 let parallel = denom <= eps;
1195
1196 let s = if !parallel {
1197 (b * f - c * e) / denom
1198 } else {
1199 _0
1200 };
1201
1202 (s, (b * s + f) / e, parallel)
1203 }
1204 }
1205}
1206
1207#[inline]
1210pub fn closest_points_line_line<N: RealField>(
1211 orig1: &Point3<N>,
1212 dir1: &Vector3<N>,
1213 orig2: &Point3<N>,
1214 dir2: &Vector3<N>,
1215) -> Line<N> {
1216 let (s, t) = closest_points_line_line_parameters(orig1, dir1, orig2, dir2);
1217 (*orig1 + *dir1 * s, *orig2 + *dir2 * t)
1218}
1219
1220
1221#[cfg(test)]
1223mod tests {
1224 use super::*;
1225
1226 #[test]
1227 fn test_cmp_points() {
1228 assert_eq!(Point3::new(1.,2.,3.).instinct_cmp(&Point3::new(4.,5.,3.)), Ordering::Equal);
1229 assert_eq!(Point3::new(1.,2.,3.00000001).instinct_cmp(&Point3::new(4.,5.,3.)), Ordering::Greater);
1230 assert_eq!(Point3::new(1.,2.,2.999999).instinct_cmp(&Point3::new(4.,5.,3.)), Ordering::Less);
1231 }
1232
1233 #[test]
1234 fn test_cmp_point_line() {
1235 let line = (Point3::new(1., 2., 3.), Point3::new(5., 8., 9.));
1236 let mut point = Point3::new(1., 2., 3.);
1237 assert_eq!(line.instinct_cmp(&point), Ordering::Equal);
1238 point = Point3::new(3., 5., 6.);
1239 assert_eq!(line.instinct_cmp(&point), Ordering::Equal);
1240 point = Point3::new(3., 5., 6.0000001);
1241 assert_eq!(line.instinct_cmp(&point), Ordering::Greater);
1242 point = Point3::new(3., 5., 5.9999999);
1243 assert_eq!(line.instinct_cmp(&point), Ordering::Less);
1244 }
1245
1246 #[test]
1247 fn test_cmp_point_plane() {
1248 let plane = (Point3::new(1., 2., 3.), Point3::new(1.4, 4., 6.), Point3::new(0., 0., 0.));
1249 let mut point = Point3::new(0., 0., 0.);
1250 assert_eq!(plane.instinct_cmp(&point), Ordering::Equal);
1251 point = Point3::new(0.8, 2., 3.);
1252 assert_eq!(plane.instinct_cmp(&point), Ordering::Equal);
1253 point = Point3::new(0.8, 2., 2.999999);
1254 assert_eq!(plane.instinct_cmp(&point), Ordering::Greater);
1255 point = Point3::new(0.8, 2., 3.000001);
1256 assert_eq!(plane.instinct_cmp(&point), Ordering::Less);
1257 }
1258
1259 #[test]
1260 fn test_cmp_lines() {
1261 let a = (Point3::new(1., 2., 3.), Point3::new(5., 8., 9.));
1262 let b = (Point3::new(1., 2., 3.), Point3::new(5., 8., 9.));
1263 assert_eq!(a.instinct_cmp(&b), Ordering::Equal);
1264 }
1265
1266 #[test]
1267 fn test_lines_perpendicular_vector() {
1268 let p1 = Point3::new(-1., 0., -1.);
1269 let p2 = Point3::new(1., 32., 0.);
1270 let d1 = Vector3::new(-10., 0., -10.);
1271 let d2 = Vector3::new(3., 0., 0.);
1272 let (s, t) = closest_points_line_line_parameters(&p1, &d1, &p2, &d2);
1273 let t1 = p1 + d1*s;
1274 let t2 = p2 + d2*t;
1275 assert_eq!(t1, Point3::new(0., 0., 0.));
1276 assert_eq!(t2, Point3::new(0., 32., 0.));
1277 }
1278}
1279
1280
1281