From 45b3425f400f5079df3a7744f6de8b8aac0bf469 Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Wed, 9 Oct 2024 09:30:01 -0400 Subject: [PATCH 1/4] Move centroid() and equals() out of Ray --- src/geometry/ArborX_Ray.hpp | 14 -------------- src/geometry/algorithms/ArborX_Centroid.hpp | 6 ++++++ src/geometry/algorithms/ArborX_Equals.hpp | 11 +++++++++++ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/geometry/ArborX_Ray.hpp b/src/geometry/ArborX_Ray.hpp index fcb660890..fb0c80b95 100644 --- a/src/geometry/ArborX_Ray.hpp +++ b/src/geometry/ArborX_Ray.hpp @@ -67,20 +67,6 @@ struct Ray constexpr Vector const &direction() const { return _direction; } }; -template -KOKKOS_INLINE_FUNCTION constexpr bool equals(Ray const &l, - Ray const &r) -{ - using ArborX::Details::equals; - return equals(l.origin(), r.origin()) && l.direction() == r.direction(); -} - -template -KOKKOS_INLINE_FUNCTION auto returnCentroid(Ray const &ray) -{ - return ray.origin(); -} - // The ray-box intersection algorithm is based on [1]. Their 'efficient slag' // algorithm checks the intersections both in front and behind the ray. // diff --git a/src/geometry/algorithms/ArborX_Centroid.hpp b/src/geometry/algorithms/ArborX_Centroid.hpp index 2a57f5cf7..f6c2c89f6 100644 --- a/src/geometry/algorithms/ArborX_Centroid.hpp +++ b/src/geometry/algorithms/ArborX_Centroid.hpp @@ -133,6 +133,12 @@ struct centroid } }; +template +struct centroid +{ + KOKKOS_FUNCTION static auto apply(Ray const &ray) { return ray.origin(); } +}; + } // namespace Dispatch } // namespace ArborX::Details diff --git a/src/geometry/algorithms/ArborX_Equals.hpp b/src/geometry/algorithms/ArborX_Equals.hpp index 536f38d73..fb74a951c 100644 --- a/src/geometry/algorithms/ArborX_Equals.hpp +++ b/src/geometry/algorithms/ArborX_Equals.hpp @@ -72,6 +72,17 @@ struct equals } }; +// equals sphere-sphere +template +struct equals +{ + KOKKOS_FUNCTION static constexpr bool apply(Ray const &l, Ray const &r) + { + return Details::equals(l.centroid(), r.centroid()) && + l.direction() == r.direction(); + } +}; + } // namespace Dispatch } // namespace ArborX::Details From 3abadc12517c021c8660af1c6ba0707d2750d93c Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Thu, 27 Aug 2026 17:15:24 -0400 Subject: [PATCH 2/4] Move intersects() out of Ray --- src/geometry/ArborX_Ray.hpp | 20 -- src/geometry/algorithms/ArborX_Intersects.hpp | 31 +++ test/tstGeometryIntersects.cpp | 207 ++++++++++++++++++ test/tstRay.cpp | 205 +---------------- 4 files changed, 239 insertions(+), 224 deletions(-) diff --git a/src/geometry/ArborX_Ray.hpp b/src/geometry/ArborX_Ray.hpp index fb0c80b95..8c56066da 100644 --- a/src/geometry/ArborX_Ray.hpp +++ b/src/geometry/ArborX_Ray.hpp @@ -142,16 +142,6 @@ KOKKOS_INLINE_FUNCTION bool intersection(Ray const &ray, return (tmin <= tmax); } -template -KOKKOS_INLINE_FUNCTION bool intersects(Ray const &ray, - Box<3, Coordinate> const &box) -{ - Coordinate tmin; - Coordinate tmax; - // intersects only if box is in front of the ray - return intersection(ray, box, tmin, tmax) && (tmax >= 0); -} - // The function returns the index of the largest // component of the direction vector. template @@ -402,16 +392,6 @@ intersection(Ray const &ray, return false; } // namespace Experimental -template -KOKKOS_INLINE_FUNCTION bool intersects(Ray const &ray, - Triangle<3, Coordinate> const &triangle) -{ - Coordinate tmin; - Coordinate tmax; - // intersects only if triangle is in front of the ray - return intersection(ray, triangle, tmin, tmax) && (tmax >= 0); -} - // Returns the first positive value for t such that ray.origin + t * direction // intersects the given box. If no such value exists, returns inf. // Note that this definiton is different from the standard diff --git a/src/geometry/algorithms/ArborX_Intersects.hpp b/src/geometry/algorithms/ArborX_Intersects.hpp index 825add2af..2798c9c17 100644 --- a/src/geometry/algorithms/ArborX_Intersects.hpp +++ b/src/geometry/algorithms/ArborX_Intersects.hpp @@ -504,6 +504,37 @@ struct intersects } }; +template +struct intersects +{ + KOKKOS_FUNCTION static constexpr bool apply(Ray const &ray, Box const &box) + { + static_assert(GeometryTraits::dimension_v == 3); + using Coordinate = GeometryTraits::coordinate_type_t; + + Coordinate tmin; + Coordinate tmax; + // intersects only if box is in front of the ray + return intersection(ray, box, tmin, tmax) && (tmax >= 0); + } +}; + +template +struct intersects +{ + KOKKOS_FUNCTION static constexpr bool apply(Ray const &ray, + Triangle const &triangle) + { + static_assert(GeometryTraits::dimension_v == 3); + using Coordinate = GeometryTraits::coordinate_type_t; + + Coordinate tmin; + Coordinate tmax; + // intersects only if triangle is in front of the ray + return intersection(ray, triangle, tmin, tmax) && (tmax >= 0); + } +}; + namespace { // Computes x^t R y diff --git a/test/tstGeometryIntersects.cpp b/test/tstGeometryIntersects.cpp index 89e14e3aa..3de961352 100644 --- a/test/tstGeometryIntersects.cpp +++ b/test/tstGeometryIntersects.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -570,3 +571,209 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(intersects_point_kdop, KDOP_t, KDOP_3D_types) BOOST_TEST(!sym_intersects(Point{1, 2, 3}, x)); } } + +BOOST_AUTO_TEST_CASE_TEMPLATE(intersects_ray_box, Coordinate, CoordinatesList) +{ + using Ray = ArborX::Experimental::Ray; + using Box = ArborX::Box<3, Coordinate>; + + constexpr Box unit_box{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}; + + // origin is within the box + BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, .5}, {0, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, .5}, {0, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 1, 1}}, unit_box)); + + // origin is outside the box + // hit the center of the face + BOOST_TEST(intersects(Ray{{-1, .5, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, .5, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, .5, .5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, .5, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, .5, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, .5, .5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, 1.5, .5}, {1, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1.5, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, 1.5, 1.5}, {1, -1, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, 0, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, -.5, .5}, {-1, 1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, -.5, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, -.5, 1.5}, {-1, 1, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 0, -1}}, unit_box)); + + // hit the center of an edge + BOOST_TEST(intersects(Ray{{-1, 0, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 0, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 0, .5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, 0, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, 0, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, 0, .5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, -1, .5}, {1, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, 1, .5}, {1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, -2, .5}, {1, 2, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, 2, .5}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, -1, .5}, {-1, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, 1, .5}, {-1, -1, 0}}, unit_box)); + + // hit a corner + BOOST_TEST(intersects(Ray{{-0.5, 1.5, 1.5}, {1, -1, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1, 1}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{-1, 1, 1}, {0, 1, 1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, 1, 1}, {1, 0, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{2, 1, 1}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{-1, -1, -1}, {1, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{2, 2, 2}, {-1, -1, -1}}, unit_box)); + + BOOST_TEST(!intersects(Ray{{1, 2, 3}, {4, 5, 6}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -2, -3}}, unit_box)); + + // origin is on the box (no 0*inf). + BOOST_TEST(intersects(Ray{{0, 0, 0}, {1, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, -1, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {-1, -1, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 1, 1}}, unit_box)); + + BOOST_TEST(intersects(Ray{{1, .5, .5}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, .5, .5}, {1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, 1, .5}, {0, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, 1, .5}, {0, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, 1}, {0, 0, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{.5, .5, 1}, {0, 0, 1}}, unit_box)); + + BOOST_TEST(intersects(Ray{{0, 0, .5}, {1, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, .5}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, .5}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, .5}, {1, 1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{0, 0.5, 0}, {-1, -2, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{0.5, 0, 0.5}, {2, 0, -1}}, unit_box)); + + // origin is on the box (with 0*inf). + BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, 1, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 0, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, -1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, -1, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, 0, -1}}, unit_box)); + + BOOST_TEST(intersects(Ray{{0, 1, 1}, {0, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 0, 1}, {1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1, 0}, {0, 1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{0, 0, 1}, {-1, 0, -1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 0, 1}, {0, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 0, 0}, {0, 1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 0, 0}, {-1, 0, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 1, 0}, {0, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 1, 0}, {0, 0, -1}}, unit_box)); + + // more cases with 0*inf: + BOOST_TEST(intersects(Ray{{0, 1.5, 1.5}, {0, -1, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{0, 1.5, 1.5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 0, 1.5}, {-1, 0, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 0, 1.5}, {1, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 1.5, 0}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 1.5, 0}, {1, 1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{1, 1.5, 1.5}, {0, -1, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1, 1.5, 1.5}, {0, 1, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 1, 1.5}, {-1, 0, -1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 1, 1.5}, {1, 0, 1}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 1.5, 1}, {-1, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 1.5, 1}, {1, 1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{1.5, 0, 0}, {-1, 0, 2}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 0, 0}, {-1, 2, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 0, 0}, {-1, 0, 2.1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 0, 0}, {-1, 2.1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 1, 1}, {-1, 0, -2}}, unit_box)); + BOOST_TEST(intersects(Ray{{1.5, 1, 1}, {-1, -2, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 1, 1}, {-1, 0, -2.1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1.5, 1, 1}, {-1, -2.1, 0}}, unit_box)); + + BOOST_TEST(intersects(Ray{{0, 1.5, 0}, {0, -1, 2}}, unit_box)); + BOOST_TEST(intersects(Ray{{0, 1.5, 0}, {2, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{0, 1.5, 0}, {0, -1, 2.1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{0, 1.5, 0}, {2.1, -1, 0}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1.5, 1}, {0, -1, -2}}, unit_box)); + BOOST_TEST(intersects(Ray{{1, 1.5, 1}, {-2, -1, 0}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1, 1.5, 1}, {0, -1, -2.1}}, unit_box)); + BOOST_TEST(!intersects(Ray{{1, 1.5, 1}, {-2.1, -1, 0}}, unit_box)); +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(intersects_ray_triangle, Coordinate, + CoordinatesList) +{ + using Ray = ArborX::Experimental::Ray; + using Triangle = ArborX::Triangle<3, Coordinate>; + + constexpr Triangle unit_triangle{ + {0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}}; + + BOOST_TEST(intersects(Ray{{.1, .2, .3}, {0, 0, -1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1.1, 1.2, 1}, {-1, -1, -1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{-1.9, 3.2, -1}, {2, -3, 1}}, unit_triangle)); + BOOST_TEST(!intersects(Ray{{1, 2, 3}, {1, 1, 0}}, unit_triangle)); + BOOST_TEST(!intersects(Ray{{1, 2, 3}, {1, 0, 0}}, unit_triangle)); + BOOST_TEST(!intersects(Ray{{1, 2, 3}, {0, 1, 0}}, unit_triangle)); + + // ray origin on the triangle + BOOST_TEST(intersects(Ray{{.1, .2, 0}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{.1, .2, 0}, {0, 0, -1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{.1, .2, 0}, {1, 2, 3}}, unit_triangle)); + + // ray directed away from the triangle + BOOST_TEST(!intersects(Ray{{.1, .2, .3}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(!intersects(Ray{{1.0, 1.0, 0.0}, {0, 1, 0}}, unit_triangle)); + + // ray in the same plane as the triangle + BOOST_TEST(intersects(Ray{{.3, .3, 0}, {1, 1, 0}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{-0.1, 0, 0}, {1, 0, 0}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{0.1, -0.2, 0}, {0, 1, 0}}, unit_triangle)); + BOOST_TEST(!intersects(Ray{{-1, -1, 0}, {0, 1, 0}}, unit_triangle)); + + BOOST_TEST(intersects(Ray{{1.0, 0.0, 0.0}, {-1, 1, 0}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1.0, 0.0, 0.0}, {1, 2, 3}}, unit_triangle)); + + // ray misses the triangle + BOOST_TEST(!intersects(Ray{{-1, 2, -3}, {0, 0, 1}}, unit_triangle)); + + // ray hits vertices + BOOST_TEST(intersects(Ray{{0, 0, -1}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1, 0, -2}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{0, 1, -3}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -2, -3}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1, 2, 3}, {0, -2, -3}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -1, -3}}, unit_triangle)); + + // ray hits edges + BOOST_TEST(intersects(Ray{{.1, 0, -1}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{0, .2, -2}, {0, 0, 1}}, unit_triangle)); + BOOST_TEST(intersects(Ray{{.5, .5, -3}, {0, 0, 1}}, unit_triangle)); + + // ray in a plane parallel to the triangle + BOOST_TEST(!intersects(Ray{{-0.1, 0, 1}, {1, 0, 0}}, unit_triangle)); + + constexpr Triangle tilted_triangle{ + {0.f, 0.f, 0.f}, {2.f, 0.f, 1.f}, {0.f, 2.f, 1.f}}; + + // ray in the same plane as the triangle + BOOST_TEST(!intersects(Ray{{10, 0, 0}, {1, 1, 1}}, tilted_triangle)); + BOOST_TEST(intersects(Ray{{3, 3, 3}, {-1, -1, -1}}, tilted_triangle)); + + // ray in a plane parallel to the triangle + BOOST_TEST(!intersects(Ray{{0., 0., 0.1}, {1, 1, 1}}, tilted_triangle)); +} diff --git a/test/tstRay.cpp b/test/tstRay.cpp index 1c0d18900..20e414a50 100644 --- a/test/tstRay.cpp +++ b/test/tstRay.cpp @@ -11,150 +11,10 @@ #include #include #include +#include #include -BOOST_AUTO_TEST_CASE(intersects_box) -{ - using ArborX::Experimental::Ray; - - constexpr ArborX::Box unit_box{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}; - - // origin is within the box - BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, .5}, {0, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, .5}, {0, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, .5}, {1, 1, 1}}, unit_box)); - - // origin is outside the box - // hit the center of the face - BOOST_TEST(intersects(Ray{{-1, .5, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, .5, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, .5, .5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, .5, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, .5, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, .5, .5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, 1.5, .5}, {1, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1.5, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, 1.5, 1.5}, {1, -1, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1.5, 1.5}, {1, 0, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, -.5, .5}, {-1, 1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, -.5, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, -.5, 1.5}, {-1, 1, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, -.5, 1.5}, {-1, 0, -1}}, unit_box)); - - // hit the center of an edge - BOOST_TEST(intersects(Ray{{-1, 0, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 0, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 0, .5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, 0, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, 0, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, 0, .5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, -1, .5}, {1, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, 1, .5}, {1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, -2, .5}, {1, 2, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, 2, .5}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, -1, .5}, {-1, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, 1, .5}, {-1, -1, 0}}, unit_box)); - - // hit a corner - BOOST_TEST(intersects(Ray{{-0.5, 1.5, 1.5}, {1, -1, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1, 1}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{-1, 1, 1}, {0, 1, 1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, 1, 1}, {1, 0, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{2, 1, 1}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{-1, -1, -1}, {1, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{2, 2, 2}, {-1, -1, -1}}, unit_box)); - - BOOST_TEST(!intersects(Ray{{1, 2, 3}, {4, 5, 6}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -2, -3}}, unit_box)); - - // origin is on the box (no 0*inf). - BOOST_TEST(intersects(Ray{{0, 0, 0}, {1, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, -1, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {-1, -1, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 1, 1}}, unit_box)); - - BOOST_TEST(intersects(Ray{{1, .5, .5}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, .5, .5}, {1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, 1, .5}, {0, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, 1, .5}, {0, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, 1}, {0, 0, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{.5, .5, 1}, {0, 0, 1}}, unit_box)); - - BOOST_TEST(intersects(Ray{{0, 0, .5}, {1, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, .5}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, .5}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, .5}, {1, 1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{0, 0.5, 0}, {-1, -2, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{0.5, 0, 0.5}, {2, 0, -1}}, unit_box)); - - // origin is on the box (with 0*inf). - BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, 1, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 0, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 0}, {0, -1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, -1, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 1}, {0, 0, -1}}, unit_box)); - - BOOST_TEST(intersects(Ray{{0, 1, 1}, {0, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 0, 1}, {1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1, 0}, {0, 1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{0, 0, 1}, {-1, 0, -1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 0, 1}, {0, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 0, 0}, {0, 1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 0, 0}, {-1, 0, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 1, 0}, {0, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 1, 0}, {0, 0, -1}}, unit_box)); - - // more cases with 0*inf: - BOOST_TEST(intersects(Ray{{0, 1.5, 1.5}, {0, -1, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{0, 1.5, 1.5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 0, 1.5}, {-1, 0, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 0, 1.5}, {1, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 1.5, 0}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 1.5, 0}, {1, 1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{1, 1.5, 1.5}, {0, -1, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1, 1.5, 1.5}, {0, 1, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 1, 1.5}, {-1, 0, -1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 1, 1.5}, {1, 0, 1}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 1.5, 1}, {-1, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 1.5, 1}, {1, 1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{1.5, 0, 0}, {-1, 0, 2}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 0, 0}, {-1, 2, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 0, 0}, {-1, 0, 2.1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 0, 0}, {-1, 2.1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 1, 1}, {-1, 0, -2}}, unit_box)); - BOOST_TEST(intersects(Ray{{1.5, 1, 1}, {-1, -2, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 1, 1}, {-1, 0, -2.1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1.5, 1, 1}, {-1, -2.1, 0}}, unit_box)); - - BOOST_TEST(intersects(Ray{{0, 1.5, 0}, {0, -1, 2}}, unit_box)); - BOOST_TEST(intersects(Ray{{0, 1.5, 0}, {2, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{0, 1.5, 0}, {0, -1, 2.1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{0, 1.5, 0}, {2.1, -1, 0}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1.5, 1}, {0, -1, -2}}, unit_box)); - BOOST_TEST(intersects(Ray{{1, 1.5, 1}, {-2, -1, 0}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1, 1.5, 1}, {0, -1, -2.1}}, unit_box)); - BOOST_TEST(!intersects(Ray{{1, 1.5, 1}, {-2.1, -1, 0}}, unit_box)); -} - #define ARBORX_TEST_RAY_BOX_INTERSECTION(ray, box, t0_ref, t1_ref) \ do \ { \ @@ -405,69 +265,6 @@ BOOST_AUTO_TEST_CASE(ray_sphere_intersection, #undef ARBORX_TEST_RAY_SPHERE_INTERSECTION #undef ARBORX_TEST_RAY_SPHERE_NO_INTERSECTION -BOOST_AUTO_TEST_CASE(intersects_triangle) -{ - using ArborX::Point; - using ArborX::Triangle; - using ArborX::Experimental::Ray; - constexpr Triangle unit_triangle{ - {0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}}; - - BOOST_TEST(intersects(Ray{{.1, .2, .3}, {0, 0, -1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1.1, 1.2, 1}, {-1, -1, -1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{-1.9, 3.2, -1}, {2, -3, 1}}, unit_triangle)); - BOOST_TEST(!intersects(Ray{{1, 2, 3}, {1, 1, 0}}, unit_triangle)); - BOOST_TEST(!intersects(Ray{{1, 2, 3}, {1, 0, 0}}, unit_triangle)); - BOOST_TEST(!intersects(Ray{{1, 2, 3}, {0, 1, 0}}, unit_triangle)); - - // ray origin on the triangle - BOOST_TEST(intersects(Ray{{.1, .2, 0}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{.1, .2, 0}, {0, 0, -1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{.1, .2, 0}, {1, 2, 3}}, unit_triangle)); - - // ray directed away from the triangle - BOOST_TEST(!intersects(Ray{{.1, .2, .3}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(!intersects(Ray{{1.0, 1.0, 0.0}, {0, 1, 0}}, unit_triangle)); - - // ray in the same plane as the triangle - BOOST_TEST(intersects(Ray{{.3, .3, 0}, {1, 1, 0}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{-0.1, 0, 0}, {1, 0, 0}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{0.1, -0.2, 0}, {0, 1, 0}}, unit_triangle)); - BOOST_TEST(!intersects(Ray{{-1, -1, 0}, {0, 1, 0}}, unit_triangle)); - - BOOST_TEST(intersects(Ray{{1.0, 0.0, 0.0}, {-1, 1, 0}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1.0, 0.0, 0.0}, {1, 2, 3}}, unit_triangle)); - - // ray misses the triangle - BOOST_TEST(!intersects(Ray{{-1, 2, -3}, {0, 0, 1}}, unit_triangle)); - - // ray hits vertices - BOOST_TEST(intersects(Ray{{0, 0, -1}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1, 0, -2}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{0, 1, -3}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -2, -3}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1, 2, 3}, {0, -2, -3}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{1, 2, 3}, {-1, -1, -3}}, unit_triangle)); - - // ray hits edges - BOOST_TEST(intersects(Ray{{.1, 0, -1}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{0, .2, -2}, {0, 0, 1}}, unit_triangle)); - BOOST_TEST(intersects(Ray{{.5, .5, -3}, {0, 0, 1}}, unit_triangle)); - - // ray in a plane parallel to the triangle - BOOST_TEST(!intersects(Ray{{-0.1, 0, 1}, {1, 0, 0}}, unit_triangle)); - - constexpr Triangle tilted_triangle{ - {0.f, 0.f, 0.f}, {2.f, 0.f, 1.f}, {0.f, 2.f, 1.f}}; - - // ray in the same plane as the triangle - BOOST_TEST(!intersects(Ray{{10, 0, 0}, {1, 1, 1}}, tilted_triangle)); - BOOST_TEST(intersects(Ray{{3, 3, 3}, {-1, -1, -1}}, tilted_triangle)); - - // ray in a plane parallel to the triangle - BOOST_TEST(!intersects(Ray{{0., 0., 0.1}, {1, 1, 1}}, tilted_triangle)); -} - #define ARBORX_TEST_RAY_TRIANGLE_INTERSECTION(ray, triangle, t0_ref, t1_ref) \ do \ { \ From 123dac6c7c69138c07ec54fd43ac8dd6bfedda9d Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Thu, 27 Aug 2026 17:32:15 -0400 Subject: [PATCH 3/4] Move distance() out of Ray --- src/geometry/ArborX_Ray.hpp | 17 -------------- src/geometry/algorithms/ArborX_Distance.hpp | 22 +++++++++++++++++ test/tstGeometryDistance.cpp | 26 +++++++++++++++++++++ test/tstRay.cpp | 23 ------------------ 4 files changed, 48 insertions(+), 40 deletions(-) diff --git a/src/geometry/ArborX_Ray.hpp b/src/geometry/ArborX_Ray.hpp index 8c56066da..a1b3ce5c4 100644 --- a/src/geometry/ArborX_Ray.hpp +++ b/src/geometry/ArborX_Ray.hpp @@ -392,23 +392,6 @@ intersection(Ray const &ray, return false; } // namespace Experimental -// Returns the first positive value for t such that ray.origin + t * direction -// intersects the given box. If no such value exists, returns inf. -// Note that this definiton is different from the standard -// "smallest distance between a point on the ray and a point in the box" -// so we can use nearest queries for ray tracing. -template -KOKKOS_INLINE_FUNCTION auto distance(Ray const &ray, - Box<3, Coordinate> const &box) -{ - Coordinate tmin; - Coordinate tmax; - bool intersects = intersection(ray, box, tmin, tmax) && (tmax >= 0); - return intersects ? Kokkos::max(tmin, (Coordinate)0) - : Details::KokkosExt::ArithmeticTraits::infinity< - Coordinate>::value; -} - // Solves a*x^2 + b*x + c = 0. // If a solution exists, return true and stores roots at x1, x2. // If a solution does not exist, returns false. diff --git a/src/geometry/algorithms/ArborX_Distance.hpp b/src/geometry/algorithms/ArborX_Distance.hpp index 2bca424e3..6929ab436 100644 --- a/src/geometry/algorithms/ArborX_Distance.hpp +++ b/src/geometry/algorithms/ArborX_Distance.hpp @@ -218,6 +218,28 @@ struct distance } }; +template +struct distance +{ + // Returns the first positive value for t such that ray.origin + t * direction + // intersects the given box. If no such value exists, returns inf. + // Note that this definiton is different from the standard + // "smallest distance between a point on the ray and a point in the box" + // so we can use nearest queries for ray tracing. + KOKKOS_FUNCTION static auto apply(Ray const &ray, Box const &box) + { + static_assert(GeometryTraits::dimension_v == 3); + using Coordinate = GeometryTraits::coordinate_type_t; + + Coordinate tmin; + Coordinate tmax; + bool intersects = intersection(ray, box, tmin, tmax) && (tmax >= 0); + return intersects ? Kokkos::max(tmin, (Coordinate)0) + : Details::KokkosExt::ArithmeticTraits::infinity< + Coordinate>::value; + } +}; + } // namespace Details::Dispatch } // namespace ArborX diff --git a/test/tstGeometryDistance.cpp b/test/tstGeometryDistance.cpp index 9a3d6f28d..e3b2b0788 100644 --- a/test/tstGeometryDistance.cpp +++ b/test/tstGeometryDistance.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -292,3 +293,28 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(distance_sphere_sphere, Coordinate, BOOST_TEST(sym_distance(Sphere{{-1, -1}, 0.5}, Sphere{{1, -1}, 0.5}) == 1.0); BOOST_TEST(sym_distance(Sphere{{-1, 1}, 1}, Sphere{{2, -3}, 1}) == 3); } + +BOOST_AUTO_TEST_CASE_TEMPLATE(distance_ray_box, Coordinate, CoordinatesList) +{ + using Ray = ArborX::Experimental::Ray; + using Box = ArborX::Box<3, Coordinate>; + + // use const instead of constexpr because MSVC shows error(error:expression + // must have a constant value) + constexpr Box unit_box{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}; + + namespace KokkosExt = ArborX::Details::KokkosExt; +#ifdef _MSC_VER + auto const inf = KokkosExt::ArithmeticTraits::infinity::value; +#else + constexpr auto inf = KokkosExt::ArithmeticTraits::infinity::value; +#endif + + // clang-format off + // origin is within the box + BOOST_TEST(distance(Ray{{.5, .5, .5}, {1, 0, 0}}, unit_box) == 0.f); + // origin outside box, ray hitting box + BOOST_TEST(distance(Ray{{.5, .5, -.5}, {0, 0, 1}}, unit_box) == .5f); + // origin outside box, ray missing box + BOOST_TEST(distance(Ray{{.5, .5, -.5}, {0, 0, -1}}, unit_box) == inf); +} diff --git a/test/tstRay.cpp b/test/tstRay.cpp index 20e414a50..8534d2ea7 100644 --- a/test/tstRay.cpp +++ b/test/tstRay.cpp @@ -109,29 +109,6 @@ BOOST_AUTO_TEST_CASE(ray_box_intersection, *boost::unit_test::tolerance(1e-6f)) #undef ARBORX_TEST_RAY_BOX_INTERSECTION #undef ARBORX_TEST_RAY_BOX_NO_INTERSECTION -BOOST_AUTO_TEST_CASE(ray_box_distance) -{ - using ArborX::Experimental::Ray; - // use const instead of constexpr because MSVC shows error(error:expression - // must have a constant value) - constexpr ArborX::Box unit_box{{0.f, 0.f, 0.f}, {1.f, 1.f, 1.f}}; - - namespace KokkosExt = ArborX::Details::KokkosExt; -#ifdef _MSC_VER - auto const inf = KokkosExt::ArithmeticTraits::infinity::value; -#else - constexpr auto inf = KokkosExt::ArithmeticTraits::infinity::value; -#endif - - // clang-format off - // origin is within the box - BOOST_TEST(distance(Ray{{.5, .5, .5}, {1, 0, 0}}, unit_box) == 0.f); - // origin outside box, ray hitting box - BOOST_TEST(distance(Ray{{.5, .5, -.5}, {0, 0, 1}}, unit_box) == .5f); - // origin outside box, ray missing box - BOOST_TEST(distance(Ray{{.5, .5, -.5}, {0, 0, -1}}, unit_box) == inf); -} - // NOTE until boost 1.70 need to cast both operands when comparing floating // points BOOST_AUTO_TEST_CASE(overlap_distance_sphere, From 083753e09bea69a15dd205c3ab35ee0a49952f4e Mon Sep 17 00:00:00 2001 From: Andrey Prokopenko Date: Thu, 27 Aug 2026 17:34:27 -0400 Subject: [PATCH 4/4] Move Ray's GeometryTraits up --- src/geometry/ArborX_Ray.hpp | 39 +++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/src/geometry/ArborX_Ray.hpp b/src/geometry/ArborX_Ray.hpp index a1b3ce5c4..1ec8bf313 100644 --- a/src/geometry/ArborX_Ray.hpp +++ b/src/geometry/ArborX_Ray.hpp @@ -67,6 +67,28 @@ struct Ray constexpr Vector const &direction() const { return _direction; } }; +} // namespace ArborX::Experimental + +template +struct ArborX::GeometryTraits::dimension> +{ + static constexpr int value = 3; +}; +template +struct ArborX::GeometryTraits::tag> +{ + using type = RayTag; +}; +template +struct ArborX::GeometryTraits::coordinate_type< + ArborX::Experimental::Ray> +{ + using type = Coordinate; +}; + +namespace ArborX::Experimental +{ + // The ray-box intersection algorithm is based on [1]. Their 'efficient slag' // algorithm checks the intersections both in front and behind the ray. // @@ -509,21 +531,4 @@ KOKKOS_INLINE_FUNCTION auto overlapDistance(Ray const &ray, } // namespace ArborX::Experimental -template -struct ArborX::GeometryTraits::dimension> -{ - static constexpr int value = 3; -}; -template -struct ArborX::GeometryTraits::tag> -{ - using type = RayTag; -}; -template -struct ArborX::GeometryTraits::coordinate_type< - ArborX::Experimental::Ray> -{ - using type = Coordinate; -}; - #endif