diff --git a/Cargo.lock b/Cargo.lock index baa77226887b..36463655a618 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1581,7 +1581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "plane-split" -version = "0.12.0" +version = "0.12.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)", @@ -2387,7 +2387,7 @@ dependencies = [ "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "plane-split 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "plane-split 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.66 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2704,7 +2704,7 @@ dependencies = [ "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum plane-split 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f0a0766225cf828672e97948dfa035bb2eae75110757359ae12fbb46509c8b66" +"checksum plane-split 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ff3a4fc9e31d70eb6828e9a2d7a401a824d9f281686a39a8fc06f08796edb1bb" "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum proc-macro2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "77997c53ae6edd6d187fec07ec41b207063b5ee6f33680e9fa86d405cdd313d4" diff --git a/third_party/rust/plane-split/.cargo-checksum.json b/third_party/rust/plane-split/.cargo-checksum.json index 16620b1b572a..6750a3196da8 100644 --- a/third_party/rust/plane-split/.cargo-checksum.json +++ b/third_party/rust/plane-split/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".travis.yml":"b76d49f66f842c652d40825c67791352364a6b6bbb7d8d1009f2ac79eb413e66","Cargo.toml":"19f5083a16929492a2e2123262e9dec955d67cc0ae49365857937846e2047bb6","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"1dedfc48b79d767e28126cefd24af8ecf7eadd937bb5c7dc6b64e30b9c7d48c7","src/clip.rs":"aa4643264580fa55bc6a5cc02a8f9c0354a590e98545a132daf380603e4f0897","src/lib.rs":"3e9fb055066623b08be1abc06d0fd30f838d840ad13a6acab76d117f0c8bf5ff","src/polygon.rs":"3a37af114c44f531ad1565937ee473d4b21d286bbec11cfb351d8fcee6c5f4ce","tests/clip.rs":"0745faa4cb679c5eef4103a26a8714d6feb37ffd00b6c3dafad5937ec5392f10","tests/main.rs":"f782509823dfdba84de83dd36ba5ad5a468d8657950e74db697ee2e8886158a5","tests/split.rs":"0eb1afb1f26cdecd5fffbf32d57e889f8f69254c0a57eecb8ccbbdf38efcdf27"},"package":"f0a0766225cf828672e97948dfa035bb2eae75110757359ae12fbb46509c8b66"} \ No newline at end of file +{"files":{".travis.yml":"b76d49f66f842c652d40825c67791352364a6b6bbb7d8d1009f2ac79eb413e66","Cargo.toml":"9bffe8481e8672f72a85e3844627b35874b2f357ea7e7d91856268ce03f898a7","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"60a306ecb7032a57bc5a7b7f094cb9669f7cd112894f85e6e2fc501a608a9404","src/clip.rs":"d1171933bea98c68440869d341d6f2ecdd672b2acb0a4408a011b7ef1c44b266","src/lib.rs":"3e9fb055066623b08be1abc06d0fd30f838d840ad13a6acab76d117f0c8bf5ff","src/polygon.rs":"c30e17aa88714b490f1cc9b7a9a388b37bc9af919ce1983e42f8b94555847118","tests/clip.rs":"0745faa4cb679c5eef4103a26a8714d6feb37ffd00b6c3dafad5937ec5392f10","tests/main.rs":"e299b33390fc486b45685eaef3af4fc67793b114dc0e63c873022dc1530ab672","tests/split.rs":"0eb1afb1f26cdecd5fffbf32d57e889f8f69254c0a57eecb8ccbbdf38efcdf27"},"package":"ff3a4fc9e31d70eb6828e9a2d7a401a824d9f281686a39a8fc06f08796edb1bb"} \ No newline at end of file diff --git a/third_party/rust/plane-split/Cargo.toml b/third_party/rust/plane-split/Cargo.toml index ec659b3212ab..084c0529ab99 100644 --- a/third_party/rust/plane-split/Cargo.toml +++ b/third_party/rust/plane-split/Cargo.toml @@ -12,7 +12,7 @@ [package] name = "plane-split" -version = "0.12.0" +version = "0.12.1" authors = ["Dzmitry Malyshau "] description = "Plane splitting" documentation = "https://docs.rs/plane-split" diff --git a/third_party/rust/plane-split/src/bsp.rs b/third_party/rust/plane-split/src/bsp.rs index 6f7cb5abe8fc..49c915e02dd6 100644 --- a/third_party/rust/plane-split/src/bsp.rs +++ b/third_party/rust/plane-split/src/bsp.rs @@ -5,7 +5,7 @@ use euclid::{TypedPoint3D, TypedVector3D}; use euclid::approxeq::ApproxEq; use num_traits::{Float, One, Zero}; -use std::{fmt, ops}; +use std::{fmt, iter, ops}; impl BspPlane for Polygon where @@ -43,7 +43,11 @@ impl BspPlane for Polygon where let mut front = Vec::new(); let mut back = Vec::new(); - for sub in Some(plane).into_iter().chain(res_add1).chain(res_add2) { + for sub in iter::once(plane) + .chain(res_add1) + .chain(res_add2) + .filter(|p| !p.is_empty()) + { if self.plane.signed_distance_sum_to(&sub) > T::zero() { front.push(sub) } else { @@ -54,8 +58,8 @@ impl BspPlane for Polygon where line, front.len(), back.len()); PlaneCut::Cut { - front: front, - back: back, + front, + back, } }, } diff --git a/third_party/rust/plane-split/src/clip.rs b/third_party/rust/plane-split/src/clip.rs index 199a39c0b6ad..10546b9c322c 100644 --- a/third_party/rust/plane-split/src/clip.rs +++ b/third_party/rust/plane-split/src/clip.rs @@ -131,6 +131,6 @@ impl< } self.results .drain(..) - .map(move |poly| poly.transform(transform).unwrap()) + .flat_map(move |poly| poly.transform(transform)) } } diff --git a/third_party/rust/plane-split/src/polygon.rs b/third_party/rust/plane-split/src/polygon.rs index f5945948de4b..f4f0147df914 100644 --- a/third_party/rust/plane-split/src/polygon.rs +++ b/third_party/rust/plane-split/src/polygon.rs @@ -119,18 +119,33 @@ impl Polygon where U: fmt::Debug, { /// Construct a polygon from points that are already transformed. + #[deprecated(since = "0.12.1", note = "Use try_from_points instead")] pub fn from_points( points: [TypedPoint3D; 4], anchor: usize, ) -> Self { + Self::try_from_points(points, anchor).unwrap() + } + + /// Construct a polygon from points that are already transformed. + /// Return None if the polygon doesn't contain any space. + /// This method will be removed in `from_points` in the next breaking release. + pub fn try_from_points( + points: [TypedPoint3D; 4], + anchor: usize, + ) -> Option { 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 + } // one of them can be zero for redundant polygons produced by plane splitting //Note: this would be nicer if we used triangles instead of quads in the first place... // see https://github.com/servo/plane-split/issues/17 - debug_assert!(edge2.square_length() > T::approx_epsilon()); let normal_rough1 = edge1.cross(edge2); let normal_rough2 = edge2.cross(edge3); let square_length1 = normal_rough1.square_length(); @@ -144,14 +159,14 @@ impl Polygon where let offset = -points[0].to_vector() .dot(normal); - Polygon { + Some(Polygon { points, plane: Plane { normal, offset, }, anchor, - } + }) } /// Construct a polygon from a non-transformed rectangle. @@ -186,7 +201,7 @@ impl Polygon where //Note: this code path could be more efficient if we had inverse-transpose //let n4 = transform.transform_point4d(&TypedPoint4D::new(T::zero(), T::zero(), T::one(), T::zero())); //let normal = TypedPoint3D::new(n4.x, n4.y, n4.z); - Some(Self::from_points(points, anchor)) + Self::try_from_points(points, anchor) } /// Bring a point into the local coordinate space, returning @@ -228,7 +243,7 @@ impl Polygon where //Note: this code path could be more efficient if we had inverse-transpose //let n4 = transform.transform_point4d(&TypedPoint4D::new(T::zero(), T::zero(), T::one(), T::zero())); //let normal = TypedPoint3D::new(n4.x, n4.y, n4.z); - Some(Polygon::from_points(points, self.anchor)) + Polygon::try_from_points(points, self.anchor) } /// Check if all the points are indeed placed on the plane defined by @@ -251,13 +266,19 @@ impl Polygon where is_planar && is_winding } + /// 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() + } + /// Check if this polygon contains another one. pub fn contains(&self, other: &Self) -> bool { //TODO: actually check for inside/outside self.plane.contains(&other.plane) } - /// Project this polygon onto a 3D vector, returning a line projection. /// Note: we can think of it as a projection to a ray placed at the origin. pub fn project_on(&self, vector: &TypedVector3D) -> LineProjection { @@ -332,8 +353,8 @@ impl Polygon where .zip(cuts.iter_mut()) { // intersecting line segment [a, b] with `line` - //a + (b-a) * t = r + k * d - //(a, d) + t * (b-a, d) - (r, d) = k + // a + (b-a) * t = r + k * d + // (a, d) + t * (b-a, d) - (r, d) = k // a + t * (b-a) = r + t * (b-a, d) * d + (a-r, d) * d // t * ((b-a) - (b-a, d)*d) = (r-a) - (r-a, d) * d let pr = line.origin - a - line.dir * line.dir.dot(line.origin - a); diff --git a/third_party/rust/plane-split/tests/main.rs b/third_party/rust/plane-split/tests/main.rs index 603186be5435..82c01d205502 100644 --- a/third_party/rust/plane-split/tests/main.rs +++ b/third_party/rust/plane-split/tests/main.rs @@ -58,6 +58,20 @@ fn valid() { assert!(poly_c.is_valid()); } +#[test] +fn empty() { + let poly = Polygon::::try_from_points( + [ + point3(0.0, 0.0, 1.0), + point3(0.0, 0.0, 1.0), + point3(0.0, 0.00001, 1.0), + point3(1.0, 0.0, 0.0), + ], + 1, + ); + assert_eq!(None, poly); +} + #[test] fn from_transformed_rect() { let rect: TypedRect = TypedRect::new(point2(10.0, 10.0), TypedSize2D::new(20.0, 30.0));