Skip to content

Commit

Permalink
Add bounding box utilities for output and upcoming ORANGE work (#1092)
Browse files Browse the repository at this point in the history
* Add bbox encloses

* Move host/device bbox utilities to BoundingBox

* Add iostream to bounding box utils
  • Loading branch information
sethrj committed Jan 29, 2024
1 parent ff984ca commit 5742b0c
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 38 deletions.
17 changes: 17 additions & 0 deletions src/orange/BoundingBox.hh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "corecel/Assert.hh"
#include "corecel/Macros.hh"
#include "corecel/Types.hh"
#include "corecel/cont/Array.hh"
#include "corecel/math/Algorithms.hh"
#include "corecel/math/NumericLimits.hh"
Expand Down Expand Up @@ -118,6 +119,22 @@ operator!=(BoundingBox<T> const& lhs, BoundingBox<T> const& rhs)
return !(lhs == rhs);
}

//---------------------------------------------------------------------------//
/*!
* Determine if a point is contained in a bounding box.
*
* No point is ever contained in a null bounding box. A degenerate bounding
* box will return "true" for any point on its face.
*/
template<class T, class U>
CELER_CONSTEXPR_FUNCTION bool
is_inside(BoundingBox<T> const& bbox, Array<U, 3> const& point)
{
return bbox.lower()[0] <= point[0] && point[0] <= bbox.upper()[0]
&& bbox.lower()[1] <= point[1] && point[1] <= bbox.upper()[1]
&& bbox.lower()[2] <= point[2] && point[2] <= bbox.upper()[2];
}

//---------------------------------------------------------------------------//
// INLINE DEFINITIONS
//---------------------------------------------------------------------------//
Expand Down
22 changes: 22 additions & 0 deletions src/orange/BoundingBoxUtils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
//---------------------------------------------------------------------------//
#include "BoundingBoxUtils.hh"

#include <iostream>

#include "corecel/Assert.hh"
#include "corecel/cont/ArrayIO.hh"
#include "corecel/math/ArrayOperators.hh"
#include "corecel/math/NumericLimits.hh"

Expand Down Expand Up @@ -99,5 +102,24 @@ BBox calc_transform(Transformation const& tr, BBox const& a)
return result;
}

//---------------------------------------------------------------------------//
/*!
* Write a bounding box to a stream.
*/
template<class T>
std::ostream& operator<<(std::ostream& os, BoundingBox<T> const& bbox)
{
os << '{';
if (bbox)
{
os << bbox.lower() << ", " << bbox.upper();
}
os << '}';
return os;
}

template std::ostream& operator<<(std::ostream&, BoundingBox<float> const&);
template std::ostream& operator<<(std::ostream&, BoundingBox<double> const&);

//---------------------------------------------------------------------------//
} // namespace celeritas
45 changes: 25 additions & 20 deletions src/orange/BoundingBoxUtils.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/BoundingBoxUtils.hh
//! \brief Host-only utilities for bounding boxes
//---------------------------------------------------------------------------//
#pragma once

#include <cmath>
#include <iosfwd>

#include "corecel/cont/Range.hh"
#include "corecel/math/Algorithms.hh"
Expand All @@ -17,29 +19,10 @@

namespace celeritas
{
//---------------------------------------------------------------------------//
class Translation;
class Transformation;
//---------------------------------------------------------------------------//
// Host/device functions
//---------------------------------------------------------------------------//
/*!
* Determine if a point is contained in a bounding box.
*
* No point is ever contained in a null bounding box. A degenerate bounding
* box will return "true" for any point on its face.
*/
template<class T, class U>
inline CELER_FUNCTION bool
is_inside(BoundingBox<T> const& bbox, Array<U, 3> point)
{
auto axes = range(to_int(Axis::size_));
return all_of(axes.begin(), axes.end(), [&point, &bbox](int ax) {
return point[ax] >= bbox.lower()[ax] && point[ax] <= bbox.upper()[ax];
});
}

//---------------------------------------------------------------------------//
// Host-only functions
//---------------------------------------------------------------------------//
/*!
* Check if a bounding box spans (-inf, inf) in every direction.
Expand Down Expand Up @@ -180,6 +163,24 @@ calc_intersection(BoundingBox<T> const& a, BoundingBox<T> const& b)
return BoundingBox<T>::from_unchecked(lower, upper);
}

//---------------------------------------------------------------------------//
/*!
* Check if all points inside the small bbox are in the big bbox.
*
* All bounding boxes should enclose a "null" bounding box (there are no points
* in the null box, so no points are outside the big box). The null bounding
* box will enclose nothing but a bounding box.
*/
template<class T>
inline bool encloses(BoundingBox<T> const& big, BoundingBox<T> const& small)
{
auto axes = range(to_int(Axis::size_));
return all_of(axes.begin(), axes.end(), [&big, &small](int ax) {
return big.lower()[ax] <= small.lower()[ax]
&& big.upper()[ax] >= small.upper()[ax];
});
}

//---------------------------------------------------------------------------//
/*!
* Bump a bounding box outward and possibly convert to another type.
Expand Down Expand Up @@ -249,5 +250,9 @@ BBox calc_transform(Translation const& tr, BBox const& a);

BBox calc_transform(Transformation const& tr, BBox const& a);

//---------------------------------------------------------------------------//
template<class T>
std::ostream& operator<<(std::ostream&, BoundingBox<T> const& bbox);

//---------------------------------------------------------------------------//
} // namespace celeritas
18 changes: 18 additions & 0 deletions test/orange/BoundingBox.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,24 @@ TEST_F(BoundingBoxTest, standard)
EXPECT_VEC_SOFT_EQ((Real3{2, 0, 6}), bb.upper());
}

TEST_F(BoundingBoxTest, is_inside)
{
BBox bbox1 = {{-5, -2, -100}, {6, 1, 1}};
EXPECT_TRUE(is_inside(bbox1, Real3{-4, 0, 0}));
EXPECT_TRUE(is_inside(bbox1, Real3{-4.9, -1.9, -99.9}));
EXPECT_FALSE(is_inside(bbox1, Real3{-6, 0, 0}));
EXPECT_FALSE(is_inside(bbox1, Real3{-5.1, -2.1, -101.1}));
EXPECT_FALSE(is_inside(BBox{}, Real3{0, 0, 0}));

BBox degenerate{{1, -2, -2}, {1, 2, 2}};
EXPECT_TRUE(is_inside(degenerate, Real3{1, 0, 0}));
EXPECT_FALSE(is_inside(degenerate, Real3{1, -3, 0}));
EXPECT_FALSE(is_inside(degenerate, Real3{1.000001, 0, 0}));

BBox super_degenerate{{1, 1, 1}, {1, 1, 1}};
EXPECT_TRUE(is_inside(degenerate, Real3{1, 1, 1}));
}

TEST_F(BoundingBoxTest, TEST_IF_CELERITAS_JSON(io))
{
using BoundingBoxT = BoundingBox<double>;
Expand Down
46 changes: 28 additions & 18 deletions test/orange/BoundingBoxUtils.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,6 @@ class BoundingBoxUtilsTest : public Test
{
};

TEST_F(BoundingBoxUtilsTest, is_inside)
{
BBox bbox1 = {{-5, -2, -100}, {6, 1, 1}};
EXPECT_TRUE(is_inside(bbox1, Real3{-4, 0, 0}));
EXPECT_TRUE(is_inside(bbox1, Real3{-4.9, -1.9, -99.9}));
EXPECT_FALSE(is_inside(bbox1, Real3{-6, 0, 0}));
EXPECT_FALSE(is_inside(bbox1, Real3{-5.1, -2.1, -101.1}));
EXPECT_FALSE(is_inside(BBox{}, Real3{0, 0, 0}));

BBox degenerate{{1, -2, -2}, {1, 2, 2}};
EXPECT_TRUE(is_inside(degenerate, Real3{1, 0, 0}));
EXPECT_FALSE(is_inside(degenerate, Real3{1, -3, 0}));
EXPECT_FALSE(is_inside(degenerate, Real3{1.000001, 0, 0}));

BBox super_degenerate{{1, 1, 1}, {1, 1, 1}};
EXPECT_TRUE(is_inside(degenerate, Real3{1, 1, 1}));
}

TEST_F(BoundingBoxUtilsTest, is_infinite)
{
BBox bbox1 = {{0, 0, 0}, {1, 1, 1}};
Expand Down Expand Up @@ -174,6 +156,20 @@ TEST_F(BoundingBoxUtilsTest, bbox_intersection)
}
}

TEST_F(BoundingBoxUtilsTest, bbox_encloses)
{
EXPECT_TRUE(encloses(BBox::from_infinite(), BBox{{-1, -1, -1}, {1, 1, 1}}));
EXPECT_TRUE(encloses(BBox{{-1, -2, -3}, {2, 2, 3}},
BBox{{-1, -1, -1}, {1, 1, 1}}));
EXPECT_FALSE(encloses(BBox{{-1, -2, -3}, {1, 1.5, 3}},
BBox{{-1, -2, -3}, {1, 2, 3}}));

EXPECT_FALSE(encloses(BBox{}, BBox{{-1, -2, -3}, {1, 2, 3}}));
EXPECT_TRUE(encloses(BBox{{-1, -2, -3}, {1, 2, 3}}, BBox{}));
EXPECT_TRUE(encloses(BBox{}, BBox{}));
EXPECT_TRUE(encloses(BBox::from_infinite(), BBox{}));
}

TEST_F(BoundingBoxUtilsTest, bumped)
{
BoundingBox<double> const ref{{-inf, 0, -100}, {0, 0.11223344556677, inf}};
Expand Down Expand Up @@ -283,6 +279,20 @@ TEST_F(BoundingBoxUtilsTest, bbox_transform)
}
}

TEST_F(BoundingBoxUtilsTest, stream)
{
{
std::ostringstream os;
os << BBox{};
EXPECT_EQ("{}", os.str());
}
{
std::ostringstream os;
os << BBox{{1, 2, 3}, {4, 5, 6}};
EXPECT_EQ("{{1,2,3}, {4,5,6}}", os.str());
}
}

//---------------------------------------------------------------------------//
} // namespace test
} // namespace celeritas

0 comments on commit 5742b0c

Please sign in to comment.