bounding_sphere_pointset.h

Back to Bounding sphere

pastel/geometry/bounding/

// Description: Bounding sphere of a point-set

#ifndef PASTELGEOMETRY_BOUNDING_SPHERE_POINTSET_H
#define PASTELGEOMETRY_BOUNDING_SPHERE_POINTSET_H

#include "pastel/geometry/shape/sphere.h"

#include "pastel/sys/point/point_concept.h"
#include "pastel/sys/pointset/pointset_concept.h"
#include "pastel/sys/vector/vector.h"
#include "pastel/math/statistic/point_mean.h"

namespace Pastel
{

    //! Finds the minimum volume bounding sphere of two points.
    template <
        Point_Concept A_Point,
        Point_Concept B_Point
    >
    Sphere<Point_Real<A_Point>, Point_N<A_Point>::value> 
        boundingSphere(
            const A_Point& aPoint,
            const B_Point& bPoint)
    {
        return 
            {
                pointAsVector(aPoint) / 2 + pointAsVector(bPoint) / 2,
                norm(evaluate(pointAsVector(bPoint) - pointAsVector(aPoint))) / 2
            };
    }

    //! Finds a bounding sphere of a point set.
    template <PointSet_Concept PointSet>
    Sphere<PointSet_Real<PointSet>, PointSet_Dimension<PointSet>::value> 
        boundingSphere(const PointSet& pointSet)
    {
        using Real = PointSet_Real<PointSet>;
        static constexpr int N = 
            PointSet_Dimension<PointSet>::value;

        // This function does not give the minimum volume
        // bounding sphere, but it does give something to
        // that direction, and is fast.

        integer n = pointSetDimension(pointSet);

        Sphere<Real, N> result(n);
        if (isEmptyRange(pointSet))
        {
            result.setRadius(0);
            return result;
        }

        // Compute the midpoint.
        Vector<Real, N> midPoint = 
            pointMean(pointSet);

        // Compute the maximum distance from the midpoint.
        Real maxDistance2 = 0;
        for (auto&& point : pointSet)
        {
            Real currentDistance2 = dot(pointAsVector(point) - midPoint);
            if (currentDistance2 > maxDistance2)
            {
                maxDistance2 = currentDistance2;
            }
        }

        return Sphere<Real, N>(
            midPoint,
            std::sqrt(maxDistance2));
    }

}

#endif