sphere.h

Back to Sphere

pastel/geometry/shape/

// Description: Sphere

#ifndef PASTELGEOMETRY_SPHERE_H
#define PASTELGEOMETRY_SPHERE_H

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

#include "pastel/geometry/topology.h"

#include <boost/operators.hpp>

namespace Pastel
{

    //! A sphere.
    /*!
   A sphere S is specified by a center position c
   and radius r. Then
   S = {x | |x - c| <= r}
   */

    template <typename Real, int N = Dynamic>
    class Sphere
        : boost::multipliable<Sphere<Real, N>, Real
        , boost::dividable<Sphere<Real, N>, Real
        , boost::addable<Sphere<Real, N>, Vector<Real, N>
        , boost::subtractable<Sphere<Real, N>, Vector<Real, N>
        > > > >
    {
    public:
        using Real_ = Real;
        static constexpr int N_ = N;

        // Using default copy constructor.
        // Using default assignment.

        //! Construct an origin centered unit sphere.
        Sphere();

        //! Construct an origin centered unit sphere.
        explicit Sphere(integer dimension);

        //! Construct a sphere using given position and radius.
        Sphere(
            const Vector<Real, N>& position,
            const Real& radius,
            Topology topology = Topology::Closed);

        //! Construct a sphere using given position and radius.
        Sphere(integer dimension,
            const Vector<Real, N>& position,
            const Real& radius,
            Topology topology = Topology::Closed);

        // Used for concept checking.
        ~Sphere();

        //! Swaps two Sphere's.
        void swap(Sphere& that);

        //! Returns the dimension of the sphere.
        integer n() const;

        //! Sets the position of the sphere.
        void setPosition(const Vector<Real, N>& position);

        //! Returns the position of the sphere.
        const Vector<Real, N>& position() const;

        //! Sets the radius of the sphere.
        void setRadius(const Real& radius);

        //! Returns the radius of the sphere.
        const Real& radius() const;

        //! Sets the topology of the sphere.
        void setTopology(Topology topology);

        //! Returns the topology of the sphere.
        Topology topology() const;

        //! Returns the inverse of the radius of the sphere.
        /*!
       This caching is to enable faster algorithms, since
       division is expensive.
       */
        const Real& inverseRadius() const;

        //! Translates the sphere by the given vector.
        Sphere<Real, N>& operator+=(const Vector<Real, N>& that);

        //! Translates the sphere backwards by the given vector.
        Sphere<Real, N>& operator-=(const Vector<Real, N>& that);

        //! Scales up the sphere without affecting position.
        Sphere<Real, N>& operator*=(const Real& that);

        //! Scales down the sphere without affecting position.
        Sphere<Real, N>& operator/=(const Real& that);

    private:
        Vector<Real, N> position_;
        Real radius_;
        Real inverseRadius_;
        Topology topology_;
    };

    template <typename Real, int N>
    void swap(
        Sphere<Real, N>& left, 
        Sphere<Real, N>& right);

    using Sphere1 = Sphere<dreal, 1>;
    using Sphere2 = Sphere<dreal, 2>;
    using Sphere3 = Sphere<dreal, 3>;
    using Sphere4 = Sphere<dreal, 4>;
    using SphereD = Sphere<dreal, Dynamic>;

}

#include "pastel/sys/vector.h"
#include "pastel/sys/math/constants.h"

namespace Pastel
{

    template <typename Real, int N>
    Sphere<Real, N>::Sphere()
        : position_(0)
        , radius_(1)
        , inverseRadius_(1)
        , topology_(Topology::Closed)
    {
        PASTEL_STATIC_ASSERT(N != Dynamic);
    }

    template <typename Real, int N>
    Sphere<Real, N>::Sphere(integer dimension)
        : position_(ofDimension(dimension), 0)
        , radius_(1)
        , inverseRadius_(1)
        , topology_(Topology::Closed)
    {
    }

    template <typename Real, int N>
    Sphere<Real, N>::Sphere(
        const Vector<Real, N>& position,
        const Real& radius,
        Topology topology)
        : position_(position)
        , radius_(radius)
        , inverseRadius_(inverse(radius))
        , topology_(topology)
    {
        PASTEL_STATIC_ASSERT(N != Dynamic);
    }

    template <typename Real, int N>
    Sphere<Real, N>::Sphere(
        integer dimension,
        const Vector<Real, N>& position,
        const Real& radius,
        Topology topology)
        : position_(position)
        , radius_(radius)
        , inverseRadius_(inverse(radius))
        , topology_(topology)
    {
        PENSURE_OP(dimension, ==, position.n());
    }

    template <typename Real, int N>
    Sphere<Real, N>::~Sphere()
    {
        PASTEL_STATIC_ASSERT(N == Dynamic || N > 0);
    }

    template <typename Real, int N>
    void Sphere<Real, N>::swap(Sphere& that)
    {
        using std::swap;
        using std::swap;

        position_.swap(that.position_);
        swap(radius_, that.radius_);
        swap(inverseRadius_, that.inverseRadius_);
        swap(topology_, that.topology_);
    }

    template <typename Real, int N>
    integer Sphere<Real, N>::n() const
    {
        return position_.n();
    }

    template <typename Real, int N>
    void Sphere<Real, N>::setPosition(
        const Vector<Real, N>& position)
    {
        PENSURE_OP(position_.n(), ==, position.n());

        position_ = position;
    }

    template <typename Real, int N>
    const Vector<Real, N>& Sphere<Real, N>::position() const
    {
        return position_;
    }

    template <typename Real, int N>
    void Sphere<Real, N>::setRadius(const Real& radius)
    {
        radius_ = radius;
        inverseRadius_ = inverse(radius_);
    }

    template <typename Real, int N>
    const Real& Sphere<Real, N>::radius() const
    {
        return radius_;
    }

    template <typename Real, int N>
    void Sphere<Real, N>::setTopology(Topology topology)
    {
        topology_ = topology;
    }

    template <typename Real, int N>
    Topology Sphere<Real, N>::topology() const
    {
        return topology_;
    }

    template <typename Real, int N>
    const Real& Sphere<Real, N>::inverseRadius() const
    {
        return inverseRadius_;
    }

    template <typename Real, int N>
    Sphere<Real, N>& Sphere<Real, N>::operator+=(
        const Vector<Real, N>& that)
    {
        position_ += that;
        return *this;
    }

    template <typename Real, int N>
    Sphere<Real, N>& Sphere<Real, N>::operator-=(
        const Vector<Real, N>& that)
    {
        position_ -= that;
        return *this;
    }

    template <typename Real, int N>
    Sphere<Real, N>& Sphere<Real, N>::operator*=(
        const Real& that)
    {
        radius_ *= that;
        inverseRadius_ /= that;

        return *this;
    }

    template <typename Real, int N>
    Sphere<Real, N>& Sphere<Real, N>::operator/=(
        const Real& that)
    {
        radius_ /= that;
        inverseRadius_ *= that;

        return *this;
    }

    template <typename Real, int N>
    void swap(
        Sphere<Real, N>& left,
        Sphere<Real, N>& right)
    {
        left.swap(right);
    }

}

#endif