summaryrefslogtreecommitdiffstats
path: root/third_party/rust/plane-split/tests/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/plane-split/tests/main.rs')
-rw-r--r--third_party/rust/plane-split/tests/main.rs341
1 files changed, 341 insertions, 0 deletions
diff --git a/third_party/rust/plane-split/tests/main.rs b/third_party/rust/plane-split/tests/main.rs
new file mode 100644
index 0000000000..0bcac5a179
--- /dev/null
+++ b/third_party/rust/plane-split/tests/main.rs
@@ -0,0 +1,341 @@
+use euclid::{
+ approxeq::ApproxEq,
+ default::{Rect, Size2D, Transform3D},
+ point2, point3, vec3, Angle,
+};
+use plane_split::{Intersection, Line, LineProjection, NegativeHemisphereError, Plane, Polygon};
+
+#[test]
+fn line_proj_bounds() {
+ assert_eq!(
+ (-5.0f64, 4.0),
+ LineProjection {
+ markers: [-5.0f64, 1.0, 4.0, 2.0]
+ }
+ .get_bounds()
+ );
+ assert_eq!(
+ (1f64, 4.0),
+ LineProjection {
+ markers: [4f64, 3.0, 2.0, 1.0]
+ }
+ .get_bounds()
+ );
+}
+
+#[test]
+fn valid() {
+ let poly_a: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 0.0, 0.0),
+ point3(1.0, 1.0, 1.0),
+ point3(1.0, 1.0, 0.0),
+ point3(0.0, 1.0, 1.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 1.0, 0.0),
+ offset: -1.0,
+ },
+ anchor: 0,
+ };
+ assert!(!poly_a.is_valid()); // points[0] is outside
+ let poly_b: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 1.0, 0.0),
+ point3(1.0, 1.0, 1.0),
+ point3(1.0, 1.0, 0.0),
+ point3(0.0, 1.0, 1.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 1.0, 0.0),
+ offset: -1.0,
+ },
+ anchor: 0,
+ };
+ assert!(!poly_b.is_valid()); // winding is incorrect
+ let poly_c: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 0.0, 1.0),
+ point3(1.0, 0.0, 1.0),
+ point3(1.0, 1.0, 1.0),
+ point3(0.0, 1.0, 1.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 0.0, 1.0),
+ offset: -1.0,
+ },
+ anchor: 0,
+ };
+ assert!(poly_c.is_valid());
+}
+
+#[test]
+fn empty() {
+ let poly = Polygon::from_points(
+ [
+ point3(0.0, 0.0, 1.0),
+ point3(0.0, 0.0, 1.0),
+ point3(0.0, 0.00000001, 1.0),
+ point3(1.0, 0.0, 0.0),
+ ],
+ 1usize,
+ );
+ assert_eq!(None, poly);
+}
+
+fn test_transformed(rect: Rect<f64>, transform: Transform3D<f64>) {
+ let poly = Polygon::from_transformed_rect(rect, transform, 0).unwrap();
+ assert!(poly.is_valid());
+
+ let inv_transform = transform.inverse().unwrap();
+ let poly2 =
+ Polygon::from_transformed_rect_with_inverse(rect, &transform, &inv_transform, 0).unwrap();
+ assert_eq!(poly.points, poly2.points);
+ assert!(poly.plane.offset.approx_eq(&poly2.plane.offset));
+ assert!(poly.plane.normal.dot(poly2.plane.normal).approx_eq(&1.0));
+}
+
+#[test]
+fn from_transformed_rect() {
+ let rect = Rect::new(point2(10.0, 10.0), Size2D::new(20.0, 30.0));
+ let transform = Transform3D::rotation(0.5f64.sqrt(), 0.0, 0.5f64.sqrt(), Angle::radians(5.0))
+ .pre_translate(vec3(0.0, 0.0, 10.0));
+ test_transformed(rect, transform);
+}
+
+#[test]
+fn from_transformed_rect_perspective() {
+ let rect = Rect::new(point2(-10.0, -5.0), Size2D::new(20.0, 30.0));
+ let mut transform = Transform3D::perspective(400.0).pre_translate(vec3(0.0, 0.0, 100.0));
+ transform.m44 = 0.7; //for fun
+ test_transformed(rect, transform);
+}
+
+#[test]
+fn untransform_point() {
+ let poly: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 0.0, 0.0),
+ point3(0.5, 1.0, 0.0),
+ point3(1.5, 1.0, 0.0),
+ point3(1.0, 0.0, 0.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 1.0, 0.0),
+ offset: 0.0,
+ },
+ anchor: 0,
+ };
+ assert_eq!(poly.untransform_point(poly.points[0]), point2(0.0, 0.0));
+ assert_eq!(poly.untransform_point(poly.points[1]), point2(1.0, 0.0));
+ assert_eq!(poly.untransform_point(poly.points[2]), point2(1.0, 1.0));
+ assert_eq!(poly.untransform_point(poly.points[3]), point2(0.0, 1.0));
+}
+
+#[test]
+fn are_outside() {
+ let plane = Plane {
+ normal: vec3(0.0, 0.0, 1.0),
+ offset: -1.0,
+ };
+ assert!(plane.are_outside(&[point3(0.0, 0.0, 1.1), point3(1.0, 1.0, 2.0),]));
+ assert!(plane.are_outside(&[point3(0.5, 0.5, 1.0),]));
+ assert!(!plane.are_outside(&[point3(0.0, 0.0, 1.0), point3(0.0, 0.0, -1.0),]));
+}
+
+#[test]
+fn intersect() {
+ let poly_a: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 0.0, 1.0),
+ point3(1.0, 0.0, 1.0),
+ point3(1.0, 1.0, 1.0),
+ point3(0.0, 1.0, 1.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 0.0, 1.0),
+ offset: -1.0,
+ },
+ anchor: 0,
+ };
+ assert!(poly_a.is_valid());
+ let poly_b: Polygon<usize> = Polygon {
+ points: [
+ point3(0.5, 0.0, 2.0),
+ point3(0.5, 1.0, 2.0),
+ point3(0.5, 1.0, 0.0),
+ point3(0.5, 0.0, 0.0),
+ ],
+ plane: Plane {
+ normal: vec3(1.0, 0.0, 0.0),
+ offset: -0.5,
+ },
+ anchor: 0,
+ };
+ assert!(poly_b.is_valid());
+
+ let intersection = match poly_a.intersect(&poly_b) {
+ Intersection::Inside(result) => result,
+ _ => panic!("Bad intersection"),
+ };
+ assert!(intersection.is_valid());
+ // confirm the origin is on both planes
+ assert!(poly_a
+ .plane
+ .signed_distance_to(&intersection.origin)
+ .approx_eq(&0.0));
+ assert!(poly_b
+ .plane
+ .signed_distance_to(&intersection.origin)
+ .approx_eq(&0.0));
+ // confirm the direction is coplanar to both planes
+ assert!(poly_a.plane.normal.dot(intersection.dir).approx_eq(&0.0));
+ assert!(poly_b.plane.normal.dot(intersection.dir).approx_eq(&0.0));
+
+ let poly_c: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, -1.0, 2.0),
+ point3(0.0, -1.0, 0.0),
+ point3(0.0, 0.0, 0.0),
+ point3(0.0, 0.0, 2.0),
+ ],
+ plane: Plane {
+ normal: vec3(1.0, 0.0, 0.0),
+ offset: 0.0,
+ },
+ anchor: 0,
+ };
+ assert!(poly_c.is_valid());
+ let poly_d: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 0.0, 0.5),
+ point3(1.0, 0.0, 0.5),
+ point3(1.0, 1.0, 0.5),
+ point3(0.0, 1.0, 0.5),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 0.0, 1.0),
+ offset: -0.5,
+ },
+ anchor: 0,
+ };
+ assert!(poly_d.is_valid());
+
+ assert!(poly_a.intersect(&poly_c).is_outside());
+ assert!(poly_a.intersect(&poly_d).is_outside());
+}
+
+fn test_cut(poly_base: &Polygon<usize>, extra_count: u8, line: Line) {
+ assert!(line.is_valid());
+
+ let normal = poly_base.plane.normal.cross(line.dir).normalize();
+ let mut poly = poly_base.clone();
+ let (extra1, extra2) = poly.split_with_normal(&line, &normal);
+ assert!(poly.is_valid() && poly_base.contains(&poly));
+ assert_eq!(extra_count > 0, extra1.is_some());
+ assert_eq!(extra_count > 1, extra2.is_some());
+ if let Some(extra) = extra1 {
+ assert!(extra.is_valid() && poly_base.contains(&extra));
+ }
+ if let Some(extra) = extra2 {
+ assert!(extra.is_valid() && poly_base.contains(&extra));
+ }
+}
+
+#[test]
+fn split() {
+ let poly: Polygon<usize> = Polygon {
+ points: [
+ point3(0.0, 1.0, 0.0),
+ point3(1.0, 1.0, 0.0),
+ point3(1.0, 1.0, 1.0),
+ point3(0.0, 1.0, 1.0),
+ ],
+ plane: Plane {
+ normal: vec3(0.0, 1.0, 0.0),
+ offset: -1.0,
+ },
+ anchor: 0,
+ };
+
+ // non-intersecting line
+ test_cut(
+ &poly,
+ 0,
+ Line {
+ origin: point3(0.0, 1.0, 0.5),
+ dir: vec3(0.0, 1.0, 0.0),
+ },
+ );
+
+ // simple cut (diff=2)
+ test_cut(
+ &poly,
+ 1,
+ Line {
+ origin: point3(0.0, 1.0, 0.5),
+ dir: vec3(1.0, 0.0, 0.0),
+ },
+ );
+
+ // complex cut (diff=1, wrapped)
+ test_cut(
+ &poly,
+ 2,
+ Line {
+ origin: point3(0.0, 1.0, 0.5),
+ dir: vec3(0.5f64.sqrt(), 0.0, -0.5f64.sqrt()),
+ },
+ );
+
+ // complex cut (diff=1, non-wrapped)
+ test_cut(
+ &poly,
+ 2,
+ Line {
+ origin: point3(0.5, 1.0, 0.0),
+ dir: vec3(0.5f64.sqrt(), 0.0, 0.5f64.sqrt()),
+ },
+ );
+
+ // complex cut (diff=3)
+ test_cut(
+ &poly,
+ 2,
+ Line {
+ origin: point3(0.5, 1.0, 0.0),
+ dir: vec3(-0.5f64.sqrt(), 0.0, 0.5f64.sqrt()),
+ },
+ );
+
+ // perfect diagonal
+ test_cut(
+ &poly,
+ 1,
+ Line {
+ origin: point3(0.0, 1.0, 0.0),
+ dir: vec3(0.5f64.sqrt(), 0.0, 0.5f64.sqrt()),
+ },
+ );
+}
+
+#[test]
+fn plane_unnormalized() {
+ let zero_vec = vec3(0.0000001, 0.0, 0.0);
+ let mut plane: Result<Option<Plane>, _> = Plane::from_unnormalized(zero_vec, 1.0);
+ assert_eq!(plane, Ok(None));
+ plane = Plane::from_unnormalized(zero_vec, 0.0);
+ assert_eq!(plane, Err(NegativeHemisphereError));
+ plane = Plane::from_unnormalized(zero_vec, -0.5);
+ assert_eq!(plane, Err(NegativeHemisphereError));
+
+ let plane = Plane::from_unnormalized(vec3(-3.0, 4.0, 0.0), 2.0)
+ .unwrap()
+ .unwrap();
+ let expected = Plane {
+ normal: vec3(-3.0 / 5.0, 4.0 / 5.0, 0.0),
+ offset: 2.0 / 5.0,
+ };
+ assert!(plane.normal.approx_eq(&expected.normal));
+ assert!(plane.offset.approx_eq(&expected.offset));
+}