bounding_alignedbox_sphere.hpp

Back to Bounding aligned box

pastel/geometry/bounding/

#ifndef PASTELGEOMETRY_BOUNDING_ALIGNEDBOX_SPHERE_HPP
#define PASTELGEOMETRY_BOUNDING_ALIGNEDBOX_SPHERE_HPP

#include "pastel/geometry/bounding/bounding_alignedbox_sphere.h"

#include "pastel/sys/vector/vector_tools.h"

namespace Pastel
{

    template <typename Real, integer N>
    AlignedBox<Real, N> boundingAlignedBox(
        const Sphere<Real, N>& sphere)
    {
        return AlignedBox<Real, N>(
            sphere.position() - sphere.radius(),
            sphere.position() + sphere.radius());
    }

    template <typename Real, integer N>
    AlignedBox<Real, N> boundingAlignedBox(
        const Sphere<Real, N>& sphere,
        const AffineTransformation<Real>& transformation)
    {
        // One can show that:
        //
        // 1) The quadratic-form matrix of the ellipsoid
        // given by transforming an origin centered unit sphere 
        // with a linear transformation A is given by:
        // Q = A^-T A^-1
        // This is shown in 'ellipsoid.hpp'.
        //
        // 2) Given a quadratic-form matrix Q for an origin-centered 
        // ellipsoid, its axis-aligned bounding box is obtained
        // by +/- sqrt(diagonal(Q^-1)).
        // This is also shown in 'ellipsoid.hpp'.
        //
        // Combining, we obtain the axis-aligned bounding box by:
        // +/- sqrt(diagonal(A A^T)).

        // The bounding box is invariant w.r.t to the position of
        // the sphere. Thus the center of the sphere can simply be
        // transformed through the affine transformation.
        // The radius of the sphere simply scales the end-result
        // uniformly w.r.t the center of the sphere.

        // This is a prime example of the power of expression templates:
        // the complexity is just O(n^2) compared to O(n^3) if the
        // operations were actually carried out non-lazily.

        Vector<Real, N> radius =
            sqrt(
                diagonal(
                    transformation.matrix() * 
                    transpose(transformation.matrix())
                )
            ) * sphere.radius();

        Vector<Real, N> center =
            transformPoint(transformation, sphere.position());

        return AlignedBox<Real, N>(
            center - radius, 
            center + radius);
    }

}

#endif