diff --git a/src/geometry/scale.rs b/src/geometry/scale.rs index 5c55e5f4..7f9f3f78 100755 --- a/src/geometry/scale.rs +++ b/src/geometry/scale.rs @@ -177,13 +177,69 @@ impl Scale { /// assert_eq!(t.inverse() * t, Scale2::identity()); /// ``` #[inline] - #[must_use = "Did you mean to use inverse_mut()?"] - pub fn inverse(&self) -> Scale + #[must_use = "Did you mean to use try_inverse_mut()?"] + pub fn try_inverse(&self) -> Option> where - T: ClosedDiv + One, + T: ClosedDiv + One + Zero, { - let useless: SVector = SVector::from_element(T::one()); - return useless.component_div(&self.vector).into(); + for i in 0..D { + if self.vector[(i, 0)] == T::zero() { + return None; + } + } + return Some(self.vector.map(|e| T::one() / e).into()); + } + + /// Inverts `self`. + /// + /// # Example + /// ``` + /// # use nalgebra::{Scale2, Scale3}; + /// let t = Scale3::new(1.0, 2.0, 3.0); + /// assert_eq!(t * t.inverse(), Scale3::identity()); + /// assert_eq!(t.inverse() * t, Scale3::identity()); + /// + /// // Work in all dimensions. + /// let t = Scale2::new(1.0, 2.0); + /// assert_eq!(t * t.inverse(), Scale2::identity()); + /// assert_eq!(t.inverse() * t, Scale2::identity()); + /// ``` + #[inline] + #[must_use] + pub unsafe fn inverse_unchecked(&self) -> Scale + where + T: ClosedDiv + One, + { + return self.vector.map(|e| T::one() / e).into(); + } + + /// Inverts `self`. + /// + /// # Example + /// ``` + /// # use nalgebra::{Scale2, Scale3}; + /// let t = Scale3::new(1.0, 2.0, 3.0); + /// assert_eq!(t * t.inverse(), Scale3::identity()); + /// assert_eq!(t.inverse() * t, Scale3::identity()); + /// + /// // Work in all dimensions. + /// let t = Scale2::new(1.0, 2.0); + /// assert_eq!(t * t.inverse(), Scale2::identity()); + /// assert_eq!(t.inverse() * t, Scale2::identity()); + /// ``` + #[inline] + #[must_use] + pub fn pseudo_inverse(&self) -> Scale + where + T: ClosedDiv + One + Zero, + { + return self.vector.map(|e| { + if e != T::zero() { + return T::one() / e; + } else { + return T::zero(); + } + }).into(); } /// Converts this Scale into its equivalent homogeneous transformation matrix. @@ -244,11 +300,15 @@ impl Scale { /// assert_eq!(inv_t * t, Scale2::identity()); /// ``` #[inline] - pub fn inverse_mut(&mut self) + pub fn try_inverse_mut(&mut self) -> bool where - T: ClosedDiv + One, + T: ClosedDiv + One + Zero { - self.vector = self.inverse().vector; + if let Some(v) = self.try_inverse() { + self.vector = v.vector; + return true; + } + return false; } } @@ -270,7 +330,7 @@ impl Scale { } } -impl Scale { +impl Scale { /// Translate the given point by the inverse of this Scale. /// /// # Example @@ -281,8 +341,11 @@ impl Scale { /// assert_eq!(transformed_point, Point3::new(4.0, 3.0, 2.0)); #[inline] #[must_use] - pub fn inverse_transform_point(&self, pt: &Point) -> Point { - return self.inverse() * pt; + pub fn try_inverse_transform_point(&self, pt: &Point) -> Option> { + if let Some(s) = self.try_inverse() { + return Some(s * pt); + } + return None; } }