distance_alignedbox_point.h

Back to Distance

pastel/geometry/distance/

// Description: Distance between an aligned box and a point

#ifndef PASTELGEOMETRY_DISTANCE_ALIGNEDBOX_POINT_H
#define PASTELGEOMETRY_DISTANCE_ALIGNEDBOX_POINT_H

#include "pastel/sys/point/point_concept.h"
#include "pastel/math/distance/distance_concept.h"
#include "pastel/geometry/shape/alignedbox.h"
#include "pastel/geometry/distance/distance_alignedbox_point.h"
#include "pastel/geometry/distance/distance_point_point.h"

#include "pastel/math/norm/euclidean_norm.h"

namespace Pastel
{

    //! Distance between an aligned box and a point.
    /*!
   Preconditions:
   alignedBox.n() == point.n()

   Time complexity: O(alignedBox.n())

   It is assumed that the aligned box is solid.
   */
    template <
        typename Real, 
        int N,
        Point_Concept Point,
        typename... ArgumentSet
    >
    requires 
        IsEqualDim<N, Point_N<Point>::value>
    auto distance2(
        const AlignedBox<Real, N>& alignedBox,
        const Point& point,
        ArgumentSet&&... argumentSet)
    {
        PENSURE_OP(alignedBox.n(), ==, dimension(point));

        auto&& norm = 
            PASTEL_ARG_C(norm, Euclidean_Norm<Real>(), Norm_Concept);

        // The distance computation between an AlignedBox and a point can
        // be decomposed into separate computations on each
        // coordinate axis. In this 1-dimensional world, the AlignedBox
        // degenerates into a range. For each axis we
        // calculate the squared distance of the point coordinate
        // to the AlignedBox coordinate range. If the point coordinate
        // is inside the AlignedBox coordinate range,
        // that particular distance is 0.
        // Finally, the 1-dimensional squared distances
        // are added together to obtain the dreal N-dimensional
        // squared distance.

        auto distance = norm();

        integer n = alignedBox.n();
        for (integer i = 0;i < n;++i)
        {
            Real x = pointAxis(point, i);
            if (x < alignedBox.min()[i])
            {
                // If the i:th point coordinate is
                // on the lesser side of the range,
                // base the distance calculation
                // on the range's minimum point.

                distance.set(i, alignedBox.min()[i] - x);
            }
            else if (x > alignedBox.max()[i])
            {
                // If the i:th point coordinate is
                // on the greater side of the range,
                // base the distance calculation
                // on the range's maximum point.

                distance.set(i, x - alignedBox.max()[i]);
            }
        }

        return distance;
    }

    //! Farthest distance between an aligned box and a point.
    /*!
   Preconditions:
   alignedBox.n() == point.n()

   Time complexity: O(alignedBox.n())

   It is assumed that the aligned box is solid.
   */
    template <
        typename Real, 
        int N,
        Point_Concept Point,
        typename... ArgumentSet
    >
    requires 
        IsEqualDim<N, Point_N<Point>::value>
    auto farthestDistance2(
        const AlignedBox<Real, N>& alignedBox,
        const Point& point,
        ArgumentSet&&... argumentSet)
    {
        auto&& norm = 
            PASTEL_ARG_C(norm, Euclidean_Norm<Real>(), Norm_Concept);

        auto distance = norm();

        const integer n = alignedBox.n();
        for (integer i = 0;i < n;++i) {
            distance.set(i, 
                std::max(
                    abs(alignedBox.min()[i] - pointAxis(point, i)),
                    abs(alignedBox.max()[i] - pointAxis(point, i))
                )
            );
        }

        return distance;
    }

}

#endif