Run `rustfmt` on the geometry crate
This commit is contained in:
parent
db8eb1c97c
commit
0da11ffe01
|
@ -97,8 +97,10 @@ impl LineSegmentF32 {
|
|||
let (from_from, to_to) = (self.0.xyxy(), self.0.zwzw());
|
||||
let d_d = to_to - from_from;
|
||||
let mid_mid = from_from + d_d * F32x4::splat(t);
|
||||
(LineSegmentF32(from_from.concat_xy_xy(mid_mid)),
|
||||
LineSegmentF32(mid_mid.concat_xy_xy(to_to)))
|
||||
(
|
||||
LineSegmentF32(from_from.concat_xy_xy(mid_mid)),
|
||||
LineSegmentF32(mid_mid.concat_xy_xy(to_to)),
|
||||
)
|
||||
}
|
||||
|
||||
// Returns the left segment first, followed by the right segment.
|
||||
|
@ -248,7 +250,12 @@ impl LineSegmentF32 {
|
|||
if self.is_zero_length() {
|
||||
*self
|
||||
} else {
|
||||
*self + self.vector().yx().normalize().scale_xy(Point2DF32::new(-distance, distance))
|
||||
*self
|
||||
+ self
|
||||
.vector()
|
||||
.yx()
|
||||
.normalize()
|
||||
.scale_xy(Point2DF32::new(-distance, distance))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,13 +55,19 @@ impl RectF32 {
|
|||
#[inline]
|
||||
pub fn contains_point(&self, point: Point2DF32) -> bool {
|
||||
// self.origin <= point && point <= self.lower_right
|
||||
self.0.concat_xy_xy(point.0).packed_le(point.0.concat_xy_zw(self.0)).is_all_ones()
|
||||
self.0
|
||||
.concat_xy_xy(point.0)
|
||||
.packed_le(point.0.concat_xy_zw(self.0))
|
||||
.is_all_ones()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_rect(&self, other: RectF32) -> bool {
|
||||
// self.origin <= other.origin && other.lower_right <= self.lower_right
|
||||
self.0.concat_xy_zw(other.0).packed_le(other.0.concat_xy_zw(self.0)).is_all_ones()
|
||||
self.0
|
||||
.concat_xy_zw(other.0)
|
||||
.packed_le(other.0.concat_xy_zw(self.0))
|
||||
.is_all_ones()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -76,14 +82,19 @@ impl RectF32 {
|
|||
|
||||
#[inline]
|
||||
pub fn union_rect(&self, other: RectF32) -> RectF32 {
|
||||
RectF32::from_points(self.origin().min(other.origin()),
|
||||
self.lower_right().max(other.lower_right()))
|
||||
RectF32::from_points(
|
||||
self.origin().min(other.origin()),
|
||||
self.lower_right().max(other.lower_right()),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: RectF32) -> bool {
|
||||
// self.origin < other.lower_right && other.origin < self.lower_right
|
||||
self.0.concat_xy_xy(other.0).packed_lt(other.0.concat_zw_zw(self.0)).is_all_ones()
|
||||
self.0
|
||||
.concat_xy_xy(other.0)
|
||||
.packed_lt(other.0.concat_zw_zw(self.0))
|
||||
.is_all_ones()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -91,8 +102,10 @@ impl RectF32 {
|
|||
if !self.intersects(other) {
|
||||
None
|
||||
} else {
|
||||
Some(RectF32::from_points(self.origin().max(other.origin()),
|
||||
self.lower_right().min(other.lower_right())))
|
||||
Some(RectF32::from_points(
|
||||
self.origin().max(other.origin()),
|
||||
self.lower_right().min(other.lower_right()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +213,10 @@ impl RectI32 {
|
|||
pub fn contains_point(&self, point: Point2DI32) -> bool {
|
||||
// self.origin <= point && point <= self.lower_right - 1
|
||||
let lower_right = self.lower_right() - Point2DI32::splat(1);
|
||||
self.0.concat_xy_xy(point.0).packed_le(point.0.concat_xy_xy(lower_right.0)).is_all_ones()
|
||||
self.0
|
||||
.concat_xy_xy(point.0)
|
||||
.packed_le(point.0.concat_xy_xy(lower_right.0))
|
||||
.is_all_ones()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -82,13 +82,21 @@ impl Matrix2x2F32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m11(&self) -> f32 { self.0[0] }
|
||||
pub fn m11(&self) -> f32 {
|
||||
self.0[0]
|
||||
}
|
||||
#[inline]
|
||||
pub fn m21(&self) -> f32 { self.0[1] }
|
||||
pub fn m21(&self) -> f32 {
|
||||
self.0[1]
|
||||
}
|
||||
#[inline]
|
||||
pub fn m12(&self) -> f32 { self.0[2] }
|
||||
pub fn m12(&self) -> f32 {
|
||||
self.0[2]
|
||||
}
|
||||
#[inline]
|
||||
pub fn m22(&self) -> f32 { self.0[3] }
|
||||
pub fn m22(&self) -> f32 {
|
||||
self.0[3]
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<Matrix2x2F32> for Matrix2x2F32 {
|
||||
|
@ -140,16 +148,20 @@ impl Transform2DF32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_scale_rotation_translation(scale: Point2DF32, theta: f32, translation: Point2DF32)
|
||||
-> Transform2DF32 {
|
||||
pub fn from_scale_rotation_translation(
|
||||
scale: Point2DF32,
|
||||
theta: f32,
|
||||
translation: Point2DF32,
|
||||
) -> Transform2DF32 {
|
||||
let rotation = Transform2DF32::from_rotation(theta);
|
||||
let translation = Transform2DF32::from_translation(&translation);
|
||||
Transform2DF32::from_scale(&scale).post_mul(&rotation).post_mul(&translation)
|
||||
Transform2DF32::from_scale(&scale)
|
||||
.post_mul(&rotation)
|
||||
.post_mul(&translation)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn row_major(m11: f32, m12: f32, m21: f32, m22: f32, m31: f32, m32: f32)
|
||||
-> Transform2DF32 {
|
||||
pub fn row_major(m11: f32, m12: f32, m21: f32, m22: f32, m31: f32, m32: f32) -> Transform2DF32 {
|
||||
Transform2DF32 {
|
||||
matrix: Matrix2x2F32::row_major(m11, m12, m21, m22),
|
||||
vector: Point2DF32::new(m31, m32),
|
||||
|
@ -187,10 +199,24 @@ impl Transform2DF32 {
|
|||
// TODO(pcwalton): Optimize better with SIMD.
|
||||
#[inline]
|
||||
pub fn to_3d(&self) -> Transform3DF32 {
|
||||
Transform3DF32::row_major(self.matrix.0[0], self.matrix.0[1], 0.0, self.vector.x(),
|
||||
self.matrix.0[2], self.matrix.0[3], 0.0, self.vector.y(),
|
||||
0.0, 0.0, 0.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
self.matrix.0[0],
|
||||
self.matrix.0[1],
|
||||
0.0,
|
||||
self.vector.x(),
|
||||
self.matrix.0[2],
|
||||
self.matrix.0[3],
|
||||
0.0,
|
||||
self.vector.y(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -199,13 +225,21 @@ impl Transform2DF32 {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn m11(&self) -> f32 { self.matrix.m11() }
|
||||
pub fn m11(&self) -> f32 {
|
||||
self.matrix.m11()
|
||||
}
|
||||
#[inline]
|
||||
pub fn m21(&self) -> f32 { self.matrix.m21() }
|
||||
pub fn m21(&self) -> f32 {
|
||||
self.matrix.m21()
|
||||
}
|
||||
#[inline]
|
||||
pub fn m12(&self) -> f32 { self.matrix.m12() }
|
||||
pub fn m12(&self) -> f32 {
|
||||
self.matrix.m12()
|
||||
}
|
||||
#[inline]
|
||||
pub fn m22(&self) -> f32 { self.matrix.m22() }
|
||||
pub fn m22(&self) -> f32 {
|
||||
self.matrix.m22()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn post_translate(&self, vector: Point2DF32) -> Transform2DF32 {
|
||||
|
|
|
@ -43,11 +43,24 @@ impl Default for Transform3DF32 {
|
|||
|
||||
impl Transform3DF32 {
|
||||
#[inline]
|
||||
pub fn row_major(m00: f32, m01: f32, m02: f32, m03: f32,
|
||||
m10: f32, m11: f32, m12: f32, m13: f32,
|
||||
m20: f32, m21: f32, m22: f32, m23: f32,
|
||||
m30: f32, m31: f32, m32: f32, m33: f32)
|
||||
-> Transform3DF32 {
|
||||
pub fn row_major(
|
||||
m00: f32,
|
||||
m01: f32,
|
||||
m02: f32,
|
||||
m03: f32,
|
||||
m10: f32,
|
||||
m11: f32,
|
||||
m12: f32,
|
||||
m13: f32,
|
||||
m20: f32,
|
||||
m21: f32,
|
||||
m22: f32,
|
||||
m23: f32,
|
||||
m30: f32,
|
||||
m31: f32,
|
||||
m32: f32,
|
||||
m33: f32,
|
||||
) -> Transform3DF32 {
|
||||
Transform3DF32 {
|
||||
c0: F32x4::new(m00, m10, m20, m30),
|
||||
c1: F32x4::new(m01, m11, m21, m31),
|
||||
|
@ -58,10 +71,9 @@ impl Transform3DF32 {
|
|||
|
||||
#[inline]
|
||||
pub fn from_scale(x: f32, y: f32, z: f32) -> Transform3DF32 {
|
||||
Transform3DF32::row_major( x, 0.0, 0.0, 0.0,
|
||||
0.0, y, 0.0, 0.0,
|
||||
0.0, 0.0, z, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -71,17 +83,16 @@ impl Transform3DF32 {
|
|||
|
||||
#[inline]
|
||||
pub fn from_translation(x: f32, y: f32, z: f32) -> Transform3DF32 {
|
||||
Transform3DF32::row_major(1.0, 0.0, 0.0, x,
|
||||
0.0, 1.0, 0.0, y,
|
||||
0.0, 0.0, 1.0, z,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, y, 0.0, 0.0, 1.0, z, 0.0, 0.0, 0.0, 1.0,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO(pcwalton): Optimize.
|
||||
pub fn from_rotation(yaw: f32, pitch: f32, roll: f32) -> Transform3DF32 {
|
||||
let (cos_b, sin_b) = (yaw.cos(), yaw.sin());
|
||||
let (cos_b, sin_b) = (yaw.cos(), yaw.sin());
|
||||
let (cos_c, sin_c) = (pitch.cos(), pitch.sin());
|
||||
let (cos_a, sin_a) = (roll.cos(), roll.sin());
|
||||
let (cos_a, sin_a) = (roll.cos(), roll.sin());
|
||||
let m00 = cos_a * cos_b;
|
||||
let m01 = cos_a * sin_b * sin_c - sin_a * cos_c;
|
||||
let m02 = cos_a * sin_b * cos_c + sin_a * sin_c;
|
||||
|
@ -91,10 +102,9 @@ impl Transform3DF32 {
|
|||
let m20 = -sin_b;
|
||||
let m21 = cos_b * sin_c;
|
||||
let m22 = cos_b * cos_c;
|
||||
Transform3DF32::row_major(m00, m01, m02, 0.0,
|
||||
m10, m11, m12, 0.0,
|
||||
m20, m21, m22, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
m00, m01, m02, 0.0, m10, m11, m12, 0.0, m20, m21, m22, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a rotation matrix from the given quaternion.
|
||||
|
@ -104,30 +114,66 @@ impl Transform3DF32 {
|
|||
pub fn from_rotation_quaternion(q: F32x4) -> Transform3DF32 {
|
||||
// TODO(pcwalton): Optimize better with more shuffles.
|
||||
let (mut sq, mut w, mut xy_xz_yz) = (q * q, q.wwww() * q, q.xxyy() * q.yzzy());
|
||||
sq += sq; w += w; xy_xz_yz += xy_xz_yz;
|
||||
sq += sq;
|
||||
w += w;
|
||||
xy_xz_yz += xy_xz_yz;
|
||||
let diag = F32x4::splat(1.0) - (sq.yxxy() + sq.zzyy());
|
||||
let (wx2, wy2, wz2) = (w.x(), w.y(), w.z());
|
||||
let (xy2, xz2, yz2) = (xy_xz_yz.x(), xy_xz_yz.y(), xy_xz_yz.z());
|
||||
Transform3DF32::row_major(diag.x(), xy2 - wz2, xz2 + wy2, 0.0,
|
||||
xy2 + wz2, diag.y(), yz2 - wx2, 0.0,
|
||||
xz2 - wy2, yz2 + wx2, diag.z(), 0.0,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
diag.x(),
|
||||
xy2 - wz2,
|
||||
xz2 + wy2,
|
||||
0.0,
|
||||
xy2 + wz2,
|
||||
diag.y(),
|
||||
yz2 - wx2,
|
||||
0.0,
|
||||
xz2 - wy2,
|
||||
yz2 + wx2,
|
||||
diag.z(),
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
)
|
||||
}
|
||||
|
||||
/// Just like `glOrtho()`.
|
||||
#[inline]
|
||||
pub fn from_ortho(left: f32, right: f32, bottom: f32, top: f32, near_val: f32, far_val: f32)
|
||||
-> Transform3DF32 {
|
||||
pub fn from_ortho(
|
||||
left: f32,
|
||||
right: f32,
|
||||
bottom: f32,
|
||||
top: f32,
|
||||
near_val: f32,
|
||||
far_val: f32,
|
||||
) -> Transform3DF32 {
|
||||
let x_inv = 1.0 / (right - left);
|
||||
let y_inv = 1.0 / (top - bottom);
|
||||
let z_inv = 1.0 / (far_val - near_val);
|
||||
let tx = -(right + left) * x_inv;
|
||||
let ty = -(top + bottom) * y_inv;
|
||||
let tz = -(far_val + near_val) * z_inv;
|
||||
Transform3DF32::row_major(2.0 * x_inv, 0.0, 0.0, tx,
|
||||
0.0, 2.0 * y_inv, 0.0, ty,
|
||||
0.0, 0.0, -2.0 * z_inv, tz,
|
||||
0.0, 0.0, 0.0, 1.0)
|
||||
Transform3DF32::row_major(
|
||||
2.0 * x_inv,
|
||||
0.0,
|
||||
0.0,
|
||||
tx,
|
||||
0.0,
|
||||
2.0 * y_inv,
|
||||
0.0,
|
||||
ty,
|
||||
0.0,
|
||||
0.0,
|
||||
-2.0 * z_inv,
|
||||
tz,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1.0,
|
||||
)
|
||||
}
|
||||
|
||||
/// Just like `gluPerspective()`.
|
||||
|
@ -140,10 +186,9 @@ impl Transform3DF32 {
|
|||
let m22 = (z_far + z_near) * z_denom;
|
||||
let m23 = 2.0 * z_far * z_near * z_denom;
|
||||
let m32 = -1.0;
|
||||
Transform3DF32::row_major(m00, 0.0, 0.0, 0.0,
|
||||
0.0, m11, 0.0, 0.0,
|
||||
0.0, 0.0, m22, m23,
|
||||
0.0, 0.0, m32, 0.0)
|
||||
Transform3DF32::row_major(
|
||||
m00, 0.0, 0.0, 0.0, 0.0, m11, 0.0, 0.0, 0.0, 0.0, m22, m23, 0.0, 0.0, m32, 0.0,
|
||||
)
|
||||
}
|
||||
|
||||
// +- -+
|
||||
|
@ -151,8 +196,12 @@ impl Transform3DF32 {
|
|||
// | C D |
|
||||
// +- -+
|
||||
#[inline]
|
||||
pub fn from_submatrices(a: Matrix2x2F32, b: Matrix2x2F32, c: Matrix2x2F32, d: Matrix2x2F32)
|
||||
-> Transform3DF32 {
|
||||
pub fn from_submatrices(
|
||||
a: Matrix2x2F32,
|
||||
b: Matrix2x2F32,
|
||||
c: Matrix2x2F32,
|
||||
d: Matrix2x2F32,
|
||||
) -> Transform3DF32 {
|
||||
Transform3DF32 {
|
||||
c0: a.0.concat_xy_xy(c.0),
|
||||
c1: a.0.concat_zw_zw(c.0),
|
||||
|
@ -232,17 +281,17 @@ impl Transform3DF32 {
|
|||
|
||||
// Compute new submatrices.
|
||||
let (a_new, b_new) = (a_inv + z.post_mul(&y).post_mul(&x), (-z).post_mul(&y));
|
||||
let (c_new, d_new) = ((-y).post_mul(&x), y);
|
||||
let (c_new, d_new) = ((-y).post_mul(&x), y);
|
||||
|
||||
// Construct inverse.
|
||||
Transform3DF32::from_submatrices(a_new, b_new, c_new, d_new)
|
||||
}
|
||||
|
||||
pub fn approx_eq(&self, other: &Transform3DF32, epsilon: f32) -> bool {
|
||||
self.c0.approx_eq(other.c0, epsilon) &&
|
||||
self.c1.approx_eq(other.c1, epsilon) &&
|
||||
self.c2.approx_eq(other.c2, epsilon) &&
|
||||
self.c3.approx_eq(other.c3, epsilon)
|
||||
self.c0.approx_eq(other.c0, epsilon)
|
||||
&& self.c1.approx_eq(other.c1, epsilon)
|
||||
&& self.c2.approx_eq(other.c2, epsilon)
|
||||
&& self.c3.approx_eq(other.c3, epsilon)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -276,15 +325,20 @@ pub struct Perspective {
|
|||
impl Perspective {
|
||||
#[inline]
|
||||
pub fn new(transform: &Transform3DF32, window_size: Point2DI32) -> Perspective {
|
||||
Perspective { transform: *transform, window_size }
|
||||
Perspective {
|
||||
transform: *transform,
|
||||
window_size,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transform_point_2d(&self, point: &Point2DF32) -> Point2DF32 {
|
||||
let point = self.transform
|
||||
.transform_point(point.to_3d())
|
||||
.perspective_divide()
|
||||
.to_2d() * Point2DF32::new(1.0, -1.0);
|
||||
let point = self
|
||||
.transform
|
||||
.transform_point(point.to_3d())
|
||||
.perspective_divide()
|
||||
.to_2d()
|
||||
* Point2DF32::new(1.0, -1.0);
|
||||
(point + Point2DF32::splat(1.0)) * self.window_size.to_f32().scale(0.5)
|
||||
}
|
||||
|
||||
|
@ -328,13 +382,22 @@ where
|
|||
fn next(&mut self) -> Option<Segment> {
|
||||
let mut segment = self.iter.next()?;
|
||||
if !segment.is_none() {
|
||||
segment.baseline.set_from(&self.perspective
|
||||
.transform_point_2d(&segment.baseline.from()));
|
||||
segment.baseline.set_to(&self.perspective.transform_point_2d(&segment.baseline.to()));
|
||||
segment.baseline.set_from(
|
||||
&self
|
||||
.perspective
|
||||
.transform_point_2d(&segment.baseline.from()),
|
||||
);
|
||||
segment
|
||||
.baseline
|
||||
.set_to(&self.perspective.transform_point_2d(&segment.baseline.to()));
|
||||
if !segment.is_line() {
|
||||
segment.ctrl.set_from(&self.perspective.transform_point_2d(&segment.ctrl.from()));
|
||||
segment
|
||||
.ctrl
|
||||
.set_from(&self.perspective.transform_point_2d(&segment.ctrl.from()));
|
||||
if !segment.is_quadratic() {
|
||||
segment.ctrl.set_to(&self.perspective.transform_point_2d(&segment.ctrl.to()));
|
||||
segment
|
||||
.ctrl
|
||||
.set_to(&self.perspective.transform_point_2d(&segment.ctrl.to()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +411,10 @@ where
|
|||
{
|
||||
#[inline]
|
||||
pub fn new(iter: I, perspective: &Perspective) -> PerspectivePathIter<I> {
|
||||
PerspectivePathIter { iter, perspective: *perspective }
|
||||
PerspectivePathIter {
|
||||
iter,
|
||||
perspective: *perspective,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,44 +425,39 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_post_mul() {
|
||||
let a = Transform3DF32::row_major(3.0, 1.0, 4.0, 5.0,
|
||||
9.0, 2.0, 6.0, 5.0,
|
||||
3.0, 5.0, 8.0, 9.0,
|
||||
7.0, 9.0, 3.0, 2.0);
|
||||
let b = Transform3DF32::row_major(3.0, 8.0, 4.0, 6.0,
|
||||
2.0, 6.0, 4.0, 3.0,
|
||||
3.0, 8.0, 3.0, 2.0,
|
||||
7.0, 9.0, 5.0, 0.0);
|
||||
let c = Transform3DF32::row_major(58.0, 107.0, 53.0, 29.0,
|
||||
84.0, 177.0, 87.0, 72.0,
|
||||
106.0, 199.0, 101.0, 49.0,
|
||||
62.0, 152.0, 83.0, 75.0);
|
||||
let a = Transform3DF32::row_major(
|
||||
3.0, 1.0, 4.0, 5.0, 9.0, 2.0, 6.0, 5.0, 3.0, 5.0, 8.0, 9.0, 7.0, 9.0, 3.0, 2.0,
|
||||
);
|
||||
let b = Transform3DF32::row_major(
|
||||
3.0, 8.0, 4.0, 6.0, 2.0, 6.0, 4.0, 3.0, 3.0, 8.0, 3.0, 2.0, 7.0, 9.0, 5.0, 0.0,
|
||||
);
|
||||
let c = Transform3DF32::row_major(
|
||||
58.0, 107.0, 53.0, 29.0, 84.0, 177.0, 87.0, 72.0, 106.0, 199.0, 101.0, 49.0, 62.0,
|
||||
152.0, 83.0, 75.0,
|
||||
);
|
||||
assert_eq!(a.post_mul(&b), c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pre_mul() {
|
||||
let a = Transform3DF32::row_major(3.0, 1.0, 4.0, 5.0,
|
||||
9.0, 2.0, 6.0, 5.0,
|
||||
3.0, 5.0, 8.0, 9.0,
|
||||
7.0, 9.0, 3.0, 2.0);
|
||||
let b = Transform3DF32::row_major(3.0, 8.0, 4.0, 6.0,
|
||||
2.0, 6.0, 4.0, 3.0,
|
||||
3.0, 8.0, 3.0, 2.0,
|
||||
7.0, 9.0, 5.0, 0.0);
|
||||
let c = Transform3DF32::row_major(135.0, 93.0, 110.0, 103.0,
|
||||
93.0, 61.0, 85.0, 82.0,
|
||||
104.0, 52.0, 90.0, 86.0,
|
||||
117.0, 50.0, 122.0, 125.0);
|
||||
let a = Transform3DF32::row_major(
|
||||
3.0, 1.0, 4.0, 5.0, 9.0, 2.0, 6.0, 5.0, 3.0, 5.0, 8.0, 9.0, 7.0, 9.0, 3.0, 2.0,
|
||||
);
|
||||
let b = Transform3DF32::row_major(
|
||||
3.0, 8.0, 4.0, 6.0, 2.0, 6.0, 4.0, 3.0, 3.0, 8.0, 3.0, 2.0, 7.0, 9.0, 5.0, 0.0,
|
||||
);
|
||||
let c = Transform3DF32::row_major(
|
||||
135.0, 93.0, 110.0, 103.0, 93.0, 61.0, 85.0, 82.0, 104.0, 52.0, 90.0, 86.0, 117.0,
|
||||
50.0, 122.0, 125.0,
|
||||
);
|
||||
assert_eq!(a.pre_mul(&b), c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transform_point() {
|
||||
let a = Transform3DF32::row_major(3.0, 1.0, 4.0, 5.0,
|
||||
9.0, 2.0, 6.0, 5.0,
|
||||
3.0, 5.0, 8.0, 9.0,
|
||||
7.0, 9.0, 3.0, 2.0);
|
||||
let a = Transform3DF32::row_major(
|
||||
3.0, 1.0, 4.0, 5.0, 9.0, 2.0, 6.0, 5.0, 3.0, 5.0, 8.0, 9.0, 7.0, 9.0, 3.0, 2.0,
|
||||
);
|
||||
let p = Point3DF32::new(3.0, 8.0, 4.0, 6.0);
|
||||
let q = Point3DF32::new(63.0, 97.0, 135.0, 117.0);
|
||||
assert_eq!(a.transform_point(p), q);
|
||||
|
@ -405,18 +466,32 @@ mod test {
|
|||
#[test]
|
||||
fn test_inverse() {
|
||||
// Random matrix.
|
||||
let m = Transform3DF32::row_major(0.86277982, 0.15986552, 0.90739898, 0.60066808,
|
||||
0.17386167, 0.016353 , 0.8535783 , 0.12969608,
|
||||
0.0946466 , 0.43248631, 0.63480505, 0.08154603,
|
||||
0.50305436, 0.48359687, 0.51057162, 0.24812012);
|
||||
let m = Transform3DF32::row_major(
|
||||
0.86277982, 0.15986552, 0.90739898, 0.60066808, 0.17386167, 0.016353, 0.8535783,
|
||||
0.12969608, 0.0946466, 0.43248631, 0.63480505, 0.08154603, 0.50305436, 0.48359687,
|
||||
0.51057162, 0.24812012,
|
||||
);
|
||||
let p0 = Point3DF32::new(0.95536648, 0.80633691, 0.16357357, 0.5477598);
|
||||
let p1 = m.transform_point(p0);
|
||||
let m_inv = m.inverse();
|
||||
let m_inv_exp =
|
||||
Transform3DF32::row_major(-2.47290136 , 3.48865688, -6.12298336 , 6.17536696 ,
|
||||
0.00124033357, -1.72561993, 2.16876606 , 0.186227748,
|
||||
-0.375021729 , 1.53883017, -0.0558194403, 0.121857058,
|
||||
5.78300323 , -6.87635769, 8.30196620 , -9.10374060);
|
||||
let m_inv_exp = Transform3DF32::row_major(
|
||||
-2.47290136,
|
||||
3.48865688,
|
||||
-6.12298336,
|
||||
6.17536696,
|
||||
0.00124033357,
|
||||
-1.72561993,
|
||||
2.16876606,
|
||||
0.186227748,
|
||||
-0.375021729,
|
||||
1.53883017,
|
||||
-0.0558194403,
|
||||
0.121857058,
|
||||
5.78300323,
|
||||
-6.87635769,
|
||||
8.30196620,
|
||||
-9.10374060,
|
||||
);
|
||||
assert!(m_inv.approx_eq(&m_inv_exp, 0.0001));
|
||||
let p2 = m_inv.transform_point(p1);
|
||||
assert!(p0.approx_eq(&p2, 0.0001));
|
||||
|
|
|
@ -53,9 +53,9 @@ impl TEdge for AxisAlignedEdge {
|
|||
#[inline]
|
||||
fn point_is_inside(&self, point: &Point2DF32) -> bool {
|
||||
match *self {
|
||||
AxisAlignedEdge::Left(x) => point.x() >= x,
|
||||
AxisAlignedEdge::Top(y) => point.y() >= y,
|
||||
AxisAlignedEdge::Right(x) => point.x() <= x,
|
||||
AxisAlignedEdge::Left(x) => point.x() >= x,
|
||||
AxisAlignedEdge::Top(y) => point.y() >= y,
|
||||
AxisAlignedEdge::Right(x) => point.x() <= x,
|
||||
AxisAlignedEdge::Bottom(y) => point.y() <= y,
|
||||
}
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ impl TEdge for AxisAlignedEdge {
|
|||
fn intersect_line_segment(&self, segment: &LineSegmentF32) -> ArrayVec<[f32; 3]> {
|
||||
let mut results = ArrayVec::new();
|
||||
let t = match *self {
|
||||
AxisAlignedEdge::Left(x) | AxisAlignedEdge::Right(x) => segment.solve_t_for_x(x),
|
||||
AxisAlignedEdge::Top(y) | AxisAlignedEdge::Bottom(y) => segment.solve_t_for_y(y),
|
||||
AxisAlignedEdge::Left(x) | AxisAlignedEdge::Right(x) => segment.solve_t_for_x(x),
|
||||
AxisAlignedEdge::Top(y) | AxisAlignedEdge::Bottom(y) => segment.solve_t_for_y(y),
|
||||
};
|
||||
if t >= 0.0 && t <= 1.0 {
|
||||
results.push(t);
|
||||
|
@ -79,7 +79,12 @@ trait TEdge: Debug {
|
|||
|
||||
fn trivially_test_segment(&self, segment: &Segment) -> EdgeRelativeLocation {
|
||||
let from_inside = self.point_is_inside(&segment.baseline.from());
|
||||
debug!("point {:?} inside {:?}: {:?}", segment.baseline.from(), self, from_inside);
|
||||
debug!(
|
||||
"point {:?} inside {:?}: {:?}",
|
||||
segment.baseline.from(),
|
||||
self,
|
||||
from_inside
|
||||
);
|
||||
if from_inside != self.point_is_inside(&segment.baseline.to()) {
|
||||
return EdgeRelativeLocation::Intersecting;
|
||||
}
|
||||
|
@ -93,7 +98,11 @@ trait TEdge: Debug {
|
|||
}
|
||||
}
|
||||
}
|
||||
if from_inside { EdgeRelativeLocation::Inside } else { EdgeRelativeLocation::Outside }
|
||||
if from_inside {
|
||||
EdgeRelativeLocation::Inside
|
||||
} else {
|
||||
EdgeRelativeLocation::Outside
|
||||
}
|
||||
}
|
||||
|
||||
fn intersect_segment(&self, segment: &Segment) -> ArrayVec<[f32; 3]> {
|
||||
|
@ -110,7 +119,7 @@ trait TEdge: Debug {
|
|||
let mut prev_t = 0.0;
|
||||
while !results.is_full() {
|
||||
if prev_t >= 1.0 {
|
||||
break
|
||||
break;
|
||||
}
|
||||
let next_t = match self.intersect_cubic_segment(&segment, prev_t, 1.0) {
|
||||
None => break,
|
||||
|
@ -124,15 +133,24 @@ trait TEdge: Debug {
|
|||
const EPSILON: f32 = 0.0001;
|
||||
}
|
||||
|
||||
fn intersect_cubic_segment(&self, segment: &Segment, mut t_min: f32, mut t_max: f32)
|
||||
-> Option<f32> {
|
||||
debug!("... intersect_cubic_segment({:?}, {:?}, t=({}, {}))", self, segment, t_min, t_max);
|
||||
fn intersect_cubic_segment(
|
||||
&self,
|
||||
segment: &Segment,
|
||||
mut t_min: f32,
|
||||
mut t_max: f32,
|
||||
) -> Option<f32> {
|
||||
debug!(
|
||||
"... intersect_cubic_segment({:?}, {:?}, t=({}, {}))",
|
||||
self, segment, t_min, t_max
|
||||
);
|
||||
|
||||
let mut segment = segment.as_cubic_segment().split_after(t_min);
|
||||
segment = segment.as_cubic_segment().split_before(t_max / (1.0 - t_min));
|
||||
segment = segment
|
||||
.as_cubic_segment()
|
||||
.split_before(t_max / (1.0 - t_min));
|
||||
|
||||
if !self.intersects_cubic_segment_hull(segment.as_cubic_segment()) {
|
||||
return None
|
||||
return None;
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -156,13 +174,16 @@ trait TEdge: Debug {
|
|||
|
||||
fn intersects_cubic_segment_hull(&self, cubic_segment: CubicSegment) -> bool {
|
||||
let inside = self.point_is_inside(&cubic_segment.0.baseline.from());
|
||||
inside != self.point_is_inside(&cubic_segment.0.ctrl.from()) ||
|
||||
inside != self.point_is_inside(&cubic_segment.0.ctrl.to()) ||
|
||||
inside != self.point_is_inside(&cubic_segment.0.baseline.to())
|
||||
inside != self.point_is_inside(&cubic_segment.0.ctrl.from())
|
||||
|| inside != self.point_is_inside(&cubic_segment.0.ctrl.to())
|
||||
|| inside != self.point_is_inside(&cubic_segment.0.baseline.to())
|
||||
}
|
||||
}
|
||||
|
||||
trait ContourClipper where Self::Edge: TEdge + Debug {
|
||||
trait ContourClipper
|
||||
where
|
||||
Self::Edge: TEdge + Debug,
|
||||
{
|
||||
type Edge;
|
||||
|
||||
fn contour_mut(&mut self) -> &mut Contour;
|
||||
|
@ -209,11 +230,10 @@ trait ContourClipper where Self::Edge: TEdge + Debug {
|
|||
let (before_split, after_split) = segment.split((t - last_t) / (1.0 - last_t));
|
||||
|
||||
// Push the split segment if appropriate.
|
||||
debug!("... ... edge={:?} before_split={:?} t={:?} starts_inside={:?}",
|
||||
edge,
|
||||
before_split,
|
||||
t,
|
||||
starts_inside);
|
||||
debug!(
|
||||
"... ... edge={:?} before_split={:?} t={:?} starts_inside={:?}",
|
||||
edge, before_split, t, starts_inside
|
||||
);
|
||||
if starts_inside {
|
||||
debug!("... split segment case, pushing segment");
|
||||
self.push_segment(&before_split);
|
||||
|
@ -255,8 +275,8 @@ trait ContourClipper where Self::Edge: TEdge + Debug {
|
|||
(None, EdgeRelativeLocation::Inside) => {
|
||||
result = Some(FastClipResult::AllInside);
|
||||
}
|
||||
(Some(FastClipResult::AllInside), EdgeRelativeLocation::Inside) |
|
||||
(Some(FastClipResult::AllOutside), EdgeRelativeLocation::Outside) => {}
|
||||
(Some(FastClipResult::AllInside), EdgeRelativeLocation::Inside)
|
||||
| (Some(FastClipResult::AllOutside), EdgeRelativeLocation::Outside) => {}
|
||||
(_, _) => return FastClipResult::SlowPath,
|
||||
}
|
||||
}
|
||||
|
@ -290,7 +310,10 @@ impl ContourClipper for ContourPolygonClipper {
|
|||
impl ContourPolygonClipper {
|
||||
#[inline]
|
||||
pub(crate) fn new(clip_polygon: &[Point2DF32], contour: Contour) -> ContourPolygonClipper {
|
||||
ContourPolygonClipper { clip_polygon: SmallVec::from_slice(clip_polygon), contour }
|
||||
ContourPolygonClipper {
|
||||
clip_polygon: SmallVec::from_slice(clip_polygon),
|
||||
contour,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clip(mut self) -> Contour {
|
||||
|
@ -341,7 +364,7 @@ impl ContourRectClipper {
|
|||
|
||||
pub(crate) fn clip(mut self) -> Contour {
|
||||
if self.clip_rect.contains_rect(self.contour.bounds()) {
|
||||
return self.contour
|
||||
return self.contour;
|
||||
}
|
||||
|
||||
self.clip_against(AxisAlignedEdge::Left(self.clip_rect.min_x()));
|
||||
|
@ -412,7 +435,7 @@ enum Edge3D {
|
|||
Bottom,
|
||||
Top,
|
||||
Near,
|
||||
Far
|
||||
Far,
|
||||
}
|
||||
|
||||
impl Edge3D {
|
||||
|
@ -420,23 +443,26 @@ impl Edge3D {
|
|||
fn point_is_inside(self, point: Point3DF32) -> bool {
|
||||
let w = point.w();
|
||||
match self {
|
||||
Edge3D::Left => point.x() >= -w, Edge3D::Right => point.x() <= w,
|
||||
Edge3D::Bottom => point.y() >= -w, Edge3D::Top => point.y() <= w,
|
||||
Edge3D::Near => point.z() >= -w, Edge3D::Far => point.z() <= w,
|
||||
Edge3D::Left => point.x() >= -w,
|
||||
Edge3D::Right => point.x() <= w,
|
||||
Edge3D::Bottom => point.y() >= -w,
|
||||
Edge3D::Top => point.y() <= w,
|
||||
Edge3D::Near => point.z() >= -w,
|
||||
Edge3D::Far => point.z() <= w,
|
||||
}
|
||||
}
|
||||
|
||||
// Blinn & Newell, "Clipping using homogeneous coordinates", SIGGRAPH 1978.
|
||||
fn line_intersection(self, prev: Point3DF32, next: Point3DF32) -> Point3DF32 {
|
||||
let (x0, x1) = match self {
|
||||
Edge3D::Left | Edge3D::Right => (prev.x(), next.x()),
|
||||
Edge3D::Bottom | Edge3D::Top => (prev.y(), next.y()),
|
||||
Edge3D::Near | Edge3D::Far => (prev.z(), next.z()),
|
||||
Edge3D::Left | Edge3D::Right => (prev.x(), next.x()),
|
||||
Edge3D::Bottom | Edge3D::Top => (prev.y(), next.y()),
|
||||
Edge3D::Near | Edge3D::Far => (prev.z(), next.z()),
|
||||
};
|
||||
let (w0, w1) = (prev.w(), next.w());
|
||||
let sign = match self {
|
||||
Edge3D::Left | Edge3D::Bottom | Edge3D::Near => -1.0,
|
||||
Edge3D::Right | Edge3D::Top | Edge3D::Far => 1.0,
|
||||
Edge3D::Left | Edge3D::Bottom | Edge3D::Near => -1.0,
|
||||
Edge3D::Right | Edge3D::Top | Edge3D::Far => 1.0,
|
||||
};
|
||||
let alpha = ((x0 - sign * w0) as f64) / ((sign * (w1 - w0) - (x1 - x0)) as f64);
|
||||
prev.lerp(next, alpha as f32)
|
||||
|
@ -449,17 +475,30 @@ impl Edge3D {
|
|||
pub(crate) fn rect_is_outside_polygon(rect: RectF32, polygon_points: &[Point2DF32]) -> bool {
|
||||
let mut outcode = Outcode::all();
|
||||
for point in polygon_points {
|
||||
if point.x() > rect.min_x() { outcode.remove(Outcode::LEFT); }
|
||||
if point.x() < rect.max_x() { outcode.remove(Outcode::RIGHT); }
|
||||
if point.y() > rect.min_y() { outcode.remove(Outcode::TOP); }
|
||||
if point.y() < rect.max_y() { outcode.remove(Outcode::BOTTOM); }
|
||||
if point.x() > rect.min_x() {
|
||||
outcode.remove(Outcode::LEFT);
|
||||
}
|
||||
if point.x() < rect.max_x() {
|
||||
outcode.remove(Outcode::RIGHT);
|
||||
}
|
||||
if point.y() > rect.min_y() {
|
||||
outcode.remove(Outcode::TOP);
|
||||
}
|
||||
if point.y() < rect.max_y() {
|
||||
outcode.remove(Outcode::BOTTOM);
|
||||
}
|
||||
}
|
||||
if !outcode.is_empty() {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME(pcwalton): Check winding!
|
||||
let rect_points = [rect.origin(), rect.upper_right(), rect.lower_left(), rect.lower_right()];
|
||||
let rect_points = [
|
||||
rect.origin(),
|
||||
rect.upper_right(),
|
||||
rect.lower_left(),
|
||||
rect.lower_right(),
|
||||
];
|
||||
for (next_point_index, &next) in polygon_points.iter().enumerate() {
|
||||
let prev_point_index = if next_point_index == 0 {
|
||||
polygon_points.len() - 1
|
||||
|
@ -468,8 +507,11 @@ pub(crate) fn rect_is_outside_polygon(rect: RectF32, polygon_points: &[Point2DF3
|
|||
};
|
||||
let prev = polygon_points[prev_point_index];
|
||||
let polygon_edge_vector = next - prev;
|
||||
if rect_points.iter().all(|&rect_point| polygon_edge_vector.det(rect_point - prev) < 0.0) {
|
||||
return true
|
||||
if rect_points
|
||||
.iter()
|
||||
.all(|&rect_point| polygon_edge_vector.det(rect_point - prev) < 0.0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,7 +521,12 @@ pub(crate) fn rect_is_outside_polygon(rect: RectF32, polygon_points: &[Point2DF3
|
|||
// Edge equation method. Requires that the polygon be convex.
|
||||
pub(crate) fn rect_is_inside_polygon(rect: RectF32, polygon_points: &[Point2DF32]) -> bool {
|
||||
// FIXME(pcwalton): Check winding!
|
||||
let rect_points = [rect.origin(), rect.upper_right(), rect.lower_left(), rect.lower_right()];
|
||||
let rect_points = [
|
||||
rect.origin(),
|
||||
rect.upper_right(),
|
||||
rect.lower_left(),
|
||||
rect.lower_right(),
|
||||
];
|
||||
for (next_point_index, &next) in polygon_points.iter().enumerate() {
|
||||
let prev_point_index = if next_point_index == 0 {
|
||||
polygon_points.len() - 1
|
||||
|
|
|
@ -42,12 +42,14 @@ impl Debug for ColorU {
|
|||
if self.a == 255 {
|
||||
write!(formatter, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b)
|
||||
} else {
|
||||
write!(formatter,
|
||||
"rgba({}, {}, {}, {})",
|
||||
self.r,
|
||||
self.g,
|
||||
self.b,
|
||||
self.a as f32 / 255.0)
|
||||
write!(
|
||||
formatter,
|
||||
"rgba({}, {}, {}, {})",
|
||||
self.r,
|
||||
self.g,
|
||||
self.b,
|
||||
self.a as f32 / 255.0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,16 +19,23 @@ pub struct ContourDilator<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ContourDilator<'a> {
|
||||
pub fn new(contour: &'a mut Contour, amount: Point2DF32, orientation: Orientation)
|
||||
-> ContourDilator<'a> {
|
||||
ContourDilator { contour, amount, orientation }
|
||||
pub fn new(
|
||||
contour: &'a mut Contour,
|
||||
amount: Point2DF32,
|
||||
orientation: Orientation,
|
||||
) -> ContourDilator<'a> {
|
||||
ContourDilator {
|
||||
contour,
|
||||
amount,
|
||||
orientation,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dilate(&mut self) {
|
||||
// Determine orientation.
|
||||
let scale = self.amount.scale_xy(match self.orientation {
|
||||
Orientation::Ccw => Point2DF32::new( 1.0, -1.0),
|
||||
Orientation::Cw => Point2DF32::new(-1.0, 1.0),
|
||||
Orientation::Ccw => Point2DF32::new(1.0, -1.0),
|
||||
Orientation::Cw => Point2DF32::new(-1.0, 1.0),
|
||||
});
|
||||
|
||||
// Find the starting and previous positions.
|
||||
|
@ -68,10 +75,10 @@ impl<'a> ContourDilator<'a> {
|
|||
}
|
||||
let next_vector = (next_position - position).normalize();
|
||||
|
||||
debug!("prev={} cur={} next={}",
|
||||
prev_point_index,
|
||||
current_point_index,
|
||||
next_point_index);
|
||||
debug!(
|
||||
"prev={} cur={} next={}",
|
||||
prev_point_index, current_point_index, next_point_index
|
||||
);
|
||||
|
||||
// Calculate new position by moving the point by the bisector.
|
||||
let bisector = prev_vector.yx() + next_vector.yx();
|
||||
|
@ -83,16 +90,18 @@ impl<'a> ContourDilator<'a> {
|
|||
};
|
||||
let new_position = position - scaled_bisector;
|
||||
|
||||
debug!("dilate(): prev={}({:?}) cur={}({:?}) next={}({:?}) bisector={:?}({:?}, {:?})",
|
||||
prev_point_index,
|
||||
prev_position,
|
||||
current_point_index,
|
||||
position,
|
||||
next_point_index,
|
||||
next_position,
|
||||
bisector,
|
||||
bisector_length,
|
||||
scaled_bisector);
|
||||
debug!(
|
||||
"dilate(): prev={}({:?}) cur={}({:?}) next={}({:?}) bisector={:?}({:?}, {:?})",
|
||||
prev_point_index,
|
||||
prev_position,
|
||||
current_point_index,
|
||||
position,
|
||||
next_point_index,
|
||||
next_position,
|
||||
bisector,
|
||||
bisector_length,
|
||||
scaled_bisector
|
||||
);
|
||||
|
||||
// Update all points.
|
||||
let mut point_index = current_point_index;
|
||||
|
|
|
@ -46,7 +46,10 @@ bitflags! {
|
|||
impl Outline {
|
||||
#[inline]
|
||||
pub fn new() -> Outline {
|
||||
Outline { contours: vec![], bounds: RectF32::default() }
|
||||
Outline {
|
||||
contours: vec![],
|
||||
bounds: RectF32::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -85,9 +88,11 @@ impl Outline {
|
|||
if !segment.is_line() {
|
||||
current_contour.push_point(segment.ctrl.from(), PointFlags::CONTROL_POINT_0, true);
|
||||
if !segment.is_quadratic() {
|
||||
current_contour.push_point(segment.ctrl.to(),
|
||||
PointFlags::CONTROL_POINT_1,
|
||||
true);
|
||||
current_contour.push_point(
|
||||
segment.ctrl.to(),
|
||||
PointFlags::CONTROL_POINT_1,
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,13 +136,20 @@ impl Outline {
|
|||
|
||||
pub fn dilate(&mut self, amount: Point2DF32) {
|
||||
let orientation = Orientation::from_outline(self);
|
||||
self.contours.iter_mut().for_each(|contour| contour.dilate(amount, orientation));
|
||||
self.contours
|
||||
.iter_mut()
|
||||
.for_each(|contour| contour.dilate(amount, orientation));
|
||||
self.bounds = self.bounds.dilate(amount);
|
||||
}
|
||||
|
||||
pub fn prepare_for_tiling(&mut self, view_box: RectF32) {
|
||||
self.contours.iter_mut().for_each(|contour| contour.prepare_for_tiling(view_box));
|
||||
self.bounds = self.bounds.intersection(view_box).unwrap_or_else(|| RectF32::default());
|
||||
self.contours
|
||||
.iter_mut()
|
||||
.for_each(|contour| contour.prepare_for_tiling(view_box));
|
||||
self.bounds = self
|
||||
.bounds
|
||||
.intersection(view_box)
|
||||
.unwrap_or_else(|| RectF32::default());
|
||||
}
|
||||
|
||||
pub fn is_outside_polygon(&self, clip_polygon: &[Point2DF32]) -> bool {
|
||||
|
@ -197,24 +209,35 @@ impl Debug for Outline {
|
|||
impl Contour {
|
||||
#[inline]
|
||||
pub fn new() -> Contour {
|
||||
Contour { points: vec![], flags: vec![], bounds: RectF32::default(), closed: false }
|
||||
Contour {
|
||||
points: vec![],
|
||||
flags: vec![],
|
||||
bounds: RectF32::default(),
|
||||
closed: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces this contour with a new one, with arrays preallocated to match `self`.
|
||||
#[inline]
|
||||
pub(crate) fn take(&mut self) -> Contour {
|
||||
let length = self.len() as usize;
|
||||
mem::replace(self, Contour {
|
||||
points: Vec::with_capacity(length),
|
||||
flags: Vec::with_capacity(length),
|
||||
bounds: RectF32::default(),
|
||||
closed: false,
|
||||
})
|
||||
mem::replace(
|
||||
self,
|
||||
Contour {
|
||||
points: Vec::with_capacity(length),
|
||||
flags: Vec::with_capacity(length),
|
||||
bounds: RectF32::default(),
|
||||
closed: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn iter(&self) -> ContourIter {
|
||||
ContourIter { contour: self, index: 1 }
|
||||
ContourIter {
|
||||
contour: self,
|
||||
index: 1,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -254,10 +277,7 @@ impl Contour {
|
|||
|
||||
// TODO(pcwalton): SIMD.
|
||||
#[inline]
|
||||
pub(crate) fn push_point(&mut self,
|
||||
point: Point2DF32,
|
||||
flags: PointFlags,
|
||||
update_bounds: bool) {
|
||||
pub(crate) fn push_point(&mut self, point: Point2DF32, flags: PointFlags, update_bounds: bool) {
|
||||
debug_assert!(!point.x().is_nan() && !point.y().is_nan());
|
||||
|
||||
if update_bounds {
|
||||
|
@ -272,7 +292,7 @@ impl Contour {
|
|||
#[inline]
|
||||
pub(crate) fn push_segment(&mut self, segment: Segment, update_bounds: bool) {
|
||||
if segment.is_none() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
|
||||
if self.is_empty() {
|
||||
|
@ -280,9 +300,17 @@ impl Contour {
|
|||
}
|
||||
|
||||
if !segment.is_line() {
|
||||
self.push_point(segment.ctrl.from(), PointFlags::CONTROL_POINT_0, update_bounds);
|
||||
self.push_point(
|
||||
segment.ctrl.from(),
|
||||
PointFlags::CONTROL_POINT_0,
|
||||
update_bounds,
|
||||
);
|
||||
if !segment.is_quadratic() {
|
||||
self.push_point(segment.ctrl.to(), PointFlags::CONTROL_POINT_1, update_bounds);
|
||||
self.push_point(
|
||||
segment.ctrl.to(),
|
||||
PointFlags::CONTROL_POINT_1,
|
||||
update_bounds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,9 +322,17 @@ impl Contour {
|
|||
self.push_point(segment.baseline.from(), PointFlags::empty(), update_bounds);
|
||||
|
||||
if !segment.is_line() {
|
||||
self.push_point(segment.ctrl.from(), PointFlags::CONTROL_POINT_0, update_bounds);
|
||||
self.push_point(
|
||||
segment.ctrl.from(),
|
||||
PointFlags::CONTROL_POINT_0,
|
||||
update_bounds,
|
||||
);
|
||||
if !segment.is_quadratic() {
|
||||
self.push_point(segment.ctrl.to(), PointFlags::CONTROL_POINT_1, update_bounds);
|
||||
self.push_point(
|
||||
segment.ctrl.to(),
|
||||
PointFlags::CONTROL_POINT_1,
|
||||
update_bounds,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,14 +372,16 @@ impl Contour {
|
|||
#[inline]
|
||||
pub fn hull_segment_after(&self, prev_point_index: u32) -> LineSegmentF32 {
|
||||
let next_point_index = self.next_point_index_of(prev_point_index);
|
||||
LineSegmentF32::new(&self.points[prev_point_index as usize],
|
||||
&self.points[next_point_index as usize])
|
||||
LineSegmentF32::new(
|
||||
&self.points[prev_point_index as usize],
|
||||
&self.points[next_point_index as usize],
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn point_is_endpoint(&self, point_index: u32) -> bool {
|
||||
!self.flags[point_index as usize]
|
||||
.intersects(PointFlags::CONTROL_POINT_0 | PointFlags::CONTROL_POINT_1)
|
||||
.intersects(PointFlags::CONTROL_POINT_0 | PointFlags::CONTROL_POINT_1)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -427,8 +465,8 @@ impl Contour {
|
|||
if contour_is_monotonic {
|
||||
if self.point_is_endpoint(point_index) {
|
||||
if let Some(last_endpoint_index) = last_endpoint_index {
|
||||
if !self.curve_with_endpoints_is_monotonic(last_endpoint_index,
|
||||
point_index) {
|
||||
if !self.curve_with_endpoints_is_monotonic(last_endpoint_index, point_index)
|
||||
{
|
||||
contour_is_monotonic = false;
|
||||
}
|
||||
}
|
||||
|
@ -443,7 +481,10 @@ impl Contour {
|
|||
}
|
||||
|
||||
// Update bounds.
|
||||
self.bounds = self.bounds.intersection(view_box).unwrap_or_else(|| RectF32::default());
|
||||
self.bounds = self
|
||||
.bounds
|
||||
.intersection(view_box)
|
||||
.unwrap_or_else(|| RectF32::default());
|
||||
}
|
||||
|
||||
fn make_monotonic(&mut self) {
|
||||
|
@ -458,15 +499,23 @@ impl Contour {
|
|||
}
|
||||
|
||||
if let Some(last_endpoint_index) = last_endpoint_index {
|
||||
let position_index =
|
||||
if point_index == input_point_count { 0 } else { point_index };
|
||||
let baseline = LineSegmentF32::new(&contour.points[last_endpoint_index as usize],
|
||||
&contour.points[position_index as usize]);
|
||||
let position_index = if point_index == input_point_count {
|
||||
0
|
||||
} else {
|
||||
point_index
|
||||
};
|
||||
let baseline = LineSegmentF32::new(
|
||||
&contour.points[last_endpoint_index as usize],
|
||||
&contour.points[position_index as usize],
|
||||
);
|
||||
let point_count = point_index - last_endpoint_index + 1;
|
||||
if point_count == 3 {
|
||||
let ctrl_point_index = last_endpoint_index as usize + 1;
|
||||
let ctrl_position = &contour.points[ctrl_point_index];
|
||||
handle_cubic(self, Segment::quadratic(&baseline, &ctrl_position).to_cubic());
|
||||
handle_cubic(
|
||||
self,
|
||||
Segment::quadratic(&baseline, &ctrl_position).to_cubic(),
|
||||
);
|
||||
} else if point_count == 4 {
|
||||
let first_ctrl_point_index = last_endpoint_index as usize + 1;
|
||||
let ctrl_position_0 = &contour.points[first_ctrl_point_index + 0];
|
||||
|
@ -475,9 +524,11 @@ impl Contour {
|
|||
handle_cubic(self, Segment::cubic(&baseline, &ctrl));
|
||||
}
|
||||
|
||||
self.push_point(contour.points[position_index as usize],
|
||||
PointFlags::empty(),
|
||||
false);
|
||||
self.push_point(
|
||||
contour.points[position_index as usize],
|
||||
PointFlags::empty(),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
last_endpoint_index = Some(point_index);
|
||||
|
@ -502,22 +553,25 @@ impl Contour {
|
|||
}
|
||||
}
|
||||
|
||||
fn curve_with_endpoints_is_monotonic(&self, start_endpoint_index: u32, end_endpoint_index: u32)
|
||||
-> bool {
|
||||
fn curve_with_endpoints_is_monotonic(
|
||||
&self,
|
||||
start_endpoint_index: u32,
|
||||
end_endpoint_index: u32,
|
||||
) -> bool {
|
||||
let start_position = self.points[start_endpoint_index as usize];
|
||||
let end_position = self.points[end_endpoint_index as usize];
|
||||
|
||||
if start_position.x() <= end_position.x() {
|
||||
for point_index in start_endpoint_index..end_endpoint_index {
|
||||
if self.points[point_index as usize].x() >
|
||||
self.points[point_index as usize + 1].x() {
|
||||
if self.points[point_index as usize].x() > self.points[point_index as usize + 1].x()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for point_index in start_endpoint_index..end_endpoint_index {
|
||||
if self.points[point_index as usize].x() <
|
||||
self.points[point_index as usize + 1].x() {
|
||||
if self.points[point_index as usize].x() < self.points[point_index as usize + 1].x()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -525,15 +579,15 @@ impl Contour {
|
|||
|
||||
if start_position.y() <= end_position.y() {
|
||||
for point_index in start_endpoint_index..end_endpoint_index {
|
||||
if self.points[point_index as usize].y() >
|
||||
self.points[point_index as usize + 1].y() {
|
||||
if self.points[point_index as usize].y() > self.points[point_index as usize + 1].y()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for point_index in start_endpoint_index..end_endpoint_index {
|
||||
if self.points[point_index as usize].y() <
|
||||
self.points[point_index as usize + 1].y() {
|
||||
if self.points[point_index as usize].y() < self.points[point_index as usize + 1].y()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -554,37 +608,45 @@ impl Debug for Contour {
|
|||
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
for (segment_index, segment) in self.iter().enumerate() {
|
||||
if segment_index == 0 {
|
||||
write!(formatter,
|
||||
"M {} {}",
|
||||
segment.baseline.from_x(),
|
||||
segment.baseline.from_y())?;
|
||||
write!(
|
||||
formatter,
|
||||
"M {} {}",
|
||||
segment.baseline.from_x(),
|
||||
segment.baseline.from_y()
|
||||
)?;
|
||||
}
|
||||
|
||||
match segment.kind {
|
||||
SegmentKind::None => {}
|
||||
SegmentKind::Line => {
|
||||
write!(formatter,
|
||||
" L {} {}",
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y())?;
|
||||
write!(
|
||||
formatter,
|
||||
" L {} {}",
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y()
|
||||
)?;
|
||||
}
|
||||
SegmentKind::Quadratic => {
|
||||
write!(formatter,
|
||||
" Q {} {} {} {}",
|
||||
segment.ctrl.from_x(),
|
||||
segment.ctrl.from_y(),
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y())?;
|
||||
write!(
|
||||
formatter,
|
||||
" Q {} {} {} {}",
|
||||
segment.ctrl.from_x(),
|
||||
segment.ctrl.from_y(),
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y()
|
||||
)?;
|
||||
}
|
||||
SegmentKind::Cubic => {
|
||||
write!(formatter,
|
||||
" C {} {} {} {} {} {}",
|
||||
segment.ctrl.from_x(),
|
||||
segment.ctrl.from_y(),
|
||||
segment.ctrl.to_x(),
|
||||
segment.ctrl.to_y(),
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y())?;
|
||||
write!(
|
||||
formatter,
|
||||
" C {} {} {} {} {} {}",
|
||||
segment.ctrl.from_x(),
|
||||
segment.ctrl.from_y(),
|
||||
segment.ctrl.to_x(),
|
||||
segment.ctrl.to_y(),
|
||||
segment.baseline.to_x(),
|
||||
segment.baseline.to_y()
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -630,8 +692,8 @@ impl<'a> Iterator for ContourIter<'a> {
|
|||
#[inline]
|
||||
fn next(&mut self) -> Option<Segment> {
|
||||
let contour = self.contour;
|
||||
if (self.index == contour.len() && !self.contour.closed) ||
|
||||
self.index == contour.len() + 1 {
|
||||
if (self.index == contour.len() && !self.contour.closed) || self.index == contour.len() + 1
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -654,15 +716,20 @@ impl<'a> Iterator for ContourIter<'a> {
|
|||
let point2 = contour.position_of(point2_index);
|
||||
self.index += 1;
|
||||
if contour.point_is_endpoint(point2_index) {
|
||||
return Some(Segment::quadratic(&LineSegmentF32::new(&point0, &point2), &point1));
|
||||
return Some(Segment::quadratic(
|
||||
&LineSegmentF32::new(&point0, &point2),
|
||||
&point1,
|
||||
));
|
||||
}
|
||||
|
||||
let point3_index = self.index;
|
||||
let point3 = contour.position_of(point3_index);
|
||||
self.index += 1;
|
||||
debug_assert!(contour.point_is_endpoint(point3_index));
|
||||
return Some(Segment::cubic(&LineSegmentF32::new(&point0, &point3),
|
||||
&LineSegmentF32::new(&point1, &point2)));
|
||||
return Some(Segment::cubic(
|
||||
&LineSegmentF32::new(&point0, &point3),
|
||||
&LineSegmentF32::new(&point1, &point2),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,9 +197,10 @@ impl<'s> CubicSegment<'s> {
|
|||
// See Kaspar Fischer, "Piecewise Linear Approximation of Bézier Curves", 2000.
|
||||
#[inline]
|
||||
pub fn is_flat(self, tolerance: f32) -> bool {
|
||||
let mut uv = F32x4::splat(3.0) * self.0.ctrl.0 -
|
||||
self.0.baseline.0 - self.0.baseline.0 -
|
||||
self.0.baseline.reversed().0;
|
||||
let mut uv = F32x4::splat(3.0) * self.0.ctrl.0
|
||||
- self.0.baseline.0
|
||||
- self.0.baseline.0
|
||||
- self.0.baseline.reversed().0;
|
||||
uv = uv * uv;
|
||||
uv = uv.max(uv.zwxy());
|
||||
uv[0] + uv[1] <= 16.0 * tolerance * tolerance
|
||||
|
@ -244,17 +245,20 @@ impl<'s> CubicSegment<'s> {
|
|||
ctrl1 = LineSegmentF32(p012p123.concat_zw_zw(p12p23));
|
||||
}
|
||||
|
||||
(Segment {
|
||||
baseline: baseline0,
|
||||
ctrl: ctrl0,
|
||||
kind: SegmentKind::Cubic,
|
||||
flags: self.0.flags & SegmentFlags::FIRST_IN_SUBPATH,
|
||||
}, Segment {
|
||||
baseline: baseline1,
|
||||
ctrl: ctrl1,
|
||||
kind: SegmentKind::Cubic,
|
||||
flags: self.0.flags & SegmentFlags::CLOSES_SUBPATH,
|
||||
})
|
||||
(
|
||||
Segment {
|
||||
baseline: baseline0,
|
||||
ctrl: ctrl0,
|
||||
kind: SegmentKind::Cubic,
|
||||
flags: self.0.flags & SegmentFlags::FIRST_IN_SUBPATH,
|
||||
},
|
||||
Segment {
|
||||
baseline: baseline1,
|
||||
ctrl: ctrl1,
|
||||
kind: SegmentKind::Cubic,
|
||||
flags: self.0.flags & SegmentFlags::CLOSES_SUBPATH,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -284,13 +288,15 @@ impl<'s> CubicSegment<'s> {
|
|||
#[inline]
|
||||
pub fn y_extrema(self) -> (Option<f32>, Option<f32>) {
|
||||
if self.is_monotonic() {
|
||||
return (None, None)
|
||||
return (None, None);
|
||||
}
|
||||
|
||||
let p0p1p2p3 = F32x4::new(self.0.baseline.from_y(),
|
||||
self.0.ctrl.from_y(),
|
||||
self.0.ctrl.to_y(),
|
||||
self.0.baseline.to_y());
|
||||
let p0p1p2p3 = F32x4::new(
|
||||
self.0.baseline.from_y(),
|
||||
self.0.ctrl.from_y(),
|
||||
self.0.ctrl.to_y(),
|
||||
self.0.baseline.to_y(),
|
||||
);
|
||||
|
||||
let pxp0p1p2 = p0p1p2p3.wxyz();
|
||||
let pxv0v1v2 = p0p1p2p3 - pxp0p1p2;
|
||||
|
@ -317,11 +323,19 @@ impl<'s> CubicSegment<'s> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min_x(&self) -> f32 { f32::min(self.0.baseline.min_x(), self.0.ctrl.min_x()) }
|
||||
pub fn min_x(&self) -> f32 {
|
||||
f32::min(self.0.baseline.min_x(), self.0.ctrl.min_x())
|
||||
}
|
||||
#[inline]
|
||||
pub fn min_y(&self) -> f32 { f32::min(self.0.baseline.min_y(), self.0.ctrl.min_y()) }
|
||||
pub fn min_y(&self) -> f32 {
|
||||
f32::min(self.0.baseline.min_y(), self.0.ctrl.min_y())
|
||||
}
|
||||
#[inline]
|
||||
pub fn max_x(&self) -> f32 { f32::max(self.0.baseline.max_x(), self.0.ctrl.max_x()) }
|
||||
pub fn max_x(&self) -> f32 {
|
||||
f32::max(self.0.baseline.max_x(), self.0.ctrl.max_x())
|
||||
}
|
||||
#[inline]
|
||||
pub fn max_y(&self) -> f32 { f32::max(self.0.baseline.max_y(), self.0.ctrl.max_y()) }
|
||||
pub fn max_y(&self) -> f32 {
|
||||
f32::max(self.0.baseline.max_y(), self.0.ctrl.max_y())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@ pub struct OutlineStrokeToFill {
|
|||
impl OutlineStrokeToFill {
|
||||
#[inline]
|
||||
pub fn new(outline: Outline, stroke_width: f32) -> OutlineStrokeToFill {
|
||||
OutlineStrokeToFill { outline, stroke_width }
|
||||
OutlineStrokeToFill {
|
||||
outline,
|
||||
stroke_width,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -55,7 +58,11 @@ struct ContourStrokeToFill {
|
|||
impl ContourStrokeToFill {
|
||||
#[inline]
|
||||
fn new(input: Contour, output: Contour, radius: f32) -> ContourStrokeToFill {
|
||||
ContourStrokeToFill { input, output, radius }
|
||||
ContourStrokeToFill {
|
||||
input,
|
||||
output,
|
||||
radius,
|
||||
}
|
||||
}
|
||||
|
||||
fn offset_forward(&mut self) {
|
||||
|
@ -66,7 +73,11 @@ impl ContourStrokeToFill {
|
|||
|
||||
fn offset_backward(&mut self) {
|
||||
// FIXME(pcwalton)
|
||||
let mut segments: Vec<_> = self.input.iter().map(|segment| segment.reversed()).collect();
|
||||
let mut segments: Vec<_> = self
|
||||
.input
|
||||
.iter()
|
||||
.map(|segment| segment.reversed())
|
||||
.collect();
|
||||
segments.reverse();
|
||||
for segment in &segments {
|
||||
segment.offset(self.radius, &mut self.output);
|
||||
|
@ -108,7 +119,7 @@ impl Offset for SegmentPF3 {
|
|||
|
||||
if self.is_quadratic() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
|
@ -123,7 +134,7 @@ impl Offset for SegmentPF3 {
|
|||
|
||||
if self.baseline.from() == self.ctrl.from() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
|
@ -137,7 +148,7 @@ impl Offset for SegmentPF3 {
|
|||
|
||||
if self.ctrl.to() == self.baseline.to() {
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
let ctrl = match segment_0.intersection_t(&segment_1) {
|
||||
|
@ -150,18 +161,20 @@ impl Offset for SegmentPF3 {
|
|||
}
|
||||
|
||||
let mut segment_0 = LineSegmentF32::new(&self.baseline.from(), &self.ctrl.from());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.ctrl.to());
|
||||
let mut segment_2 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
let mut segment_1 = LineSegmentF32::new(&self.ctrl.from(), &self.ctrl.to());
|
||||
let mut segment_2 = LineSegmentF32::new(&self.ctrl.to(), &self.baseline.to());
|
||||
segment_0 = segment_0.offset(distance);
|
||||
segment_1 = segment_1.offset(distance);
|
||||
segment_2 = segment_2.offset(distance);
|
||||
let (ctrl_0, ctrl_1) = match (segment_0.intersection_t(&segment_1),
|
||||
segment_1.intersection_t(&segment_2)) {
|
||||
let (ctrl_0, ctrl_1) = match (
|
||||
segment_0.intersection_t(&segment_1),
|
||||
segment_1.intersection_t(&segment_2),
|
||||
) {
|
||||
(Some(t0), Some(t1)) => (segment_0.sample(t0), segment_1.sample(t1)),
|
||||
_ => {
|
||||
(segment_0.to().lerp(segment_1.from(), 0.5),
|
||||
segment_1.to().lerp(segment_2.from(), 0.5))
|
||||
}
|
||||
_ => (
|
||||
segment_0.to().lerp(segment_1.from(), 0.5),
|
||||
segment_1.to().lerp(segment_2.from(), 0.5),
|
||||
),
|
||||
};
|
||||
let baseline = LineSegmentF32::new(&segment_0.from(), &segment_2.to());
|
||||
let ctrl = LineSegmentF32::new(&ctrl_0, &ctrl_1);
|
||||
|
@ -169,7 +182,10 @@ impl Offset for SegmentPF3 {
|
|||
}
|
||||
|
||||
fn error_is_within_tolerance(&self, other: &SegmentPF3, distance: f32) -> bool {
|
||||
let (mut min, mut max) = (f32::abs(distance) - TOLERANCE, f32::abs(distance) + TOLERANCE);
|
||||
let (mut min, mut max) = (
|
||||
f32::abs(distance) - TOLERANCE,
|
||||
f32::abs(distance) + TOLERANCE,
|
||||
);
|
||||
min = if min <= 0.0 { 0.0 } else { min * min };
|
||||
max = if max <= 0.0 { 0.0 } else { max * max };
|
||||
|
||||
|
@ -179,8 +195,10 @@ impl Offset for SegmentPF3 {
|
|||
let (this_p, other_p) = (self.sample(t), other.sample(t));
|
||||
let vector = this_p - other_p;
|
||||
let square_distance = vector.square_length();
|
||||
debug!("this_p={:?} other_p={:?} vector={:?} sqdist={:?} min={:?} max={:?}",
|
||||
this_p, other_p, vector, square_distance, min, max);
|
||||
debug!(
|
||||
"this_p={:?} other_p={:?} vector={:?} sqdist={:?} min={:?} max={:?}",
|
||||
this_p, other_p, vector, square_distance, min, max
|
||||
);
|
||||
if square_distance < min || square_distance > max {
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue