|
EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
|
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. | |
The triangle signed-distance kernel.
|
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:
| V | Scalar (float or double) or SIMD::Pack. |
| Source | Triangle accessor, as above. |
| [in] | a_triangle | Triangle accessor. |
| [in] | a_point | Query point, the same in every lane. |
|
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.
| V | Scalar or SIMD::Pack. |
| Source | A triangle accessor (see signedDistance()). |
| [in] | a_triangle | The triangle(s). |
| [in] | a_point | The point, broadcast to every lane. |