/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2018 Danny Robson */ #pragma once #include "../debug/assert.hpp" #include "../extent.hpp" #include "../point.hpp" namespace cruft::geom { /////////////////////////////////////////////////////////////////////////// /// represents an axis-aligned bounding-box through two opposing corners. /// /// `lo' must be less-than-or-equal to `hi'. equality is allowed so that /// we can represent zero sized bounding-boxes. template struct aabb { using point_type = cruft::point; aabb () = default; aabb (point _lo, point _hi): lo (_lo), hi (_hi) { CHECK (all (lo <= hi)); } /////////////////////////////////////////////////////////////////////// /// Returns a copy of the AABB with all elements implicitly cast to the /// type `DestinationT`. template constexpr aabb cast (void) const { return { lo.template cast (), hi.template cast () }; } /////////////////////////////////////////////////////////////////////// extent magnitude (void) const { return (hi - lo).template as (); } ///-------------------------------------------------------------------- T diameter (void) const { return magnitude ().diameter (); } //--------------------------------------------------------------------- point centre (void) const { point res; for (std::size_t i = 0; i < S; ++i) res[i] = (lo[i] + hi[i]) / 2; return res; } ///-------------------------------------------------------------------- /// tests whether a point lies within the region, inclusive of borders constexpr bool inclusive (point p) const noexcept { return all (lo <= p && hi >= p); } ///-------------------------------------------------------------------- /// Find's the closest point on the AABB border to the supplied point. point closest (point query) const { return clamp (query, lo, hi); } ///-------------------------------------------------------------------- /// Modifies the AABB to cover the supplied point inclusively. void cover (point p) { lo = min (p, lo); hi = max (p, hi); } /////////////////////////////////////////////////////////////////////// /// Applies a negative offset to lo, and a positive offset to hi, and /// returns the result. /// /// The offset applied is identical for lo and hi, so one may need to /// consider halving the supplied magnitude depending on the use case. aabb expand [[nodiscard]] (T mag) const { return { lo - mag, hi + mag }; } /////////////////////////////////////////////////////////////////////// /// Adds a constant vector to both the lo and hi points. aabb operator+ (vector v) const { return { lo + v, hi + v }; } ///-------------------------------------------------------------------- /// Substracts a constant vector from both the lo and hi points. aabb operator- (vector v) const { return { lo - v, hi - v }; } /////////////////////////////////////////////////////////////////////// /// Returns an aabb that covers the supplied point in addition to the /// current aabb area. auto operator| [[nodiscard]] (point p) const noexcept { return aabb ( cruft::min (lo, p), cruft::max (hi, p) ); } ///-------------------------------------------------------------------- /// Modifies the AABB to cover the supplied point inclusively. auto& operator|= (point p) noexcept { return *this = *this | p; } ///-------------------------------------------------------------------- /// Returns an AABB that covers this AABB and the supplied AABB. aabb operator| [[nodiscard]] (aabb rhs) const noexcept { return { min (lo, rhs.lo), max (hi, rhs.hi) }; } ///-------------------------------------------------------------------- /// Returns a read only list of vertices for the AABB. std::array,cruft::pow(2,S)> vertices (void) const noexcept; /////////////////////////////////////////////////////////////////////// /// The most negative corner of the AABB. ::cruft::point lo; /// The most positive corner of the AABB. ::cruft::point hi; }; /////////////////////////////////////////////////////////////////////////// template constexpr bool operator== (const aabb &a, const aabb &b) noexcept { return a.lo == b.lo && a.hi == b.hi; } /////////////////////////////////////////////////////////////////////////// typedef aabb<2,float> aabb2f; typedef aabb<2,unsigned> aabb2u; typedef aabb<2,int> aabb2i; typedef aabb<3,float> aabb3f; typedef aabb<3,unsigned> aabb3u; typedef aabb<3,int> aabb3i; template bool intersects (aabb const &a, point const &b) noexcept { return a.inclusive (b); } /////////////////////////////////////////////////////////////////////////// /// Returns the squared minimum distance from the AABB to a point. template T distance2 (aabb a, point b); //------------------------------------------------------------------------- template T distance2 (point a, aabb b) { return distance2 (b, a); } } /////////////////////////////////////////////////////////////////////////////// #include "sample/fwd.hpp" #include namespace cruft::geom::sample { template class volume> { public: using shape_type = aabb; volume (shape_type&&); volume (shape_type const &target): m_target (target) { ; } template auto eval (GeneratorT &&g) const noexcept { point res; for (size_t i = 0; i < S; ++i) res[i] = cruft::random::uniform (m_target.lo[i], m_target.hi[i], g); return res; } private: shape_type const &m_target; }; }