EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
Classes | Functions
EBGeometry::TriangleDistance Namespace Reference

The triangle signed-distance kernel. More...

Classes

struct  Vec3V
 A 3D vector of V, where V is a scalar or a SIMD::Pack: x, y and z each hold one lane per triangle. More...
 

Functions

template<class V , class Source >
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.
 
template<class V , class Source >
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() (the face where the point projects inside it, else the nearest vertex or edge), none signed.
 

Detailed Description

The triangle signed-distance kernel.

Function Documentation

◆ signedDistance()

template<class V , class Source >
EBGEOMETRY_HOST_ALWAYS_INLINE V EBGeometry::TriangleDistance::signedDistance ( const Source &  a_triangle,
const Vec3V< V > &  a_point 
)
inlinenoexcept

Signed distance from a_point to a triangle, or to one triangle per lane.

Where the point projects inside the triangle, the distance is the signed distance to its plane. Elsewhere it is the distance to the closest vertex or edge, signed by that feature's pseudonormal. The candidates are compared by squared distance in the order vertex 0, 1, 2 and edge 0, 1, 2, a later one replacing the best only when strictly closer, and there is one square root, at the end. A sign test (s > 0) gives -1 at zero and at NaN. For a SIMD::Pack every lane computes every candidate, so the kernel has no branches. For a scalar (a device thread, Triangle, a build without SIMD) it branches instead: it returns at once for a point projecting inside the face, and signs only the closest candidate, with the same candidates, order and arithmetic, so the result is the same.

The triangle is read through a_triangle, at the point each value is needed, so that a SIMD caller loads straight from its arrays into registers rather than staging the whole triangle in memory first. It provides, as Vec3V<V> by value:

  • vertex(k): vertex position k, for k = 0, 1, 2;
  • normal(): the face normal;
  • vertexNormal(k): the pseudonormal of vertex k;
  • edgeNormal(k): the pseudonormal of edge k, from vertex k to vertex k + 1 (mod 3).
    Template Parameters
    VScalar (float or double) or SIMD::Pack.
    SourceTriangle accessor, as above.
    Parameters
    [in]a_triangleTriangle accessor.
    [in]a_pointQuery point, the same in every lane.
    Returns
    The signed distance, negative behind the face normal.

◆ unsignedDistance2()

template<class V , class Source >
EBGEOMETRY_HOST_ALWAYS_INLINE V EBGeometry::TriangleDistance::unsignedDistance2 ( const Source &  a_triangle,
const Vec3V< V > &  a_point 
)
inlinenoexcept

The squared distance from a point to a triangle, without its sign: the candidates of signedDistance() (the face where the point projects inside it, else the nearest vertex or edge), none signed.

A nearest-triangle search compares these and signs only the winner, with signedDistance() on that triangle: the six pseudonormal dot products and the square root are then paid once per query, not once per triangle. The square root of this value equals |signedDistance()| to rounding, so the winner is the triangle a search on signedDistance() picks, except where two triangles are equally near to rounding. With V a scalar, the inside case returns early, as signedDistance()'s does.

Template Parameters
VScalar or SIMD::Pack.
SourceA triangle accessor (see signedDistance()).
Parameters
[in]a_triangleThe triangle(s).
[in]a_pointThe point, broadcast to every lane.
Returns
The squared distance, one per lane.