use alga::general::Real; use core::{DefaultAllocator, Scalar, Unit, Matrix, Vector}; use core::constraint::{ShapeConstraint, SameNumberOfRows, DimEq, AreMultipliable}; use core::allocator::Allocator; use dimension::{Dim, DimName, U1}; use storage::{Storage, StorageMut}; use geometry::Point; /// A reflection wrt. a plane. pub struct Reflection> { axis: Vector, bias: N } impl> Reflection { /// Creates a new reflection wrt the plane orthogonal to the given axis and bias. /// /// The bias is the position of the plane on the axis. In particular, a bias equal to zero /// represents a plane that passes through the origin. pub fn new(axis: Unit>, bias: N) -> Reflection { Reflection { axis: axis.unwrap(), bias: bias } } /// Creates a new reflection wrt. the plane orthogonal to the given axis and that contains the /// point `pt`. pub fn new_containing_point(axis: Unit>, pt: &Point) -> Reflection where D: DimName, DefaultAllocator: Allocator { let bias = pt.coords.dot(axis.as_ref()); Self::new(axis, bias) } /// The reflexion axis. pub fn axis(&self) -> &Vector { &self.axis } // FIXME: naming convension: reflect_to, reflect_assign ? /// Applies the reflection to the columns of `rhs`. pub fn reflect(&self, rhs: &mut Matrix) where S2: StorageMut, ShapeConstraint: SameNumberOfRows { for i in 0 .. rhs.ncols() { // NOTE: we borrow the column twice here. First it is borrowed immutably for the // dot product, and then mutably. Somehow, this allows significantly // better optimizations of the dot product from the compiler. let m_two: N = ::convert(-2.0f64); let factor = (rhs.column(i).dot(&self.axis) - self.bias) * m_two; rhs.column_mut(i).axpy(factor, &self.axis, N::one()); } } /// Applies the reflection to the rows of `rhs`. pub fn reflect_rows(&self, rhs: &mut Matrix, work: &mut Vector) where S2: StorageMut, S3: StorageMut, ShapeConstraint: DimEq + AreMultipliable { rhs.mul_to(&self.axis, work); if !self.bias.is_zero() { work.add_scalar_mut(-self.bias); } let m_two: N = ::convert(-2.0f64); rhs.ger(m_two, &work, &self.axis, N::one()); } }