plane.h

Back to Plane

pastel/geometry/shape/

// Description: Plane

#ifndef PASTELGEOMETRY_PLANE_H
#define PASTELGEOMETRY_PLANE_H

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

#include <boost/operators.hpp>

namespace Pastel
{

    //! A plane.

    /*!
   A plane can be described by a position and a
   normal. The hyperplane is the set of all x's that satisfy
   the equation:
   dot(normal, x - position) = 0

   The plane passes through the given
   'position' point. This can be seen by substituting
   'x' = 'position'. Any other 'position' point on the plane
   describes the same plane. For consider any translation
   vector T on the plane, such that dot(normal, T) = 0.
   Then
   dot(normal, x - (position + T)) =
   dot(normal, x - position) - dot(normal, T) =
   dot(normal, x - position)

   For performance reasons it must
   be required that the plane normal is always of unit
   length. This is not enforced by the system, but it is
   required by the algorithms.
   */

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

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

        //! Constructs an x-orthogonal plane at the origin.
        Plane();

        //! Constructs an x-orthogonal plane at the origin.
        explicit Plane(integer dimension);

        //! Constructs a plane given a position and a normal.
        Plane(const Vector<Real, N>& position,
            const Vector<Real, N>& unitNormal);

        //! Constructs a plane given a position and a normal.
        Plane(integer dimension,
            const Vector<Real, N>& position,
            const Vector<Real, N>& unitNormal);

        //! Used for concept checking.
        ~Plane();

        //! Swaps two planes.
        void swap(Plane<Real, N>& that);

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

        //! Sets the position and normal of the plane.
        void set(const Vector<Real, N>& position,
            const Vector<Real, N>& unitNormal);

        //! Sets the point which the plane must pass through.
        void setPosition(const Vector<Real, N>& position);

        //! Returns the point that the plane must pass through.
        const Vector<Real, N>& position() const;

        //! Sets the normal of the plane.
        void setNormal(const Vector<Real, N>& unitNormal);

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

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

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

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

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

    private:
        Vector<Real, N> position_;
        Vector<Real, N> normal_;
    };

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

    using Plane1 = Plane<dreal, 1>;
    using Plane2 = Plane<dreal, 2>;
    using Plane3 = Plane<dreal, 3>;
    using Plane4 = Plane<dreal, 4>;
    using PlaneD = Plane<dreal, Dynamic>;

}

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

namespace Pastel
{

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

    template <typename Real, int N>
    Plane<Real, N>::Plane()
        : position_()
        , normal_(unitAxis<Real, N>(0))
    {
        PASTEL_STATIC_ASSERT(N != Dynamic);
    }

    template <typename Real, int N>
    Plane<Real, N>::Plane(integer dimension)
        : position_(ofDimension(dimension))
        , normal_(unitAxis<Real, N>(dimension, 0))
    {
    }

    template <typename Real, int N>
    Plane<Real, N>::Plane(
        const Vector<Real, N>& position,
        const Vector<Real, N>& unitNormal)
        : position_(position)
        , normal_(unitNormal)
    {
    }

    template <typename Real, int N>
    Plane<Real, N>::Plane(
        integer dimension,
        const Vector<Real, N>& position,
        const Vector<Real, N>& unitNormal)
        : position_(position)
        , normal_(unitNormal)
    {
        PENSURE_OP(dimension, ==, position.n());
        PENSURE_OP(dimension, ==, unitNormal.n());
    }

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

    template <typename Real, int N>
    void Plane<Real, N>::swap(
        Plane<Real, N>& that)
    {
        position_.swap(that.position_);
        normal_.swap(that.normal_);
    }

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

    template <typename Real, int N>
    void Plane<Real, N>::set(
        const Vector<Real, N>& position,
        const Vector<Real, N>& unitNormal)
    {
        setPosition(position);
        setNormal(unitNormal);
    }

    template <typename Real, int N>
    void Plane<Real, N>::setPosition(
        const Vector<Real, N>& position)
    {
        position_ = position;
    }

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

    template <typename Real, int N>
    void Plane<Real, N>::setNormal(
        const Vector<Real, N>& unitNormal)
    {
        normal_ = unitNormal;
    }

    template <typename Real, int N>
    const Vector<Real, N>& Plane<Real, N>::normal() const
    {
        return normal_;
    }

    template <typename Real, int N>
    Plane<Real, N>& Plane<Real, N>::operator+=(
        const Vector<Real, N>& that)
    {
        position_ += that;

        return *this;
    }

    template <typename Real, int N>
    Plane<Real, N>& Plane<Real, N>::operator-=(
        const Vector<Real, N>& that)
    {
        position_ -= that;

        return *this;
    }

    template <typename Real, int N>
    Plane<Real, N>& Plane<Real, N>::operator*=(
        const Real& that)
    {
        // Do nothing.

        unused(that);

        return *this;
    }

    template <typename Real, int N>
    Plane<Real, N>& Plane<Real, N>::operator/=(
        const Real& that)
    {
        PENSURE_OP(that, !=, 0);

        // Do nothing.

        return *this;
    }

}

#endif