Skip to content

Commit

Permalink
Bug 1525087 - Plane split dependency update to 0.13.5 r=kats
Browse files Browse the repository at this point in the history
Update to have servo/plane-split#27 included

Differential Revision: https://phabricator.services.mozilla.com/D18593
  • Loading branch information
kvark committed Feb 5, 2019
1 parent 7e940ea commit 8f844b4
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 85 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions gfx/wr/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion third_party/rust/plane-split/.cargo-checksum.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"files":{"Cargo.toml":"b91e34b32c5ace1a51d7d4fd1cc1c18982e85017caaf943aadbf50b1d9230286","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"451d2fffdb558e85c595cfeb0ab721a99a20386551620b46261c80b7d262b7b1","src/clip.rs":"a635bda3de37a133d78183953e0eec6571ef97782582bd6abf339c8b4ff19ae4","src/lib.rs":"89dfb8415217863a303c40346395ad327fcc044f8c6cb5236a3359a44a15281c","src/polygon.rs":"31ba899f7e10082644b95fff7527b43b2786720d16fc2d4c225bc7b63ada75ee","tests/clip.rs":"3335364fd6849697d3919084be5dce6c49acb31d8c53adc93a4cd05ee2ea93a9","tests/main.rs":"86dd9b91db2a5c28451164b14ca5179f2c08598562d04ee52f578a17640b134f","tests/split.rs":"87b539bf4bb699d428108f583ebd420fcd2d40ae0266a0b358a5f8b8d88003b9"},"package":"69f5ea52d7bf50ff02342f5af8527c81030bac5545e92eeeb4a2dfd7bfd2ef69"}
{"files":{"Cargo.toml":"b9eb30cfd45bebc30ac709d34e029f2a1efee60f3c88cb4fc59354cd63ef7420","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"2ccdca9bfc7d9a52621fcf91c441e924eb2068291b48daa8235ec000932a7790","src/clip.rs":"b58bb753b85b822eee2a0a88ea4eb5dff6a69276168ca61202486a6fb95eb95e","src/lib.rs":"57a6c885819b18ead087968937017b6330378bdcc10f285052c9d76e7a1b2226","src/polygon.rs":"133922c90751a8c08e4b5b0529ab3000b65e4a25d4e18cfe119b5e3104411269","tests/clip.rs":"3335364fd6849697d3919084be5dce6c49acb31d8c53adc93a4cd05ee2ea93a9","tests/main.rs":"7c50a23d32eb8b0742bd533e98ba95c96110c4773b27ae0c40121c347feb9325","tests/split.rs":"88fe8192f8e0d03ac2b4b526c377ceeccbee4e3c35f4fa00be160d1402af09a2"},"package":"b84b8cf2daa6a829b3e756fb75e0eab8e0d963754de9bfc83a4373a47121323a"}
2 changes: 1 addition & 1 deletion third_party/rust/plane-split/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

[package]
name = "plane-split"
version = "0.13.4"
version = "0.13.6"
authors = ["Dzmitry Malyshau <kvark@mozilla.com>"]
description = "Plane splitting"
documentation = "https://docs.rs/plane-split"
Expand Down
13 changes: 6 additions & 7 deletions third_party/rust/plane-split/src/bsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@ impl<T, U> BspPlane for Polygon<T, U> where

//Note: we treat `self` as a plane, and `poly` as a concrete polygon here
let (intersection, dist) = match self.plane.intersect(&poly.plane) {
None if self.plane.normal.dot(poly.plane.normal) > T::zero() => {
debug!("\t\tNormals roughly point to the same direction");
(Intersection::Coplanar, self.plane.offset - poly.plane.offset)
}
None => {
debug!("\t\tNormals roughly point to opposite directions");
(Intersection::Coplanar, self.plane.offset + poly.plane.offset)
let ndot = self.plane.normal.dot(poly.plane.normal);
debug!("\t\tNormals are aligned with {:?}", ndot);
let dist = self.plane.offset - ndot * poly.plane.offset;
(Intersection::Coplanar, dist)
}
Some(_) if self.plane.are_outside(&poly.points) => {
//Note: we can't start with `are_outside` because it's subject to FP precision
let dist = self.plane.signed_distance_sum_to(&poly);
(Intersection::Outside, dist)
}
Expand Down Expand Up @@ -64,7 +63,7 @@ impl<T, U> BspPlane for Polygon<T, U> where
}
Intersection::Inside(line) => {
debug!("\t\tCut across {:?}", line);
let (res_add1, res_add2) = poly.split(&line);
let (res_add1, res_add2) = poly.split_with_normal(&line, &self.plane.normal);
let mut front = Vec::new();
let mut back = Vec::new();

Expand Down
2 changes: 1 addition & 1 deletion third_party/rust/plane-split/src/clip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl<

for mut poly in self.temp.drain(..) {
if let Intersection::Inside(line) = poly.intersect_plane(clip) {
let (res1, res2) = poly.split(&line);
let (res1, res2) = poly.split_with_normal(&line, &clip.normal);
self.results.extend(
res1
.into_iter()
Expand Down
24 changes: 24 additions & 0 deletions third_party/rust/plane-split/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@ impl<T, U> Line<T, U> where
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<TypedPoint3D<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;
// edge.start + edge_vec * t = r + k * d
// (edge.start, d) + t * (edge_vec, d) - (r, d) = k
// edge.start + t * edge_vec = r + t * (edge_vec, d) * d + (start-r, d) * d
// t * (edge_vec - (edge_vec, d)*d) = origin_vec - (origin_vec, d) * d
let pr = origin_vec - self.dir * self.dir.dot(origin_vec);
let pb = edge_vec - self.dir * self.dir.dot(edge_vec);
let denom = pb.dot(pb);
if denom.approx_eq(&T::zero()) {
None
} else {
Some(pr.dot(pb) / denom)
}
}
}


Expand Down
220 changes: 153 additions & 67 deletions third_party/rust/plane-split/src/polygon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use euclid::approxeq::ApproxEq;
use euclid::Trig;
use num_traits::{Float, One, Zero};

use std::{fmt, mem, ops};
use std::{fmt, iter, mem, ops};


/// The projection of a `Polygon` on a line.
Expand Down Expand Up @@ -361,8 +361,104 @@ impl<T, U> Polygon<T, U> where
}
}

/// Split the polygon along the specified `Line`. Will do nothing if the line
/// doesn't belong to the polygon plane.
fn split_impl(
&mut self,
first: (usize, TypedPoint3D<T, U>),
second: (usize, TypedPoint3D<T, U>),
) -> (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);
let base = first.0;
assert!(base < self.points.len());
match second.0 - first.0 {
1 => {
// rect between the cut at the diagonal
let other1 = Polygon {
points: [
first.1,
second.1,
self.points[(base + 2) & 3],
self.points[base],
],
.. self.clone()
};
// triangle on the near side of the diagonal
let other2 = Polygon {
points: [
self.points[(base + 2) & 3],
self.points[(base + 3) & 3],
self.points[base],
self.points[base],
],
.. self.clone()
};
// triangle being cut out
self.points = [
first.1,
self.points[(base + 1) & 3],
second.1,
second.1,
];
(Some(other1), Some(other2))
}
2 => {
// rect on the far side
let other = Polygon {
points: [
first.1,
self.points[(base + 1) & 3],
self.points[(base + 2) & 3],
second.1,
],
.. self.clone()
};
// rect on the near side
self.points = [
first.1,
second.1,
self.points[(base + 3) & 3],
self.points[base],
];
(Some(other), None)
}
3 => {
// rect between the cut at the diagonal
let other1 = Polygon {
points: [
first.1,
self.points[(base + 1) & 3],
self.points[(base + 3) & 3],
second.1,
],
.. self.clone()
};
// triangle on the far side of the diagonal
let other2 = Polygon {
points: [
self.points[(base + 1) & 3],
self.points[(base + 2) & 3],
self.points[(base + 3) & 3],
self.points[(base + 3) & 3],
],
.. self.clone()
};
// triangle being cut out
self.points = [
first.1,
second.1,
self.points[base],
self.points[base],
];
(Some(other1), Some(other2))
}
_ => panic!("Unexpected indices {} {}", first.0, second.0),
}
}

/// Split the polygon along the specified `Line`.
/// 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");
// check if the cut is within the polygon plane first
Expand All @@ -381,17 +477,8 @@ impl<T, U> Polygon<T, U> where
.zip(self.points.iter())
.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 + 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);
let pb = b - a - line.dir * line.dir.dot(b - a);
let denom = pb.dot(pb);
if !denom.approx_eq(&T::zero()) {
let t = pr.dot(pb) / denom;
if t > T::approx_epsilon() && t < T::one() - T::approx_epsilon() {
if let Some(t) = line.intersect_edge(a .. b) {
if t >= T::zero() && t < T::one() {
*cut = Some(a + (b - a) * t);
}
}
Expand All @@ -405,61 +492,60 @@ impl<T, U> Polygon<T, U> where
Some(pos) => first + 1 + pos,
None => return (None, None),
};
debug!("\t\tReached complex case [{}, {}]", first, second);
//TODO: can be optimized for when the polygon has a redundant 4th vertex
//TODO: can be simplified greatly if only working with triangles
let (a, b) = (cuts[first].unwrap(), cuts[second].unwrap());
match second-first {
2 => {
let mut other_points = self.points;
other_points[first] = a;
other_points[(first+3) % 4] = b;
self.points[first+1] = a;
self.points[first+2] = b;
let poly = Polygon {
points: other_points,
.. self.clone()
};
(Some(poly), None)
}
3 => {
let xpoints = [
self.points[first+1],
self.points[first+2],
self.points[first+3],
b];
let ypoints = [a, self.points[first+1], b, b];
self.points = [self.points[first], a, b, b];
let poly1 = Polygon {
points: xpoints,
.. self.clone()
};
let poly2 = Polygon {
points: ypoints,
.. self.clone()
};
(Some(poly1), Some(poly2))
self.split_impl(
(first, cuts[first].unwrap()),
(second, cuts[second].unwrap()),
)
}

/// Split the polygon along the specified `Line`, with a normal to the split line provided.
/// This is useful when called by the plane splitter, since the other plane's normal
/// 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: &TypedVector3D<T, U>,
) -> (Option<Self>, Option<Self>) {
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);
for (side, point) in sides.iter_mut().zip(&self.points) {
*side = normal.dot(*point - line.origin);
}
// compute the edge intersection points
for (i, ((&side1, point1), (&side0, point0))) in sides[1..]
.iter()
.chain(iter::once(&sides[0]))
.zip(self.points[1..].iter().chain(iter::once(&self.points[0])))
.zip(sides.iter().zip(&self.points))
.enumerate()
{
// figure out if an edge between 0 and 1 needs to be cut
let cut = if side0 < T::zero() && side1 >= T::zero() {
&mut cut_positive
} else if side0 > T::zero() && side1 <= T::zero() {
&mut cut_negative
} else {
continue;
};
// compute the cut point
if let Some(t) = line.intersect_edge(*point0 .. *point1) {
//Note: it is expected that T is in [0, 1] range, but it can go outside of it
// by an epsilon due to computation inefficiencies, and it's fine.
debug_assert!(t >= -T::epsilon() && t <= T::one() + T::epsilon());
debug_assert_eq!(*cut, None);
let point = *point0 + (*point1 - *point0) * t;
*cut = Some((i, point));
}
1 => {
let xpoints = [
b,
self.points[(first+2) % 4],
self.points[(first+3) % 4],
self.points[first]
];
let ypoints = [self.points[first], a, b, b];
self.points = [a, self.points[first+1], b, b];
let poly1 = Polygon {
points: xpoints,
.. self.clone()
};
let poly2 = Polygon {
points: ypoints,
.. self.clone()
};
(Some(poly1), Some(poly2))
}
// form new polygons
if let (Some(first), Some(mut second)) = (cut_positive, cut_negative) {
if second.0 < first.0 {
second.0 += 4;
}
_ => panic!("Unexpected indices {} {}", first, second),
self.split_impl(first, second)
} else {
(None, None)
}
}
}
Loading

0 comments on commit 8f844b4

Please sign in to comment.