|
1 | 1 | use std::f32::consts::{FRAC_PI_3, PI};
|
2 | 2 |
|
3 | 3 | use super::{Circle, Primitive3d};
|
4 |
| -use crate::{ |
5 |
| - bounding::{Aabb3d, Bounded3d, BoundingSphere}, |
6 |
| - Dir3, InvalidDirectionError, Mat3, Quat, Vec2, Vec3, |
7 |
| -}; |
| 4 | +use crate::{Dir3, InvalidDirectionError, Mat3, Vec2, Vec3}; |
8 | 5 |
|
9 | 6 | /// A sphere primitive
|
10 | 7 | #[derive(Clone, Copy, Debug, PartialEq)]
|
@@ -767,7 +764,7 @@ impl Triangle3d {
|
767 | 764 |
|
768 | 765 | /// Checks if the triangle is degenerate, meaning it has zero area.
|
769 | 766 | ///
|
770 |
| - /// A triangle is degenerate if the cross product of the vectors `ab` and `ac` has a length less than `f32::EPSILON`. |
| 767 | + /// A triangle is degenerate if the cross product of the vectors `ab` and `ac` has a length less than `10e-7`. |
771 | 768 | /// This indicates that the three vertices are collinear or nearly collinear.
|
772 | 769 | #[inline(always)]
|
773 | 770 | pub fn is_degenerate(&self) -> bool {
|
@@ -838,59 +835,6 @@ impl Triangle3d {
|
838 | 835 | }
|
839 | 836 | }
|
840 | 837 |
|
841 |
| -impl Bounded3d for Triangle3d { |
842 |
| - /// Get the bounding box of the triangle. |
843 |
| - fn aabb_3d(&self, translation: Vec3, rotation: Quat) -> Aabb3d { |
844 |
| - let [a, b, c] = self.vertices; |
845 |
| - |
846 |
| - let a = rotation * a; |
847 |
| - let b = rotation * b; |
848 |
| - let c = rotation * c; |
849 |
| - |
850 |
| - let min = a.min(b).min(c); |
851 |
| - let max = a.max(b).max(c); |
852 |
| - |
853 |
| - let bounding_center = (max + min) / 2.0 + translation; |
854 |
| - let half_extents = (max - min) / 2.0; |
855 |
| - |
856 |
| - Aabb3d::new(bounding_center, half_extents) |
857 |
| - } |
858 |
| - |
859 |
| - /// Get the bounding sphere of the triangle. |
860 |
| - /// |
861 |
| - /// The [`Triangle3d`] implements the minimal bounding sphere calculation. For acute triangles, the circumcenter is used as |
862 |
| - /// the center of the sphere. For the others, the bounding sphere is the minimal sphere |
863 |
| - /// that contains the largest side of the triangle. |
864 |
| - fn bounding_sphere(&self, translation: Vec3, rotation: Quat) -> BoundingSphere { |
865 |
| - if self.is_degenerate() { |
866 |
| - let (p1, p2) = self.largest_side(); |
867 |
| - let (segment, _) = Segment3d::from_points(p1, p2); |
868 |
| - return segment.bounding_sphere(translation, rotation); |
869 |
| - } |
870 |
| - |
871 |
| - let [a, b, c] = self.vertices; |
872 |
| - |
873 |
| - let side_opposite_to_non_acute = if (b - a).dot(c - a) <= 0.0 { |
874 |
| - Some((b, c)) |
875 |
| - } else if (c - b).dot(a - b) <= 0.0 { |
876 |
| - Some((c, a)) |
877 |
| - } else if (a - c).dot(b - c) <= 0.0 { |
878 |
| - Some((a, b)) |
879 |
| - } else { |
880 |
| - None |
881 |
| - }; |
882 |
| - |
883 |
| - if let Some((p1, p2)) = side_opposite_to_non_acute { |
884 |
| - let (segment, _) = Segment3d::from_points(p1, p2); |
885 |
| - segment.bounding_sphere(translation, rotation) |
886 |
| - } else { |
887 |
| - let circumcenter = self.circumcenter(); |
888 |
| - let radius = circumcenter.distance(a); |
889 |
| - BoundingSphere::new(circumcenter + translation, radius) |
890 |
| - } |
891 |
| - } |
892 |
| -} |
893 |
| - |
894 | 838 | /// A tetrahedron primitive.
|
895 | 839 | #[derive(Clone, Copy, Debug, PartialEq)]
|
896 | 840 | #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
@@ -976,6 +920,7 @@ mod tests {
|
976 | 920 | // Reference values were computed by hand and/or with external tools
|
977 | 921 |
|
978 | 922 | use super::*;
|
| 923 | + use crate::Quat; |
979 | 924 | use approx::assert_relative_eq;
|
980 | 925 |
|
981 | 926 | #[test]
|
@@ -1174,4 +1119,31 @@ mod tests {
|
1174 | 1119 | );
|
1175 | 1120 | assert_relative_eq!(Tetrahedron::default().centroid(), Vec3::ZERO);
|
1176 | 1121 | }
|
| 1122 | + |
| 1123 | + #[test] |
| 1124 | + fn triangle_math() { |
| 1125 | + let [a, b, c] = [Vec3::ZERO, Vec3::new(1., 1., 0.5), Vec3::new(-3., 2.5, 1.)]; |
| 1126 | + let triangle = Triangle3d::new(a, b, c); |
| 1127 | + |
| 1128 | + assert!(!triangle.is_degenerate(), "incorrectly found degenerate"); |
| 1129 | + assert_eq!(triangle.area(), 3.0233467, "incorrect area"); |
| 1130 | + assert_eq!(triangle.perimeter(), 9.832292, "incorrect perimeter"); |
| 1131 | + assert_eq!( |
| 1132 | + triangle.circumcenter(), |
| 1133 | + Vec3::new(-1., 1.75, 0.75), |
| 1134 | + "incorrect circumcenter" |
| 1135 | + ); |
| 1136 | + assert_eq!( |
| 1137 | + triangle.normal(), |
| 1138 | + Ok(Dir3::new_unchecked(Vec3::new( |
| 1139 | + -0.04134491, |
| 1140 | + -0.4134491, |
| 1141 | + 0.90958804 |
| 1142 | + ))), |
| 1143 | + "incorrect normal" |
| 1144 | + ); |
| 1145 | + |
| 1146 | + let degenerate = Triangle3d::new(Vec3::NEG_ONE, Vec3::ZERO, Vec3::ONE); |
| 1147 | + assert!(degenerate.is_degenerate(), "did not find degenerate"); |
| 1148 | + } |
1177 | 1149 | }
|
0 commit comments