15#ifndef EBGEOMETRY_TRIANGLEDISTANCE_HPP
16#define EBGEOMETRY_TRIANGLEDISTANCE_HPP
30namespace TriangleDistance {
62 return Vec3V<V>{a_u.
x - a_v.x, a_u.y - a_v.y, a_u.z - a_v.z};
68dot(
const Vec3V<V>& a_u,
const Vec3V<V>& a_v)
noexcept
70 return a_u.x * a_v.x + a_u.y * a_v.y + a_u.z * a_v.z;
76cross(
const Vec3V<V>& a_u,
const Vec3V<V>& a_v)
noexcept
78 return Vec3V<V>{a_u.y * a_v.z - a_u.z * a_v.y, a_u.z * a_v.x - a_u.x * a_v.z, a_u.x * a_v.y - a_u.y * a_v.x};
84scaled(
const Vec3V<V>& a_u,
const V a_s)
noexcept
86 return Vec3V<V>{a_s * a_u.x, a_s * a_u.y, a_s * a_u.z};
92constant(
const int a_value)
noexcept
103sign(
const V a_x)
noexcept
107 return select(a_x > constant<V>(0), constant<V>(1), constant<V>(-1));
114onEdge(
const V a_t)
noexcept
118 return both(a_t > constant<V>(0), a_t < constant<V>(1));
148template <
class V,
class Source>
159 const Vec3V<V> v0 = a_triangle.vertex(0);
160 const Vec3V<V> v1 = a_triangle.vertex(1);
161 const Vec3V<V> v2 = a_triangle.vertex(2);
162 const Vec3V<V> n = a_triangle.normal();
174 const V s0 = sign(
dot(
cross(v21, n), p1));
175 const V s1 = sign(
dot(
cross(v32, n), p2));
176 const V s2 = sign(
dot(
cross(v13, n), p3));
178 const auto inside = abs(s0 + s1 + s2) >= constant<V>(2);
179 const V faceD =
dot(n, p1);
181 if constexpr (std::is_floating_point_v<V>) {
192 V bestD2 =
dot(p1, p1);
196 const V p2d2 =
dot(p2, p2);
204 const V p3d2 =
dot(p3, p3);
212 const V t1 =
dot(p1, v21) /
dot(v21, v21);
215 const Vec3V<V> y1 = p1 - scaled(v21, t1);
216 const V y1d2 =
dot(y1, y1);
225 const V t2 =
dot(p2, v32) /
dot(v32, v32);
228 const Vec3V<V> y2 = p2 - scaled(v32, t2);
229 const V y2d2 =
dot(y2, y2);
238 const V t3 =
dot(p3, v13) /
dot(v13, v13);
241 const Vec3V<V> y3 = p3 - scaled(v13, t3);
242 const V y3d2 =
dot(y3, y3);
251 const auto k =
static_cast<size_t>(best);
252 const Vec3V<V> pseudonormal = k < 3 ? a_triangle.vertexNormal(k) : a_triangle.edgeNormal(k - 3);
254 return sign(
dot(pseudonormal, bestVec)) * sqrt(bestD2);
257 const V t1 =
dot(p1, v21) /
dot(v21, v21);
258 const V t2 =
dot(p2, v32) /
dot(v32, v32);
259 const V t3 =
dot(p3, v13) /
dot(v13, v13);
261 const Vec3V<V> y1 = p1 - scaled(v21, t1);
262 const Vec3V<V> y2 = p2 - scaled(v32, t2);
263 const Vec3V<V> y3 = p3 - scaled(v13, t3);
267 V bestD2 =
dot(p1, p1);
268 V bestSign = sign(
dot(a_triangle.vertexNormal(0), p1));
270 const V p2d2 =
dot(p2, p2);
271 const auto c2 = p2d2 < bestD2;
272 bestSign = select(c2, sign(
dot(a_triangle.vertexNormal(1), p2)), bestSign);
273 bestD2 = select(c2, p2d2, bestD2);
275 const V p3d2 =
dot(p3, p3);
276 const auto c3 = p3d2 < bestD2;
277 bestSign = select(c3, sign(
dot(a_triangle.vertexNormal(2), p3)), bestSign);
278 bestD2 = select(c3, p3d2, bestD2);
280 const V y1d2 =
dot(y1, y1);
281 const auto e1 = both(onEdge(t1), y1d2 < bestD2);
282 bestSign = select(e1, sign(
dot(a_triangle.edgeNormal(0), y1)), bestSign);
283 bestD2 = select(e1, y1d2, bestD2);
285 const V y2d2 =
dot(y2, y2);
286 const auto e2 = both(onEdge(t2), y2d2 < bestD2);
287 bestSign = select(e2, sign(
dot(a_triangle.edgeNormal(1), y2)), bestSign);
288 bestD2 = select(e2, y2d2, bestD2);
290 const V y3d2 =
dot(y3, y3);
291 const auto e3 = both(onEdge(t3), y3d2 < bestD2);
292 bestSign = select(e3, sign(
dot(a_triangle.edgeNormal(2), y3)), bestSign);
293 bestD2 = select(e3, y3d2, bestD2);
295 return select(inside, faceD, bestSign * sqrt(bestD2));
312template <
class V,
class Source>
322 const Vec3V<V> v0 = a_triangle.vertex(0);
323 const Vec3V<V> v1 = a_triangle.vertex(1);
324 const Vec3V<V> v2 = a_triangle.vertex(2);
325 const Vec3V<V> n = a_triangle.normal();
335 const V s0 = sign(
dot(
cross(v21, n), p1));
336 const V s1 = sign(
dot(
cross(v32, n), p2));
337 const V s2 = sign(
dot(
cross(v13, n), p3));
339 const auto inside = abs(s0 + s1 + s2) >= constant<V>(2);
340 const V faceD =
dot(n, p1);
342 if constexpr (std::is_floating_point_v<V>) {
344 return faceD * faceD;
347 V bestD2 =
dot(p1, p1);
349 const V p2d2 =
dot(p2, p2);
350 const V p3d2 =
dot(p3, p3);
352 bestD2 = p2d2 < bestD2 ? p2d2 : bestD2;
353 bestD2 = p3d2 < bestD2 ? p3d2 : bestD2;
355 const V t1 =
dot(p1, v21) /
dot(v21, v21);
358 const Vec3V<V> y1 = p1 - scaled(v21, t1);
359 const V y1d2 =
dot(y1, y1);
361 bestD2 = y1d2 < bestD2 ? y1d2 : bestD2;
364 const V t2 =
dot(p2, v32) /
dot(v32, v32);
367 const Vec3V<V> y2 = p2 - scaled(v32, t2);
368 const V y2d2 =
dot(y2, y2);
370 bestD2 = y2d2 < bestD2 ? y2d2 : bestD2;
373 const V t3 =
dot(p3, v13) /
dot(v13, v13);
376 const Vec3V<V> y3 = p3 - scaled(v13, t3);
377 const V y3d2 =
dot(y3, y3);
379 bestD2 = y3d2 < bestD2 ? y3d2 : bestD2;
385 const V t1 =
dot(p1, v21) /
dot(v21, v21);
386 const V t2 =
dot(p2, v32) /
dot(v32, v32);
387 const V t3 =
dot(p3, v13) /
dot(v13, v13);
389 const Vec3V<V> y1 = p1 - scaled(v21, t1);
390 const Vec3V<V> y2 = p2 - scaled(v32, t2);
391 const Vec3V<V> y3 = p3 - scaled(v13, t3);
393 V bestD2 =
dot(p1, p1);
395 const V p2d2 =
dot(p2, p2);
396 bestD2 = select(p2d2 < bestD2, p2d2, bestD2);
398 const V p3d2 =
dot(p3, p3);
399 bestD2 = select(p3d2 < bestD2, p3d2, bestD2);
401 const V y1d2 =
dot(y1, y1);
402 bestD2 = select(both(onEdge(t1), y1d2 < bestD2), y1d2, bestD2);
404 const V y2d2 =
dot(y2, y2);
405 bestD2 = select(both(onEdge(t2), y2d2 < bestD2), y2d2, bestD2);
407 const V y3d2 =
dot(y3, y3);
408 bestD2 = select(both(onEdge(t3), y3d2 < bestD2), y3d2, bestD2);
410 return select(inside, faceD * faceD, bestD2);
GPU portability layer: host/device decoration macros and backend detection.
#define EBGEOMETRY_HOST_ALWAYS_INLINE
Always inline a function in a host pass (GCC and Clang); nothing in a device pass.
Definition EBGeometry_GPU.hpp:123
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
Thin wrappers over SSE4.1, AVX and AVX-512 registers, so that one kernel template serves every SIMD w...
EBGEOMETRY_HOST_ALWAYS_INLINE Tagged< T > select(const bool a_second, const Tagged< T > &a_first, const Tagged< T > &a_other) noexcept
One of two tagged values, chosen field by field, so that the compiler selects without a branch: a who...
Definition EBGeometry_CSGOps.hpp:273
bool both(const bool a_lhs, const bool a_rhs) noexcept
Whether both conditions hold (scalar form).
Definition EBGeometry_SIMD.hpp:62
T select(const bool a_mask, const T a_ifTrue, const T a_ifFalse) noexcept
Pick a_ifTrue where a_mask holds, else a_ifFalse (scalar form).
Definition EBGeometry_SIMD.hpp:49
float sqrt(const float a_x) noexcept
Square root (scalar form).
Definition EBGeometry_SIMD.hpp:74
float abs(const float a_x) noexcept
Absolute value (scalar form).
Definition EBGeometry_SIMD.hpp:98
EBGEOMETRY_HOST_ALWAYS_INLINE V unsignedDistance2(const Source &a_triangle, const Vec3V< V > &a_point) noexcept
The squared distance from a point to a triangle, without its sign: the candidates of signedDistance()...
Definition EBGeometry_TriangleDistance.hpp:316
EBGEOMETRY_HOST_ALWAYS_INLINE V signedDistance(const Source &a_triangle, const Vec3V< V > &a_point) noexcept
Signed distance from a_point to a triangle, or to one triangle per lane.
Definition EBGeometry_TriangleDistance.hpp:152
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
constexpr Vec3T< T > cross(const Vec3T< T > &u, const Vec3T< T > &v) noexcept
Cross product of two 3D vectors.
T dot(const Vec2T< T > &u, const Vec2T< T > &v) noexcept
Dot product of two 2D vectors.
V type
The scalar type.
Definition EBGeometry_SIMD.hpp:177
A 3D vector of V, where V is a scalar or a SIMD::Pack: x, y and z each hold one lane per triangle.
Definition EBGeometry_TriangleDistance.hpp:39
V y
y components.
Definition EBGeometry_TriangleDistance.hpp:48
V z
z components.
Definition EBGeometry_TriangleDistance.hpp:53
V x
x components.
Definition EBGeometry_TriangleDistance.hpp:43