diff --git a/Cargo.toml b/Cargo.toml index 315da3f..aa677df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "euclid" -version = "0.16.1" +version = "0.16.2" authors = ["The Servo Project Developers"] description = "Geometry primitives" documentation = "https://docs.rs/euclid/" diff --git a/src/rotation.rs b/src/rotation.rs index e25af1b..0c33a43 100644 --- a/src/rotation.rs +++ b/src/rotation.rs @@ -216,7 +216,6 @@ where T: Copy + Clone + Mul + Div + Neg + - ApproxEq + PartialOrd + Float + One + Zero @@ -330,7 +329,8 @@ impl TypedRotation3D where T: Copy { } impl TypedRotation3D -where T: Float + ApproxEq +where + T: Float, { /// Creates the identity rotation. #[inline] @@ -428,7 +428,10 @@ where T: Float + ApproxEq } #[inline] - pub fn is_normalized(&self) -> bool { + pub fn is_normalized(&self) -> bool + where + T: ApproxEq, + { // TODO: we might need to relax the threshold here, because of floating point imprecision. self.square_norm().approx_eq(&T::one()) } @@ -436,7 +439,10 @@ where T: Float + ApproxEq /// Spherical linear interpolation between this rotation and another rotation. /// /// `t` is expected to be between zero and one. - pub fn slerp(&self, other: &Self, t: T) -> Self { + pub fn slerp(&self, other: &Self, t: T) -> Self + where + T: ApproxEq, + { debug_assert!(self.is_normalized()); debug_assert!(other.is_normalized()); @@ -484,7 +490,10 @@ where T: Float + ApproxEq /// Returns the given 3d point transformed by this rotation. /// /// The input point must be use the unit Src, and the returned point has the unit Dst. - pub fn rotate_point3d(&self, point: &TypedPoint3D) -> TypedPoint3D { + pub fn rotate_point3d(&self, point: &TypedPoint3D) -> TypedPoint3D + where + T: ApproxEq, + { debug_assert!(self.is_normalized()); let two = T::one() + T::one(); @@ -501,7 +510,10 @@ where T: Float + ApproxEq /// /// The input point must be use the unit Src, and the returned point has the unit Dst. #[inline] - pub fn rotate_point2d(&self, point: &TypedPoint2D) -> TypedPoint2D { + pub fn rotate_point2d(&self, point: &TypedPoint2D) -> TypedPoint2D + where + T: ApproxEq, + { self.rotate_point3d(&point.to_3d()).xy() } @@ -509,7 +521,10 @@ where T: Float + ApproxEq /// /// The input vector must be use the unit Src, and the returned point has the unit Dst. #[inline] - pub fn rotate_vector3d(&self, vector: &TypedVector3D) -> TypedVector3D { + pub fn rotate_vector3d(&self, vector: &TypedVector3D) -> TypedVector3D + where + T: ApproxEq, + { self.rotate_point3d(&vector.to_point()).to_vector() } @@ -517,13 +532,19 @@ where T: Float + ApproxEq /// /// The input vector must be use the unit Src, and the returned point has the unit Dst. #[inline] - pub fn rotate_vector2d(&self, vector: &TypedVector2D) -> TypedVector2D { + pub fn rotate_vector2d(&self, vector: &TypedVector2D) -> TypedVector2D + where + T: ApproxEq, + { self.rotate_vector3d(&vector.to_3d()).xy() } /// Returns the matrix representation of this rotation. #[inline] - pub fn to_transform(&self) -> TypedTransform3D { + pub fn to_transform(&self) -> TypedTransform3D + where + T: ApproxEq, + { debug_assert!(self.is_normalized()); let i2 = self.i + self.i; @@ -563,7 +584,10 @@ where T: Float + ApproxEq } /// Returns a rotation representing the other rotation followed by this rotation. - pub fn pre_rotate(&self, other: &TypedRotation3D) -> TypedRotation3D { + pub fn pre_rotate(&self, other: &TypedRotation3D) -> TypedRotation3D + where + T: ApproxEq, + { debug_assert!(self.is_normalized()); TypedRotation3D::quaternion( self.i * other.r + self.r * other.i + self.j * other.k - self.k * other.j, @@ -575,7 +599,10 @@ where T: Float + ApproxEq /// Returns a rotation representing this rotation followed by the other rotation. #[inline] - pub fn post_rotate(&self, other: &TypedRotation3D) -> TypedRotation3D { + pub fn post_rotate(&self, other: &TypedRotation3D) -> TypedRotation3D + where + T: ApproxEq, + { other.pre_rotate(self) } diff --git a/src/vector.rs b/src/vector.rs index 6bdef1a..473001c 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -151,13 +151,8 @@ where T: Copy + Mul + Add + Sub { } #[inline] - pub fn normalize(self) -> Self where T: Float + ApproxEq { - let dot = self.dot(self); - if dot.approx_eq(&T::zero()) { - self - } else { - self / dot.sqrt() - } + pub fn normalize(self) -> Self where T: Float { + self / self.length() } #[inline] @@ -547,13 +542,8 @@ impl + } #[inline] - pub fn normalize(self) -> Self where T: Float + ApproxEq { - let dot = self.dot(self); - if dot.approx_eq(&T::zero()) { - self - } else { - self / dot.sqrt() - } + pub fn normalize(self) -> Self where T: Float { + self / self.length() } #[inline] @@ -562,7 +552,7 @@ impl + } #[inline] - pub fn length(&self) -> T where T: Float + ApproxEq { + pub fn length(&self) -> T where T: Float { self.square_length().sqrt() } } @@ -839,7 +829,7 @@ mod vector2d { let p0: Vec2 = Vec2::zero(); let p1: Vec2 = vec2(4.0, 0.0); let p2: Vec2 = vec2(3.0, -4.0); - assert_eq!(p0.normalize(), p0); + assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan()); assert_eq!(p1.normalize(), vec2(1.0, 0.0)); assert_eq!(p2.normalize(), vec2(0.6, -0.8)); } @@ -950,7 +940,7 @@ mod vector3d { let p0: Vec3 = Vec3::zero(); let p1: Vec3 = vec3(0.0, -6.0, 0.0); let p2: Vec3 = vec3(1.0, 2.0, -2.0); - assert_eq!(p0.normalize(), p0); + assert!(p0.normalize().x.is_nan() && p0.normalize().y.is_nan() && p0.normalize().z.is_nan()); assert_eq!(p1.normalize(), vec3(0.0, -1.0, 0.0)); assert_eq!(p2.normalize(), vec3(1.0/3.0, 2.0/3.0, -2.0/3.0)); }