forked from mirrors/gecko-dev
Bug 1678454 - Update plane-split dependency to 0.17.1 r=jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D97784
This commit is contained in:
parent
c9720a8ee7
commit
09630ed233
13 changed files with 386 additions and 314 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -3864,9 +3864,9 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
|||
|
||||
[[package]]
|
||||
name = "plane-split"
|
||||
version = "0.17.0"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2211e7ccc9b6260779dd9bad59f7b10889d6361974623b9e405afd7e7e764654"
|
||||
checksum = "f3f7075ec146b897b6e0faca47adeb7ed3d4f6eaa8145bf19db17311081b3f63"
|
||||
dependencies = [
|
||||
"binary-space-partition",
|
||||
"euclid",
|
||||
|
|
|
|||
6
gfx/wr/Cargo.lock
generated
6
gfx/wr/Cargo.lock
generated
|
|
@ -1175,7 +1175,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "plane-split"
|
||||
version = "0.17.0"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -1815,7 +1815,7 @@ dependencies = [
|
|||
"malloc_size_of_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -2180,7 +2180,7 @@ dependencies = [
|
|||
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
|
||||
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum plane-split 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2211e7ccc9b6260779dd9bad59f7b10889d6361974623b9e405afd7e7e764654"
|
||||
"checksum plane-split 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f7075ec146b897b6e0faca47adeb7ed3d4f6eaa8145bf19db17311081b3f63"
|
||||
"checksum png 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "910f09135b1ed14bb16be445a8c23ddf0777eca485fbfc7cee00d81fecab158a"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"bbf7428797ff113d822633c126ccf5e0e7584fe15c825048952623fdd99ab677","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"558d046c8c9ad79f23adef1e4b26c28c4599dcba56dadd60e2e7dc3a03ec2806","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"34c92cff76488fea23bee209fed62eee2db8c9687991c6413605961782e1317e","src/clip.rs":"e9ac9102f85709336088f3887b53273958aa9b2505d7ab06ba9a3e1e720aa540","src/lib.rs":"62613b64dacbfcd4727c5ce57e09bd9289db5a678f86dfe8544f1efc0f3f62b0","src/polygon.rs":"b8458d3c01dc06918b8410f363b19f15542522f1037cdd731f08b65e92a822bd","tests/clip.rs":"1a17f850cd770dbfb08c61779bf11f36f39e4315a00d3101c459e882b7982269","tests/main.rs":"5ebe911ddbb0e5449aacf060b977083c2bc43e3d8e5d5a3279d7e4950529f4a7","tests/split.rs":"fac076a403b87de1bdd0d11a54d36d0b02753868fc9cde5e5c5c1e03297da4ff"},"package":"2211e7ccc9b6260779dd9bad59f7b10889d6361974623b9e405afd7e7e764654"}
|
||||
{"files":{"Cargo.toml":"36e50e6fbc0d7e1b9587eacee54d75076503acf6d385e769ed606262dc4ff79b","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"558d046c8c9ad79f23adef1e4b26c28c4599dcba56dadd60e2e7dc3a03ec2806","benches/split.rs":"47dee7456a887b260af1a42590074ea2f4959c41344c636163434925d20ee903","rustfmt.toml":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","src/bsp.rs":"5c4f9685348b04cd716050a74f4fcabde8c64cca1e7f7c50734e26301f467f64","src/clip.rs":"df110afc471a350a70241e6f2b2fcf1d967ad012745ae82ddec43a8934982fda","src/lib.rs":"c56c64dc8d405a5a2875efd9579a55cf6f1820eddaa466f6c2c120114d8736c2","src/polygon.rs":"02ed361aca6b44c22121718f874a98e346f310cdcccbe23fd8a5ec1211a46371","tests/clip.rs":"f49b3ae961c4a69714f1eccc575304b8d8d823f018d51a0841fa70214ce7c309","tests/main.rs":"2f4999f199e456cba234b60d252329fcc0c081158168484468002a184d65cc07","tests/split.rs":"84ff0f87e4d37710ee952397f78c95450945baddd7b8f57b0b0422fff50ecc64"},"package":"f3f7075ec146b897b6e0faca47adeb7ed3d4f6eaa8145bf19db17311081b3f63"}
|
||||
3
third_party/rust/plane-split/Cargo.toml
vendored
3
third_party/rust/plane-split/Cargo.toml
vendored
|
|
@ -11,8 +11,9 @@
|
|||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "plane-split"
|
||||
version = "0.17.0"
|
||||
version = "0.17.1"
|
||||
authors = ["Dzmitry Malyshau <kvark@mozilla.com>"]
|
||||
description = "Plane splitting"
|
||||
documentation = "https://docs.rs/plane-split"
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ extern crate euclid;
|
|||
extern crate plane_split;
|
||||
extern crate test;
|
||||
|
||||
use std::sync::Arc;
|
||||
use euclid::vec3;
|
||||
use plane_split::{BspSplitter, Splitter, make_grid};
|
||||
use plane_split::{make_grid, BspSplitter, Splitter};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[bench]
|
||||
fn bench_bsp(b: &mut test::Bencher) {
|
||||
|
|
|
|||
0
third_party/rust/plane-split/rustfmt.toml
vendored
Executable file
0
third_party/rust/plane-split/rustfmt.toml
vendored
Executable file
64
third_party/rust/plane-split/src/bsp.rs
vendored
64
third_party/rust/plane-split/src/bsp.rs
vendored
|
|
@ -1,31 +1,34 @@
|
|||
use {Intersection, Plane, Polygon, Splitter};
|
||||
use is_zero;
|
||||
use crate::{is_zero, Intersection, Plane, Polygon, Splitter};
|
||||
|
||||
use binary_space_partition::{BspNode, Plane as BspPlane, PlaneCut};
|
||||
use euclid::{Point3D, Vector3D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::{approxeq::ApproxEq, Point3D, Vector3D};
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
use std::{fmt, iter, ops};
|
||||
|
||||
|
||||
impl<T, U, A> BspPlane for Polygon<T, U, A> where
|
||||
T: Copy + fmt::Debug + ApproxEq<T> +
|
||||
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
|
||||
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
|
||||
Zero + Float,
|
||||
impl<T, U, A> BspPlane for Polygon<T, U, A>
|
||||
where
|
||||
T: Copy
|
||||
+ fmt::Debug
|
||||
+ ApproxEq<T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>
|
||||
+ ops::Div<T, Output = T>
|
||||
+ Zero
|
||||
+ Float,
|
||||
U: fmt::Debug,
|
||||
A: Copy + fmt::Debug,
|
||||
{
|
||||
fn cut(&self, mut poly: Self) -> PlaneCut<Self> {
|
||||
debug!("\tCutting anchor {:?} by {:?}", poly.anchor, self.anchor);
|
||||
trace!("\t\tbase {:?}", self.plane);
|
||||
log::debug!("\tCutting anchor {:?} by {:?}", poly.anchor, self.anchor);
|
||||
log::trace!("\t\tbase {:?}", self.plane);
|
||||
|
||||
//Note: we treat `self` as a plane, and `poly` as a concrete polygon here
|
||||
let (intersection, dist) = match self.plane.intersect(&poly.plane) {
|
||||
None => {
|
||||
let ndot = self.plane.normal.dot(poly.plane.normal);
|
||||
debug!("\t\tNormals are aligned with {:?}", ndot);
|
||||
log::debug!("\t\tNormals are aligned with {:?}", ndot);
|
||||
let dist = self.plane.offset - ndot * poly.plane.offset;
|
||||
(Intersection::Coplanar, dist)
|
||||
}
|
||||
|
|
@ -45,11 +48,11 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
|
|||
// This is done to avoid mistakenly ordering items that should be on the same
|
||||
// plane but end up slightly different due to the floating point precision.
|
||||
Intersection::Coplanar if is_zero(dist) => {
|
||||
debug!("\t\tCoplanar at {:?}", dist);
|
||||
log::debug!("\t\tCoplanar at {:?}", dist);
|
||||
PlaneCut::Sibling(poly)
|
||||
}
|
||||
Intersection::Coplanar | Intersection::Outside => {
|
||||
debug!("\t\tOutside at {:?}", dist);
|
||||
log::debug!("\t\tOutside at {:?}", dist);
|
||||
if dist > T::zero() {
|
||||
PlaneCut::Cut {
|
||||
front: vec![poly],
|
||||
|
|
@ -63,7 +66,7 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
|
|||
}
|
||||
}
|
||||
Intersection::Inside(line) => {
|
||||
debug!("\t\tCut across {:?}", line);
|
||||
log::debug!("\t\tCut across {:?}", line);
|
||||
let (res_add1, res_add2) = poly.split_with_normal(&line, &self.plane.normal);
|
||||
let mut front = Vec::new();
|
||||
let mut back = Vec::new();
|
||||
|
|
@ -75,19 +78,16 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
|
|||
{
|
||||
let dist = self.plane.signed_distance_sum_to(&sub);
|
||||
if dist > T::zero() {
|
||||
trace!("\t\t\tdist {:?} -> front: {:?}", dist, sub);
|
||||
log::trace!("\t\t\tdist {:?} -> front: {:?}", dist, sub);
|
||||
front.push(sub)
|
||||
} else {
|
||||
trace!("\t\t\tdist {:?} -> back: {:?}", dist, sub);
|
||||
log::trace!("\t\t\tdist {:?} -> back: {:?}", dist, sub);
|
||||
back.push(sub)
|
||||
}
|
||||
}
|
||||
|
||||
PlaneCut::Cut {
|
||||
front,
|
||||
back,
|
||||
}
|
||||
},
|
||||
PlaneCut::Cut { front, back }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,6 @@ impl<T, U, A> BspPlane for Polygon<T, U, A> where
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Binary Space Partitioning splitter, uses a BSP tree.
|
||||
pub struct BspSplitter<T, U, A> {
|
||||
tree: BspNode<Polygon<T, U, A>>,
|
||||
|
|
@ -113,11 +112,18 @@ impl<T, U, A> BspSplitter<T, U, A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U, A> Splitter<T, U, A> for BspSplitter<T, U, A> where
|
||||
T: Copy + fmt::Debug + ApproxEq<T> +
|
||||
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
|
||||
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
|
||||
Zero + One + Float,
|
||||
impl<T, U, A> Splitter<T, U, A> for BspSplitter<T, U, A>
|
||||
where
|
||||
T: Copy
|
||||
+ fmt::Debug
|
||||
+ ApproxEq<T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>
|
||||
+ ops::Div<T, Output = T>
|
||||
+ Zero
|
||||
+ One
|
||||
+ Float,
|
||||
U: fmt::Debug,
|
||||
A: Copy + fmt::Debug + Default,
|
||||
{
|
||||
|
|
|
|||
78
third_party/rust/plane-split/src/clip.rs
vendored
78
third_party/rust/plane-split/src/clip.rs
vendored
|
|
@ -1,12 +1,10 @@
|
|||
use {Intersection, NegativeHemisphereError, Plane, Polygon};
|
||||
use crate::{Intersection, NegativeHemisphereError, Plane, Polygon};
|
||||
|
||||
use euclid::{Trig, Rect, Scale, Transform3D, Vector3D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::{approxeq::ApproxEq, Rect, Scale, Transform3D, Trig, Vector3D};
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
use std::{fmt, iter, mem, ops};
|
||||
|
||||
|
||||
/// A helper object to clip polygons by a number of planes.
|
||||
#[derive(Debug)]
|
||||
pub struct Clipper<T, U, A> {
|
||||
|
|
@ -16,13 +14,20 @@ pub struct Clipper<T, U, A> {
|
|||
}
|
||||
|
||||
impl<
|
||||
T: Copy + fmt::Debug + ApproxEq<T> +
|
||||
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
|
||||
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
|
||||
Zero + One + Float,
|
||||
U: fmt::Debug,
|
||||
A: Copy + fmt::Debug,
|
||||
> Clipper<T, U, A> {
|
||||
T: Copy
|
||||
+ fmt::Debug
|
||||
+ ApproxEq<T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>
|
||||
+ ops::Div<T, Output = T>
|
||||
+ Zero
|
||||
+ One
|
||||
+ Float,
|
||||
U: fmt::Debug,
|
||||
A: Copy + fmt::Debug,
|
||||
> Clipper<T, U, A>
|
||||
{
|
||||
/// Create a new clipper object.
|
||||
pub fn new() -> Self {
|
||||
Clipper {
|
||||
|
|
@ -49,33 +54,26 @@ impl<
|
|||
Some(bounds) => {
|
||||
let mx = Vector3D::new(t.m11, t.m21, t.m31);
|
||||
let left = bounds.origin.x;
|
||||
let plane_left = Plane::from_unnormalized(
|
||||
mx - mw * Scale::new(left),
|
||||
t.m41 - t.m44 * left,
|
||||
)?;
|
||||
let plane_left =
|
||||
Plane::from_unnormalized(mx - mw * Scale::new(left), t.m41 - t.m44 * left)?;
|
||||
let right = bounds.origin.x + bounds.size.width;
|
||||
let plane_right = Plane::from_unnormalized(
|
||||
mw * Scale::new(right) - mx,
|
||||
t.m44 * right - t.m41,
|
||||
)?;
|
||||
let plane_right =
|
||||
Plane::from_unnormalized(mw * Scale::new(right) - mx, t.m44 * right - t.m41)?;
|
||||
|
||||
let my = Vector3D::new(t.m12, t.m22, t.m32);
|
||||
let top = bounds.origin.y;
|
||||
let plane_top = Plane::from_unnormalized(
|
||||
my - mw * Scale::new(top),
|
||||
t.m42 - t.m44 * top,
|
||||
)?;
|
||||
let plane_top =
|
||||
Plane::from_unnormalized(my - mw * Scale::new(top), t.m42 - t.m44 * top)?;
|
||||
let bottom = bounds.origin.y + bounds.size.height;
|
||||
let plane_bottom = Plane::from_unnormalized(
|
||||
mw * Scale::new(bottom) - my,
|
||||
t.m44 * bottom - t.m42,
|
||||
)?;
|
||||
let plane_bottom =
|
||||
Plane::from_unnormalized(mw * Scale::new(bottom) - my, t.m44 * bottom - t.m42)?;
|
||||
|
||||
Some(plane_left
|
||||
.into_iter()
|
||||
.chain(plane_right)
|
||||
.chain(plane_top)
|
||||
.chain(plane_bottom)
|
||||
Some(
|
||||
plane_left
|
||||
.into_iter()
|
||||
.chain(plane_right)
|
||||
.chain(plane_top)
|
||||
.chain(plane_bottom),
|
||||
)
|
||||
}
|
||||
None => None,
|
||||
|
|
@ -84,8 +82,7 @@ impl<
|
|||
Ok(bounds_iter_maybe
|
||||
.into_iter()
|
||||
.flat_map(|pi| pi)
|
||||
.chain(plane_positive)
|
||||
)
|
||||
.chain(plane_positive))
|
||||
}
|
||||
|
||||
/// Add a clipping plane to the list. The plane will clip everything behind it,
|
||||
|
|
@ -96,7 +93,7 @@ impl<
|
|||
|
||||
/// Clip specified polygon by the contained planes, return the fragmented polygons.
|
||||
pub fn clip(&mut self, polygon: Polygon<T, U, A>) -> &[Polygon<T, U, A>] {
|
||||
debug!("\tClipping {:?}", polygon);
|
||||
log::debug!("\tClipping {:?}", polygon);
|
||||
self.results.clear();
|
||||
self.results.push(polygon);
|
||||
|
||||
|
|
@ -112,17 +109,15 @@ impl<
|
|||
iter::once(poly)
|
||||
.chain(res1)
|
||||
.chain(res2)
|
||||
.filter(|p| clip.signed_distance_sum_to(p) > T::zero())
|
||||
.filter(|p| clip.signed_distance_sum_to(p) > T::zero()),
|
||||
);
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
Intersection::Coplanar => {
|
||||
let ndot = poly.plane.normal.dot(clip.normal);
|
||||
clip.offset - ndot * poly.plane.offset
|
||||
}
|
||||
Intersection::Outside => {
|
||||
clip.signed_distance_sum_to(&poly)
|
||||
}
|
||||
Intersection::Outside => clip.signed_distance_sum_to(&poly),
|
||||
};
|
||||
|
||||
if dist > T::zero() {
|
||||
|
|
@ -157,7 +152,8 @@ impl<
|
|||
self.clips.pop();
|
||||
}
|
||||
|
||||
let polys = self.results
|
||||
let polys = self
|
||||
.results
|
||||
.drain(..)
|
||||
.flat_map(move |poly| poly.transform(transform));
|
||||
Ok(polys)
|
||||
|
|
|
|||
101
third_party/rust/plane-split/src/lib.rs
vendored
101
third_party/rust/plane-split/src/lib.rs
vendored
|
|
@ -10,18 +10,11 @@ the resulting sub-polygons by depth and avoid transparency blending issues.
|
|||
*/
|
||||
#![warn(missing_docs)]
|
||||
|
||||
extern crate binary_space_partition;
|
||||
extern crate euclid;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate num_traits;
|
||||
|
||||
mod bsp;
|
||||
mod clip;
|
||||
mod polygon;
|
||||
|
||||
use euclid::{Point3D, Scale, Vector3D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::{approxeq::ApproxEq, Point3D, Scale, Vector3D};
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
use std::ops;
|
||||
|
|
@ -30,20 +23,26 @@ pub use self::bsp::BspSplitter;
|
|||
pub use self::clip::Clipper;
|
||||
pub use self::polygon::{Intersection, LineProjection, Polygon};
|
||||
|
||||
|
||||
fn is_zero<T>(value: T) -> bool where
|
||||
T: Copy + Zero + ApproxEq<T> + ops::Mul<T, Output=T> {
|
||||
fn is_zero<T>(value: T) -> bool
|
||||
where
|
||||
T: Copy + Zero + ApproxEq<T> + ops::Mul<T, Output = T>,
|
||||
{
|
||||
//HACK: this is rough, but the original Epsilon is too strict
|
||||
(value * value).approx_eq(&T::zero())
|
||||
}
|
||||
|
||||
fn is_zero_vec<T, U>(vec: Vector3D<T, U>) -> bool where
|
||||
T: Copy + Zero + ApproxEq<T> +
|
||||
ops::Add<T, Output=T> + ops::Sub<T, Output=T> + ops::Mul<T, Output=T> {
|
||||
fn is_zero_vec<T, U>(vec: Vector3D<T, U>) -> bool
|
||||
where
|
||||
T: Copy
|
||||
+ Zero
|
||||
+ ApproxEq<T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>,
|
||||
{
|
||||
vec.dot(vec).approx_eq(&T::zero())
|
||||
}
|
||||
|
||||
|
||||
/// A generic line.
|
||||
#[derive(Debug)]
|
||||
pub struct Line<T, U> {
|
||||
|
|
@ -53,9 +52,15 @@ pub struct Line<T, U> {
|
|||
pub dir: Vector3D<T, U>,
|
||||
}
|
||||
|
||||
impl<T, U> Line<T, U> where
|
||||
T: Copy + One + Zero + ApproxEq<T> +
|
||||
ops::Add<T, Output=T> + ops::Sub<T, Output=T> + ops::Mul<T, Output=T>
|
||||
impl<T, U> Line<T, U>
|
||||
where
|
||||
T: Copy
|
||||
+ One
|
||||
+ Zero
|
||||
+ ApproxEq<T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>,
|
||||
{
|
||||
/// Check if the line has consistent parameters.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
|
|
@ -64,17 +69,14 @@ impl<T, U> Line<T, U> where
|
|||
/// Check if two lines match each other.
|
||||
pub fn matches(&self, other: &Self) -> bool {
|
||||
let diff = self.origin - other.origin;
|
||||
is_zero_vec(self.dir.cross(other.dir)) &&
|
||||
is_zero_vec(self.dir.cross(diff))
|
||||
is_zero_vec(self.dir.cross(other.dir)) && is_zero_vec(self.dir.cross(diff))
|
||||
}
|
||||
|
||||
/// Intersect an edge given by the end points.
|
||||
/// Returns the fraction of the edge where the intersection occurs.
|
||||
fn intersect_edge(
|
||||
&self,
|
||||
edge: ops::Range<Point3D<T, U>>,
|
||||
) -> Option<T>
|
||||
where T: ops::Div<T, Output=T>
|
||||
fn intersect_edge(&self, edge: ops::Range<Point3D<T, U>>) -> Option<T>
|
||||
where
|
||||
T: ops::Div<T, Output = T>,
|
||||
{
|
||||
let edge_vec = edge.end - edge.start;
|
||||
let origin_vec = self.origin - edge.start;
|
||||
|
|
@ -93,7 +95,6 @@ impl<T, U> Line<T, U> where
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// An infinite plane in 3D space, defined by equation:
|
||||
/// dot(v, normal) + offset = 0
|
||||
/// When used for plane splitting, it's defining a hemisphere
|
||||
|
|
@ -122,14 +123,22 @@ impl<T: Clone, U> Clone for Plane<T, U> {
|
|||
pub struct NegativeHemisphereError;
|
||||
|
||||
impl<
|
||||
T: Copy + Zero + One + Float + ApproxEq<T> +
|
||||
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
|
||||
ops::Mul<T, Output=T> + ops::Div<T, Output=T>,
|
||||
U,
|
||||
> Plane<T, U> {
|
||||
T: Copy
|
||||
+ Zero
|
||||
+ One
|
||||
+ Float
|
||||
+ ApproxEq<T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>
|
||||
+ ops::Div<T, Output = T>,
|
||||
U,
|
||||
> Plane<T, U>
|
||||
{
|
||||
/// Construct a new plane from unnormalized equation.
|
||||
pub fn from_unnormalized(
|
||||
normal: Vector3D<T, U>, offset: T
|
||||
normal: Vector3D<T, U>,
|
||||
offset: T,
|
||||
) -> Result<Option<Self>, NegativeHemisphereError> {
|
||||
let square_len = normal.square_length();
|
||||
if square_len < T::approx_epsilon() * T::approx_epsilon() {
|
||||
|
|
@ -163,7 +172,9 @@ impl<
|
|||
/// Compute the distance across the line to the plane plane,
|
||||
/// starting from the line origin.
|
||||
pub fn distance_to_line(&self, line: &Line<T, U>) -> T
|
||||
where T: ops::Neg<Output=T> {
|
||||
where
|
||||
T: ops::Neg<Output = T>,
|
||||
{
|
||||
self.signed_distance_to(&line.origin) / -self.normal.dot(line.dir)
|
||||
}
|
||||
|
||||
|
|
@ -197,11 +208,10 @@ impl<
|
|||
let w = self.normal.dot(other.normal);
|
||||
let divisor = T::one() - w * w;
|
||||
if divisor < T::approx_epsilon() * T::approx_epsilon() {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
let origin = Point3D::origin() +
|
||||
self.normal * ((other.offset * w - self.offset) / divisor) -
|
||||
other.normal* ((other.offset - self.offset * w) / divisor);
|
||||
let origin = Point3D::origin() + self.normal * ((other.offset * w - self.offset) / divisor)
|
||||
- other.normal * ((other.offset - self.offset * w) / divisor);
|
||||
|
||||
let cross_dir = self.normal.cross(other.normal);
|
||||
// note: the cross product isn't too close to zero
|
||||
|
|
@ -214,8 +224,6 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Generic plane splitter interface
|
||||
pub trait Splitter<T, U, A> {
|
||||
/// Reset the splitter results.
|
||||
|
|
@ -230,11 +238,7 @@ pub trait Splitter<T, U, A> {
|
|||
fn sort(&mut self, view: Vector3D<T, U>) -> &[Polygon<T, U, A>];
|
||||
|
||||
/// Process a set of polygons at once.
|
||||
fn solve(
|
||||
&mut self,
|
||||
input: &[Polygon<T, U, A>],
|
||||
view: Vector3D<T, U>,
|
||||
) -> &[Polygon<T, U, A>]
|
||||
fn solve(&mut self, input: &[Polygon<T, U, A>], view: Vector3D<T, U>) -> &[Polygon<T, U, A>]
|
||||
where
|
||||
T: Clone,
|
||||
U: Clone,
|
||||
|
|
@ -248,14 +252,13 @@ pub trait Splitter<T, U, A> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Helper method used for benchmarks and tests.
|
||||
/// Constructs a 3D grid of polygons.
|
||||
#[doc(hidden)]
|
||||
pub fn make_grid(count: usize) -> Vec<Polygon<f32, (), usize>> {
|
||||
let mut polys: Vec<Polygon<f32, (), usize>> = Vec::with_capacity(count*3);
|
||||
let mut polys: Vec<Polygon<f32, (), usize>> = Vec::with_capacity(count * 3);
|
||||
let len = count as f32;
|
||||
polys.extend((0 .. count).map(|i| Polygon {
|
||||
polys.extend((0..count).map(|i| Polygon {
|
||||
points: [
|
||||
Point3D::new(0.0, i as f32, 0.0),
|
||||
Point3D::new(len, i as f32, 0.0),
|
||||
|
|
@ -268,7 +271,7 @@ pub fn make_grid(count: usize) -> Vec<Polygon<f32, (), usize>> {
|
|||
},
|
||||
anchor: 0,
|
||||
}));
|
||||
polys.extend((0 .. count).map(|i| Polygon {
|
||||
polys.extend((0..count).map(|i| Polygon {
|
||||
points: [
|
||||
Point3D::new(i as f32, 0.0, 0.0),
|
||||
Point3D::new(i as f32, len, 0.0),
|
||||
|
|
@ -281,7 +284,7 @@ pub fn make_grid(count: usize) -> Vec<Polygon<f32, (), usize>> {
|
|||
},
|
||||
anchor: 0,
|
||||
}));
|
||||
polys.extend((0 .. count).map(|i| Polygon {
|
||||
polys.extend((0..count).map(|i| Polygon {
|
||||
points: [
|
||||
Point3D::new(0.0, 0.0, i as f32),
|
||||
Point3D::new(len, 0.0, i as f32),
|
||||
|
|
|
|||
200
third_party/rust/plane-split/src/polygon.rs
vendored
200
third_party/rust/plane-split/src/polygon.rs
vendored
|
|
@ -1,26 +1,28 @@
|
|||
use {Line, Plane, is_zero};
|
||||
use crate::{is_zero, Line, Plane};
|
||||
|
||||
use euclid::default::Point2D;
|
||||
use euclid::{Transform3D, Point3D, Vector3D, Rect};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::Trig;
|
||||
use euclid::{approxeq::ApproxEq, default::Point2D, Point3D, Rect, Transform3D, Trig, Vector3D};
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
use std::{fmt, iter, mem, ops};
|
||||
|
||||
|
||||
/// The projection of a `Polygon` on a line.
|
||||
pub struct LineProjection<T> {
|
||||
/// Projected value of each point in the polygon.
|
||||
pub markers: [T; 4],
|
||||
}
|
||||
|
||||
impl<T> LineProjection<T> where
|
||||
T : Copy + PartialOrd + ops::Sub<T, Output=T> + ops::Add<T, Output=T>
|
||||
impl<T> LineProjection<T>
|
||||
where
|
||||
T: Copy + PartialOrd + ops::Sub<T, Output = T> + ops::Add<T, Output = T>,
|
||||
{
|
||||
/// Get the min/max of the line projection markers.
|
||||
pub fn get_bounds(&self) -> (T, T) {
|
||||
let (mut a, mut b, mut c, mut d) = (self.markers[0], self.markers[1], self.markers[2], self.markers[3]);
|
||||
let (mut a, mut b, mut c, mut d) = (
|
||||
self.markers[0],
|
||||
self.markers[1],
|
||||
self.markers[2],
|
||||
self.markers[3],
|
||||
);
|
||||
// bitonic sort of 4 elements
|
||||
// we could not just use `min/max` since they require `Ord` bound
|
||||
//TODO: make it nicer
|
||||
|
|
@ -49,14 +51,21 @@ impl<T> LineProjection<T> where
|
|||
let span = self.get_bounds();
|
||||
let other_span = other.get_bounds();
|
||||
// compute the total footprint
|
||||
let left = if span.0 < other_span.0 { span.0 } else { other_span.0 };
|
||||
let right = if span.1 > other_span.1 { span.1 } else { other_span.1 };
|
||||
let left = if span.0 < other_span.0 {
|
||||
span.0
|
||||
} else {
|
||||
other_span.0
|
||||
};
|
||||
let right = if span.1 > other_span.1 {
|
||||
span.1
|
||||
} else {
|
||||
other_span.1
|
||||
};
|
||||
// they intersect if the footprint is smaller than the sum
|
||||
right - left < span.1 - span.0 + other_span.1 - other_span.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Polygon intersection results.
|
||||
pub enum Intersection<T> {
|
||||
/// Polygons are coplanar, including the case of being on the same plane.
|
||||
|
|
@ -84,7 +93,6 @@ impl<T> Intersection<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// A convex polygon with 4 points lying on a plane.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Polygon<T, U, A> {
|
||||
|
|
@ -102,9 +110,9 @@ impl<T: Clone, U, A: Copy> Clone for Polygon<T, U, A> {
|
|||
Polygon {
|
||||
points: [
|
||||
self.points[0].clone(),
|
||||
self.points[1].clone(),
|
||||
self.points[2].clone(),
|
||||
self.points[3].clone(),
|
||||
self.points[1].clone(),
|
||||
self.points[2].clone(),
|
||||
self.points[3].clone(),
|
||||
],
|
||||
plane: self.plane.clone(),
|
||||
anchor: self.anchor,
|
||||
|
|
@ -112,27 +120,31 @@ impl<T: Clone, U, A: Copy> Clone for Polygon<T, U, A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U, A> Polygon<T, U, A> where
|
||||
T: Copy + fmt::Debug + ApproxEq<T> +
|
||||
ops::Sub<T, Output=T> + ops::Add<T, Output=T> +
|
||||
ops::Mul<T, Output=T> + ops::Div<T, Output=T> +
|
||||
Zero + One + Float,
|
||||
impl<T, U, A> Polygon<T, U, A>
|
||||
where
|
||||
T: Copy
|
||||
+ fmt::Debug
|
||||
+ ApproxEq<T>
|
||||
+ ops::Sub<T, Output = T>
|
||||
+ ops::Add<T, Output = T>
|
||||
+ ops::Mul<T, Output = T>
|
||||
+ ops::Div<T, Output = T>
|
||||
+ Zero
|
||||
+ One
|
||||
+ Float,
|
||||
U: fmt::Debug,
|
||||
A: Copy,
|
||||
{
|
||||
/// Construct a polygon from points that are already transformed.
|
||||
/// Return None if the polygon doesn't contain any space.
|
||||
pub fn from_points(
|
||||
points: [Point3D<T, U>; 4],
|
||||
anchor: A,
|
||||
) -> Option<Self> {
|
||||
pub fn from_points(points: [Point3D<T, U>; 4], anchor: A) -> Option<Self> {
|
||||
let edge1 = points[1] - points[0];
|
||||
let edge2 = points[2] - points[0];
|
||||
let edge3 = points[3] - points[0];
|
||||
let edge4 = points[3] - points[1];
|
||||
|
||||
if edge2.square_length() < T::epsilon() || edge4.square_length() < T::epsilon() {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
|
||||
// one of them can be zero for redundant polygons produced by plane splitting
|
||||
|
|
@ -148,15 +160,11 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
normal_rough2 / square_length2.sqrt()
|
||||
};
|
||||
|
||||
let offset = -points[0].to_vector()
|
||||
.dot(normal);
|
||||
let offset = -points[0].to_vector().dot(normal);
|
||||
|
||||
Some(Polygon {
|
||||
points,
|
||||
plane: Plane {
|
||||
normal,
|
||||
offset,
|
||||
},
|
||||
plane: Plane { normal, offset },
|
||||
anchor,
|
||||
})
|
||||
}
|
||||
|
|
@ -188,7 +196,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
anchor: A,
|
||||
) -> Option<Self>
|
||||
where
|
||||
T: Trig + ops::Neg<Output=T>,
|
||||
T: Trig + ops::Neg<Output = T>,
|
||||
{
|
||||
let min = rect.min();
|
||||
let max = rect.max();
|
||||
|
|
@ -210,7 +218,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
anchor: A,
|
||||
) -> Option<Self>
|
||||
where
|
||||
T: Trig + ops::Neg<Output=T>,
|
||||
T: Trig + ops::Neg<Output = T>,
|
||||
{
|
||||
let min = rect.min();
|
||||
let max = rect.max();
|
||||
|
|
@ -230,15 +238,12 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
None
|
||||
} else {
|
||||
let normal = normal_raw / normal_sql.sqrt();
|
||||
let offset = -Vector3D::new(transform.m41, transform.m42, transform.m43)
|
||||
.dot(normal) / transform.m44;
|
||||
let offset = -Vector3D::new(transform.m41, transform.m42, transform.m43).dot(normal)
|
||||
/ transform.m44;
|
||||
|
||||
Some(Polygon {
|
||||
points,
|
||||
plane: Plane {
|
||||
normal,
|
||||
offset,
|
||||
},
|
||||
plane: Plane { normal, offset },
|
||||
anchor,
|
||||
})
|
||||
}
|
||||
|
|
@ -266,9 +271,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
}
|
||||
|
||||
/// Transform a polygon by an affine transform (preserving straight lines).
|
||||
pub fn transform<V>(
|
||||
&self, transform: &Transform3D<T, U, V>
|
||||
) -> Option<Polygon<T, V, A>>
|
||||
pub fn transform<V>(&self, transform: &Transform3D<T, U, V>) -> Option<Polygon<T, V, A>>
|
||||
where
|
||||
T: Trig,
|
||||
V: fmt::Debug,
|
||||
|
|
@ -289,7 +292,8 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// Check if all the points are indeed placed on the plane defined by
|
||||
/// the normal and offset, and the winding order is consistent.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
let is_planar = self.points
|
||||
let is_planar = self
|
||||
.points
|
||||
.iter()
|
||||
.all(|p| is_zero(self.plane.signed_distance_to(p)));
|
||||
let edges = [
|
||||
|
|
@ -309,8 +313,8 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// Check if the polygon doesn't contain any space. This may happen
|
||||
/// after a sequence of splits, and such polygons should be discarded.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
(self.points[0] - self.points[2]).square_length() < T::epsilon() ||
|
||||
(self.points[1] - self.points[3]).square_length() < T::epsilon()
|
||||
(self.points[0] - self.points[2]).square_length() < T::epsilon()
|
||||
|| (self.points[1] - self.points[3]).square_length() < T::epsilon()
|
||||
}
|
||||
|
||||
/// Check if this polygon contains another one.
|
||||
|
|
@ -335,13 +339,13 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// Compute the line of intersection with an infinite plane.
|
||||
pub fn intersect_plane(&self, other: &Plane<T, U>) -> Intersection<Line<T, U>> {
|
||||
if other.are_outside(&self.points) {
|
||||
debug!("\t\tOutside of the plane");
|
||||
return Intersection::Outside
|
||||
log::debug!("\t\tOutside of the plane");
|
||||
return Intersection::Outside;
|
||||
}
|
||||
match self.plane.intersect(&other) {
|
||||
Some(line) => Intersection::Inside(line),
|
||||
None => {
|
||||
debug!("\t\tCoplanar");
|
||||
log::debug!("\t\tCoplanar");
|
||||
Intersection::Coplanar
|
||||
}
|
||||
}
|
||||
|
|
@ -350,8 +354,8 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// Compute the line of intersection with another polygon.
|
||||
pub fn intersect(&self, other: &Self) -> Intersection<Line<T, U>> {
|
||||
if self.plane.are_outside(&other.points) || other.plane.are_outside(&self.points) {
|
||||
debug!("\t\tOne is completely outside of the other");
|
||||
return Intersection::Outside
|
||||
log::debug!("\t\tOne is completely outside of the other");
|
||||
return Intersection::Outside;
|
||||
}
|
||||
match self.plane.intersect(&other.plane) {
|
||||
Some(line) => {
|
||||
|
|
@ -361,12 +365,12 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
Intersection::Inside(line)
|
||||
} else {
|
||||
// projections on the line don't intersect
|
||||
debug!("\t\tProjection is outside");
|
||||
log::debug!("\t\tProjection is outside");
|
||||
Intersection::Outside
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug!("\t\tCoplanar");
|
||||
log::debug!("\t\tCoplanar");
|
||||
Intersection::Coplanar
|
||||
}
|
||||
}
|
||||
|
|
@ -379,7 +383,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
) -> (Option<Self>, Option<Self>) {
|
||||
//TODO: can be optimized for when the polygon has a redundant 4th vertex
|
||||
//TODO: can be simplified greatly if only working with triangles
|
||||
debug!("\t\tReached complex case [{}, {}]", first.0, second.0);
|
||||
log::debug!("\t\tReached complex case [{}, {}]", first.0, second.0);
|
||||
let base = first.0;
|
||||
assert!(base < self.points.len());
|
||||
match second.0 - first.0 {
|
||||
|
|
@ -392,7 +396,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
self.points[(base + 2) & 3],
|
||||
self.points[base],
|
||||
],
|
||||
.. self.clone()
|
||||
..self.clone()
|
||||
};
|
||||
// triangle on the near side of the diagonal
|
||||
let other2 = Polygon {
|
||||
|
|
@ -402,15 +406,10 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
self.points[base],
|
||||
self.points[base],
|
||||
],
|
||||
.. self.clone()
|
||||
..self.clone()
|
||||
};
|
||||
// triangle being cut out
|
||||
self.points = [
|
||||
first.1,
|
||||
self.points[(base + 1) & 3],
|
||||
second.1,
|
||||
second.1,
|
||||
];
|
||||
self.points = [first.1, self.points[(base + 1) & 3], second.1, second.1];
|
||||
(Some(other1), Some(other2))
|
||||
}
|
||||
2 => {
|
||||
|
|
@ -422,7 +421,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
self.points[(base + 2) & 3],
|
||||
second.1,
|
||||
],
|
||||
.. self.clone()
|
||||
..self.clone()
|
||||
};
|
||||
// rect on the near side
|
||||
self.points = [
|
||||
|
|
@ -442,7 +441,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
self.points[(base + 3) & 3],
|
||||
second.1,
|
||||
],
|
||||
.. self.clone()
|
||||
..self.clone()
|
||||
};
|
||||
// triangle on the far side of the diagonal
|
||||
let other2 = Polygon {
|
||||
|
|
@ -452,15 +451,10 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
self.points[(base + 3) & 3],
|
||||
self.points[(base + 3) & 3],
|
||||
],
|
||||
.. self.clone()
|
||||
..self.clone()
|
||||
};
|
||||
// triangle being cut out
|
||||
self.points = [
|
||||
first.1,
|
||||
second.1,
|
||||
self.points[base],
|
||||
self.points[base],
|
||||
];
|
||||
self.points = [first.1, second.1, self.points[base], self.points[base]];
|
||||
(Some(other1), Some(other2))
|
||||
}
|
||||
_ => panic!("Unexpected indices {} {}", first.0, second.0),
|
||||
|
|
@ -471,24 +465,29 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// Will do nothing if the line doesn't belong to the polygon plane.
|
||||
#[deprecated(note = "Use split_with_normal instead")]
|
||||
pub fn split(&mut self, line: &Line<T, U>) -> (Option<Self>, Option<Self>) {
|
||||
debug!("\tSplitting");
|
||||
log::debug!("\tSplitting");
|
||||
// check if the cut is within the polygon plane first
|
||||
if !is_zero(self.plane.normal.dot(line.dir)) ||
|
||||
!is_zero(self.plane.signed_distance_to(&line.origin)) {
|
||||
debug!("\t\tDoes not belong to the plane, normal dot={:?}, origin distance={:?}",
|
||||
self.plane.normal.dot(line.dir), self.plane.signed_distance_to(&line.origin));
|
||||
return (None, None)
|
||||
if !is_zero(self.plane.normal.dot(line.dir))
|
||||
|| !is_zero(self.plane.signed_distance_to(&line.origin))
|
||||
{
|
||||
log::debug!(
|
||||
"\t\tDoes not belong to the plane, normal dot={:?}, origin distance={:?}",
|
||||
self.plane.normal.dot(line.dir),
|
||||
self.plane.signed_distance_to(&line.origin)
|
||||
);
|
||||
return (None, None);
|
||||
}
|
||||
// compute the intersection points for each edge
|
||||
let mut cuts = [None; 4];
|
||||
for ((&b, &a), cut) in self.points
|
||||
for ((&b, &a), cut) in self
|
||||
.points
|
||||
.iter()
|
||||
.cycle()
|
||||
.skip(1)
|
||||
.zip(self.points.iter())
|
||||
.zip(cuts.iter_mut())
|
||||
{
|
||||
if let Some(t) = line.intersect_edge(a .. b) {
|
||||
if let Some(t) = line.intersect_edge(a..b) {
|
||||
if t >= T::zero() && t < T::one() {
|
||||
*cut = Some(a + (b - a) * t);
|
||||
}
|
||||
|
|
@ -499,7 +498,7 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
Some(pos) => pos,
|
||||
None => return (None, None),
|
||||
};
|
||||
let second = match cuts[first+1 ..].iter().position(|c| c.is_some()) {
|
||||
let second = match cuts[first + 1..].iter().position(|c| c.is_some()) {
|
||||
Some(pos) => first + 1 + pos,
|
||||
None => return (None, None),
|
||||
};
|
||||
|
|
@ -514,9 +513,11 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
/// forms the side direction here, and figuring out the actual line of split isn't needed.
|
||||
/// Will do nothing if the line doesn't belong to the polygon plane.
|
||||
pub fn split_with_normal(
|
||||
&mut self, line: &Line<T, U>, normal: &Vector3D<T, U>,
|
||||
&mut self,
|
||||
line: &Line<T, U>,
|
||||
normal: &Vector3D<T, U>,
|
||||
) -> (Option<Self>, Option<Self>) {
|
||||
debug!("\tSplitting with normal");
|
||||
log::debug!("\tSplitting with normal");
|
||||
// figure out which side of the split does each point belong to
|
||||
let mut sides = [T::zero(); 4];
|
||||
let (mut cut_positive, mut cut_negative) = (None, None);
|
||||
|
|
@ -548,8 +549,15 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
// Given that we are intersecting two straight lines, the triangles on both
|
||||
// sides of intersection are alike, so distances along the [point0, point1] line
|
||||
// are proportional to the side vector lengths we just computed: (side0, side1).
|
||||
let point = (*point0 * side1.abs() + point1.to_vector() * side0.abs()) / (side0 - side1).abs();
|
||||
debug_assert_eq!(*cut, None);
|
||||
let point =
|
||||
(*point0 * side1.abs() + point1.to_vector() * side0.abs()) / (side0 - side1).abs();
|
||||
if cut.is_some() {
|
||||
// We don't expect that the direction changes more than once, unless
|
||||
// the polygon is close to redundant, and we hit precision issues when
|
||||
// computing the sides.
|
||||
log::warn!("Splitting failed due to precision issues: {:?}", sides);
|
||||
break;
|
||||
}
|
||||
*cut = Some((i, point));
|
||||
}
|
||||
// form new polygons
|
||||
|
|
@ -563,3 +571,27 @@ impl<T, U, A> Polygon<T, U, A> where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_precision() {
|
||||
// regression test for https://bugzilla.mozilla.org/show_bug.cgi?id=1678454
|
||||
let mut polygon = Polygon::<_, (), ()> {
|
||||
points: [
|
||||
Point3D::new(300.0102, 150.00958, 0.0),
|
||||
Point3D::new(606.0, 306.0, 0.0),
|
||||
Point3D::new(300.21954, 150.11946, 0.0),
|
||||
Point3D::new(300.08844, 150.05064, 0.0),
|
||||
],
|
||||
plane: Plane {
|
||||
normal: Vector3D::zero(),
|
||||
offset: 0.0,
|
||||
},
|
||||
anchor: (),
|
||||
};
|
||||
let line = Line {
|
||||
origin: Point3D::new(3.0690663, -5.8472385, 0.0),
|
||||
dir: Vector3D::new(0.8854436, 0.46474677, -0.0),
|
||||
};
|
||||
let normal = Vector3D::new(0.46474662, -0.8854434, -0.0006389789);
|
||||
polygon.split_with_normal(&line, &normal);
|
||||
}
|
||||
|
|
|
|||
39
third_party/rust/plane-split/tests/clip.rs
vendored
39
third_party/rust/plane-split/tests/clip.rs
vendored
|
|
@ -1,16 +1,13 @@
|
|||
extern crate euclid;
|
||||
extern crate plane_split;
|
||||
|
||||
use euclid::{point3, rect, vec3};
|
||||
use euclid::{Angle, Rect, Transform3D};
|
||||
use euclid::{point3, rect, vec3, Angle, Rect, Transform3D};
|
||||
use plane_split::{Clipper, Plane, Polygon};
|
||||
|
||||
use std::f32::consts::FRAC_PI_4;
|
||||
|
||||
|
||||
#[test]
|
||||
fn clip_in() {
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), 20.0).unwrap().unwrap();
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), 20.0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut clipper = Clipper::new();
|
||||
clipper.add(plane);
|
||||
|
||||
|
|
@ -22,7 +19,8 @@ fn clip_in() {
|
|||
point3(-10.0, 10.0, 0.0),
|
||||
],
|
||||
0,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let results = clipper.clip(poly.clone());
|
||||
assert_eq!(results[0], poly);
|
||||
|
|
@ -31,7 +29,9 @@ fn clip_in() {
|
|||
|
||||
#[test]
|
||||
fn clip_out() {
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), -20.0).unwrap().unwrap();
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), -20.0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut clipper = Clipper::new();
|
||||
clipper.add(plane);
|
||||
|
||||
|
|
@ -43,7 +43,8 @@ fn clip_out() {
|
|||
point3(-10.0, 10.0, 0.0),
|
||||
],
|
||||
0,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let results = clipper.clip(poly);
|
||||
assert!(results.is_empty());
|
||||
|
|
@ -66,7 +67,8 @@ fn clip_parallel() {
|
|||
point3(-10.0, 10.0, 0.0),
|
||||
],
|
||||
0,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let results = clipper.clip(poly);
|
||||
assert!(results.is_empty());
|
||||
|
|
@ -74,7 +76,9 @@ fn clip_parallel() {
|
|||
|
||||
#[test]
|
||||
fn clip_repeat() {
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), 0.0).unwrap().unwrap();
|
||||
let plane: Plane<f32, ()> = Plane::from_unnormalized(vec3(1.0, 0.0, 1.0), 0.0)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
let mut clipper = Clipper::new();
|
||||
clipper.add(plane.clone());
|
||||
clipper.add(plane.clone());
|
||||
|
|
@ -87,7 +91,8 @@ fn clip_repeat() {
|
|||
point3(-10.0, 10.0, 0.0),
|
||||
],
|
||||
0,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let results = clipper.clip(poly);
|
||||
assert_eq!(results.len(), 1);
|
||||
|
|
@ -98,8 +103,7 @@ fn clip_repeat() {
|
|||
fn clip_transformed() {
|
||||
let t_rot: Transform3D<f32, (), ()> =
|
||||
Transform3D::rotation(0.0, 1.0, 0.0, Angle::radians(-FRAC_PI_4));
|
||||
let t_div: Transform3D<f32, (), ()> =
|
||||
Transform3D::perspective(5.0);
|
||||
let t_div: Transform3D<f32, (), ()> = Transform3D::perspective(5.0);
|
||||
let transform = t_rot.then(&t_div);
|
||||
|
||||
let polygon = Polygon::from_rect(rect(-10.0, -10.0, 20.0, 20.0), 0);
|
||||
|
|
@ -126,10 +130,7 @@ fn clip_badly_transformed() {
|
|||
#[test]
|
||||
fn clip_near_coplanar() {
|
||||
let tx = Transform3D::<f32, (), ()>::new(
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
-960.0, -625.0, 1.0, -1.0,
|
||||
100.0, -2852.0, 0.0, 1.0,
|
||||
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, -960.0, -625.0, 1.0, -1.0, 100.0, -2852.0, 0.0, 1.0,
|
||||
);
|
||||
let mut clipper = Clipper::new();
|
||||
let polygon = Polygon::from_rect(rect(0.0, 0.0, 1703.0, 4020.0), 0);
|
||||
|
|
|
|||
146
third_party/rust/plane-split/tests/main.rs
vendored
146
third_party/rust/plane-split/tests/main.rs
vendored
|
|
@ -1,15 +1,22 @@
|
|||
extern crate euclid;
|
||||
extern crate plane_split;
|
||||
|
||||
use euclid::{Angle, Rect, Size2D, Transform3D, point2, point3, vec3};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use euclid::{approxeq::ApproxEq, point2, point3, vec3, Angle, Rect, Size2D, Transform3D};
|
||||
use plane_split::{Intersection, Line, LineProjection, NegativeHemisphereError, Plane, Polygon};
|
||||
|
||||
|
||||
#[test]
|
||||
fn line_proj_bounds() {
|
||||
assert_eq!((-5i8, 4), LineProjection { markers: [-5i8, 1, 4, 2] }.get_bounds());
|
||||
assert_eq!((1f32, 4.0), LineProjection { markers: [4f32, 3.0, 2.0, 1.0] }.get_bounds());
|
||||
assert_eq!(
|
||||
(-5i8, 4),
|
||||
LineProjection {
|
||||
markers: [-5i8, 1, 4, 2]
|
||||
}
|
||||
.get_bounds()
|
||||
);
|
||||
assert_eq!(
|
||||
(1f32, 4.0),
|
||||
LineProjection {
|
||||
markers: [4f32, 3.0, 2.0, 1.0]
|
||||
}
|
||||
.get_bounds()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -77,7 +84,8 @@ fn test_transformed(rect: Rect<f32, ()>, transform: Transform3D<f32, (), ()>) {
|
|||
assert!(poly.is_valid());
|
||||
|
||||
let inv_transform = transform.inverse().unwrap();
|
||||
let poly2 = Polygon::from_transformed_rect_with_inverse(rect, &transform, &inv_transform, 0).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));
|
||||
|
|
@ -86,8 +94,7 @@ fn test_transformed(rect: Rect<f32, ()>, transform: Transform3D<f32, (), ()>) {
|
|||
#[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.5f32.sqrt(), 0.0, 0.5f32.sqrt(), Angle::radians(5.0))
|
||||
let transform = Transform3D::rotation(0.5f32.sqrt(), 0.0, 0.5f32.sqrt(), Angle::radians(5.0))
|
||||
.pre_translate(vec3(0.0, 0.0, 10.0));
|
||||
test_transformed(rect, transform);
|
||||
}
|
||||
|
|
@ -95,9 +102,7 @@ fn from_transformed_rect() {
|
|||
#[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));
|
||||
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);
|
||||
}
|
||||
|
|
@ -129,17 +134,9 @@ fn are_outside() {
|
|||
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),
|
||||
]));
|
||||
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]
|
||||
|
|
@ -179,8 +176,14 @@ fn intersect() {
|
|||
};
|
||||
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));
|
||||
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));
|
||||
|
|
@ -218,11 +221,7 @@ fn intersect() {
|
|||
assert!(poly_a.intersect(&poly_d).is_outside());
|
||||
}
|
||||
|
||||
fn test_cut(
|
||||
poly_base: &Polygon<f32, (), usize>,
|
||||
extra_count: u8,
|
||||
line: Line<f32, ()>,
|
||||
) {
|
||||
fn test_cut(poly_base: &Polygon<f32, (), usize>, extra_count: u8, line: Line<f32, ()>) {
|
||||
assert!(line.is_valid());
|
||||
|
||||
let normal = poly_base.plane.normal.cross(line.dir).normalize();
|
||||
|
|
@ -256,40 +255,64 @@ fn split() {
|
|||
};
|
||||
|
||||
// non-intersecting line
|
||||
test_cut(&poly, 0, Line {
|
||||
origin: point3(0.0, 1.0, 0.5),
|
||||
dir: vec3(0.0, 1.0, 0.0),
|
||||
});
|
||||
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),
|
||||
});
|
||||
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.5f32.sqrt(), 0.0, -0.5f32.sqrt()),
|
||||
});
|
||||
test_cut(
|
||||
&poly,
|
||||
2,
|
||||
Line {
|
||||
origin: point3(0.0, 1.0, 0.5),
|
||||
dir: vec3(0.5f32.sqrt(), 0.0, -0.5f32.sqrt()),
|
||||
},
|
||||
);
|
||||
|
||||
// complex cut (diff=1, non-wrapped)
|
||||
test_cut(&poly, 2, Line {
|
||||
origin: point3(0.5, 1.0, 0.0),
|
||||
dir: vec3(0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
});
|
||||
test_cut(
|
||||
&poly,
|
||||
2,
|
||||
Line {
|
||||
origin: point3(0.5, 1.0, 0.0),
|
||||
dir: vec3(0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
},
|
||||
);
|
||||
|
||||
// complex cut (diff=3)
|
||||
test_cut(&poly, 2, Line {
|
||||
origin: point3(0.5, 1.0, 0.0),
|
||||
dir: vec3(-0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
});
|
||||
test_cut(
|
||||
&poly,
|
||||
2,
|
||||
Line {
|
||||
origin: point3(0.5, 1.0, 0.0),
|
||||
dir: vec3(-0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
},
|
||||
);
|
||||
|
||||
// perfect diagonal
|
||||
test_cut(&poly, 1, Line {
|
||||
origin: point3(0.0, 1.0, 0.0),
|
||||
dir: vec3(0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
});
|
||||
test_cut(
|
||||
&poly,
|
||||
1,
|
||||
Line {
|
||||
origin: point3(0.0, 1.0, 0.0),
|
||||
dir: vec3(0.5f32.sqrt(), 0.0, 0.5f32.sqrt()),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -303,8 +326,11 @@ fn plane_unnormalized() {
|
|||
assert_eq!(plane, Err(NegativeHemisphereError));
|
||||
|
||||
plane = Plane::from_unnormalized(vec3(-3.0, 4.0, 0.0), 2.0);
|
||||
assert_eq!(plane, Ok(Some(Plane {
|
||||
normal: vec3(-3.0/5.0, 4.0/5.0, 0.0),
|
||||
offset: 2.0/5.0,
|
||||
})));
|
||||
assert_eq!(
|
||||
plane,
|
||||
Ok(Some(Plane {
|
||||
normal: vec3(-3.0 / 5.0, 4.0 / 5.0, 0.0),
|
||||
offset: 2.0 / 5.0,
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
|
|
|||
53
third_party/rust/plane-split/tests/split.rs
vendored
53
third_party/rust/plane-split/tests/split.rs
vendored
|
|
@ -1,17 +1,12 @@
|
|||
extern crate binary_space_partition;
|
||||
extern crate euclid;
|
||||
extern crate plane_split;
|
||||
|
||||
use std::f32::consts::FRAC_PI_4;
|
||||
use binary_space_partition::{Plane as Plane_, PlaneCut};
|
||||
use euclid::{Angle, Transform3D, Rect, rect, vec3};
|
||||
use plane_split::{BspSplitter, Polygon, Splitter, make_grid};
|
||||
|
||||
use euclid::{rect, vec3, Angle, Rect, Transform3D};
|
||||
use plane_split::{make_grid, BspSplitter, Polygon, Splitter};
|
||||
use std::f32::consts::FRAC_PI_4;
|
||||
|
||||
fn grid_impl(count: usize, splitter: &mut dyn Splitter<f32, (), usize>) {
|
||||
let polys = make_grid(count);
|
||||
let result = splitter.solve(&polys, vec3(0.0, 0.0, 1.0));
|
||||
assert_eq!(result.len(), count + count*count + count*count*count);
|
||||
assert_eq!(result.len(), count + count * count + count * count * count);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -19,7 +14,6 @@ fn grid_bsp() {
|
|||
grid_impl(2, &mut BspSplitter::new());
|
||||
}
|
||||
|
||||
|
||||
fn sort_rotation(splitter: &mut dyn Splitter<f32, (), usize>) {
|
||||
let transform0: Transform3D<f32, (), ()> =
|
||||
Transform3D::rotation(0.0, 1.0, 0.0, Angle::radians(-FRAC_PI_4));
|
||||
|
|
@ -32,9 +26,12 @@ fn sort_rotation(splitter: &mut dyn Splitter<f32, (), usize>) {
|
|||
let p1 = Polygon::from_transformed_rect(rect, transform0, 0);
|
||||
let p2 = Polygon::from_transformed_rect(rect, transform1, 1);
|
||||
let p3 = Polygon::from_transformed_rect(rect, transform2, 2);
|
||||
assert!(p1.is_some() && p2.is_some() && p3.is_some(), "Cannot construct transformed polygons");
|
||||
assert!(
|
||||
p1.is_some() && p2.is_some() && p3.is_some(),
|
||||
"Cannot construct transformed polygons"
|
||||
);
|
||||
|
||||
let polys = [ p1.unwrap(), p2.unwrap(), p3.unwrap() ];
|
||||
let polys = [p1.unwrap(), p2.unwrap(), p3.unwrap()];
|
||||
let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0));
|
||||
let ids: Vec<_> = result.iter().map(|poly| poly.anchor).collect();
|
||||
assert_eq!(&ids, &[2, 1, 0, 1, 2]);
|
||||
|
|
@ -45,16 +42,19 @@ fn rotation_bsp() {
|
|||
sort_rotation(&mut BspSplitter::new());
|
||||
}
|
||||
|
||||
|
||||
fn sort_trivial(splitter: &mut dyn Splitter<f32, (), usize>) {
|
||||
let anchors: Vec<_> = (0usize .. 10).collect();
|
||||
let anchors: Vec<_> = (0usize..10).collect();
|
||||
let rect: Rect<f32, ()> = rect(-10.0, -10.0, 20.0, 20.0);
|
||||
let polys: Vec<_> = anchors.iter().map(|&anchor| {
|
||||
let transform: Transform3D<f32, (), ()> = Transform3D::translation(0.0, 0.0, anchor as f32);
|
||||
let poly = Polygon::from_transformed_rect(rect, transform, anchor);
|
||||
assert!(poly.is_some(), "Cannot construct transformed polygons");
|
||||
poly.unwrap()
|
||||
}).collect();
|
||||
let polys: Vec<_> = anchors
|
||||
.iter()
|
||||
.map(|&anchor| {
|
||||
let transform: Transform3D<f32, (), ()> =
|
||||
Transform3D::translation(0.0, 0.0, anchor as f32);
|
||||
let poly = Polygon::from_transformed_rect(rect, transform, anchor);
|
||||
assert!(poly.is_some(), "Cannot construct transformed polygons");
|
||||
poly.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0));
|
||||
let anchors1: Vec<_> = result.iter().map(|p| p.anchor).collect();
|
||||
|
|
@ -68,7 +68,8 @@ fn sort_external(splitter: &mut dyn Splitter<f32, (), usize>) {
|
|||
let rect0: Rect<f32, ()> = rect(-10.0, -10.0, 20.0, 20.0);
|
||||
let poly0 = Polygon::from_rect(rect0, 0);
|
||||
let poly1 = {
|
||||
let transform0: Transform3D<f32, (), ()> = Transform3D::rotation(1.0, 0.0, 0.0, Angle::radians(2.0 * FRAC_PI_4));
|
||||
let transform0: Transform3D<f32, (), ()> =
|
||||
Transform3D::rotation(1.0, 0.0, 0.0, Angle::radians(2.0 * FRAC_PI_4));
|
||||
let transform1: Transform3D<f32, (), ()> = Transform3D::translation(0.0, 100.0, 0.0);
|
||||
Polygon::from_transformed_rect(rect0, transform0.then(&transform1), 1).unwrap()
|
||||
};
|
||||
|
|
@ -119,13 +120,19 @@ fn test_cut() {
|
|||
// test grouping front
|
||||
poly2.plane.offset += 0.1;
|
||||
match poly.cut(poly2.clone()) {
|
||||
PlaneCut::Cut { ref front, ref back } => assert_eq!((front.len(), back.len()), (1, 0)),
|
||||
PlaneCut::Cut {
|
||||
ref front,
|
||||
ref back,
|
||||
} => assert_eq!((front.len(), back.len()), (1, 0)),
|
||||
PlaneCut::Sibling(_) => panic!("wrong sibling!"),
|
||||
}
|
||||
// test grouping back
|
||||
poly2.plane.normal *= -1.0;
|
||||
match poly.cut(poly2.clone()) {
|
||||
PlaneCut::Cut { ref front, ref back } => assert_eq!((front.len(), back.len()), (0, 1)),
|
||||
PlaneCut::Cut {
|
||||
ref front,
|
||||
ref back,
|
||||
} => assert_eq!((front.len(), back.len()), (0, 1)),
|
||||
PlaneCut::Sibling(_) => panic!("wrong sibling!"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue