Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 17 additions & 63 deletions src/geometry/ArborX_Ray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,27 @@ struct Ray
constexpr Vector const &direction() const { return _direction; }
};

} // namespace ArborX::Experimental

template <typename Coordinate>
KOKKOS_INLINE_FUNCTION constexpr bool equals(Ray<Coordinate> const &l,
Ray<Coordinate> const &r)
struct ArborX::GeometryTraits::dimension<ArborX::Experimental::Ray<Coordinate>>
{
using ArborX::Details::equals;
return equals(l.origin(), r.origin()) && l.direction() == r.direction();
}

static constexpr int value = 3;
};
template <typename Coordinate>
KOKKOS_INLINE_FUNCTION auto returnCentroid(Ray<Coordinate> const &ray)
struct ArborX::GeometryTraits::tag<ArborX::Experimental::Ray<Coordinate>>
{
using type = RayTag;
};
template <typename Coordinate>
struct ArborX::GeometryTraits::coordinate_type<
ArborX::Experimental::Ray<Coordinate>>
{
using type = Coordinate;
};

namespace ArborX::Experimental
{
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.
Expand Down Expand Up @@ -156,16 +164,6 @@ KOKKOS_INLINE_FUNCTION bool intersection(Ray<Coordinate> const &ray,
return (tmin <= tmax);
}

template <typename Coordinate>
KOKKOS_INLINE_FUNCTION bool intersects(Ray<Coordinate> 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 <typename Coordinate>
Expand Down Expand Up @@ -416,33 +414,6 @@ intersection(Ray<Coordinate> const &ray,
return false;
} // namespace Experimental

template <typename Coordinate>
KOKKOS_INLINE_FUNCTION bool intersects(Ray<Coordinate> 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
// "smallest distance between a point on the ray and a point in the box"
// so we can use nearest queries for ray tracing.
template <typename Coordinate>
KOKKOS_INLINE_FUNCTION auto distance(Ray<Coordinate> 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.
Expand Down Expand Up @@ -560,21 +531,4 @@ KOKKOS_INLINE_FUNCTION auto overlapDistance(Ray<Coordinate> const &ray,

} // namespace ArborX::Experimental

template <typename Coordinate>
struct ArborX::GeometryTraits::dimension<ArborX::Experimental::Ray<Coordinate>>
{
static constexpr int value = 3;
};
template <typename Coordinate>
struct ArborX::GeometryTraits::tag<ArborX::Experimental::Ray<Coordinate>>
{
using type = RayTag;
};
template <typename Coordinate>
struct ArborX::GeometryTraits::coordinate_type<
ArborX::Experimental::Ray<Coordinate>>
{
using type = Coordinate;
};

#endif
6 changes: 6 additions & 0 deletions src/geometry/algorithms/ArborX_Centroid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ struct centroid<EllipsoidTag, Ellipsoid>
}
};

template <typename Ray>
struct centroid<RayTag, Ray>
{
KOKKOS_FUNCTION static auto apply(Ray const &ray) { return ray.origin(); }
};

} // namespace Dispatch

} // namespace ArborX::Details
Expand Down
22 changes: 22 additions & 0 deletions src/geometry/algorithms/ArborX_Distance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,28 @@ struct distance<PointTag, SegmentTag, Point, Segment>
}
};

template <typename Ray, typename Box>
struct distance<RayTag, BoxTag, Ray, Box>
{
// 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<Ray> == 3);
using Coordinate = GeometryTraits::coordinate_type_t<Ray>;

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
Expand Down
11 changes: 11 additions & 0 deletions src/geometry/algorithms/ArborX_Equals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ struct equals<SphereTag, Sphere>
}
};

// equals sphere-sphere
template <typename Ray>
struct equals<RayTag, Ray>
{
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
Expand Down
31 changes: 31 additions & 0 deletions src/geometry/algorithms/ArborX_Intersects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,37 @@ struct intersects<SegmentTag, TriangleTag, Segment, Triangle>
}
};

template <typename Ray, typename Box>
struct intersects<RayTag, BoxTag, Ray, Box>
{
KOKKOS_FUNCTION static constexpr bool apply(Ray const &ray, Box const &box)
{
static_assert(GeometryTraits::dimension_v<Ray> == 3);
using Coordinate = GeometryTraits::coordinate_type_t<Ray>;

Coordinate tmin;
Coordinate tmax;
// intersects only if box is in front of the ray
return intersection(ray, box, tmin, tmax) && (tmax >= 0);
}
};

template <typename Ray, typename Triangle>
struct intersects<RayTag, TriangleTag, Ray, Triangle>
{
KOKKOS_FUNCTION static constexpr bool apply(Ray const &ray,
Triangle const &triangle)
{
static_assert(GeometryTraits::dimension_v<Ray> == 3);
using Coordinate = GeometryTraits::coordinate_type_t<Ray>;

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
Expand Down
26 changes: 26 additions & 0 deletions test/tstGeometryDistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <ArborX_Box.hpp>
#include <ArborX_Ellipsoid.hpp>
#include <ArborX_Ray.hpp>
#include <ArborX_Segment.hpp>
#include <ArborX_Sphere.hpp>
#include <ArborX_Tetrahedron.hpp>
Expand Down Expand Up @@ -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<Coordinate>;
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<float>::value;
#else
constexpr auto inf = KokkosExt::ArithmeticTraits::infinity<float>::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);
}
Loading
Loading