|
| template<typename DerivedV, typename DerivedF> |
| | WindingNumberAntipodalScene (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, const Direction &x0=default_x0()) |
| | Build a scene from a 3D triangle mesh.
|
| template<typename Intersector, typename Derivedp> |
| Scalar | winding_number (const Intersector &intersector, const Eigen::MatrixBase< Derivedp > &p) const |
| | Single-point query: full generalized winding number at p (fractional + signed integer crossings).
|
| template<typename Intersector, typename DerivedO, typename DerivedW> |
| void | winding_number (const Intersector &intersector, const Eigen::MatrixBase< DerivedO > &O, Eigen::PlainObjectBase< DerivedW > &W) const |
| | Batch query, parallelized via igl::parallel_for.
|
| const Direction & | x0 () const |
| | Reference direction x0 used to evaluate this scene.
|
| size_t | num_boundary_segments () const |
| | Number of weighted boundary edge segments.
|
| size_t | num_faces () const |
| | Number of triangles in the original mesh.
|
|
| static Direction | default_x0 () |
| | Default reference direction: normalize(1, sqrt(2), sqrt(3)).
|
| static Scalar | half_solid_angle_unorm (const Direction &x1, const Point &v0, const Point &v1) |
| | Half the signed solid angle subtended by the spherical triangle (x1, v0, v1) at the origin, via the unnormalized Van Oosterom-Strackee formula.
|
| template<typename DerivedV, typename DerivedF> |
| static void | build_boundary_segments (const Eigen::MatrixBase< DerivedV > &V, const Eigen::MatrixBase< DerivedF > &F, std::vector< WeightedSeg > &out) |
| | Extract the open boundary as oriented, weighted edge segments.
|
template<typename Scalar>
class igl::WindingNumberAntipodalScene< Scalar >
Precomputed scene for the Antipodal Method generalized winding number.
The scene stores only the weighted open-boundary edges of the input triangle mesh and a fixed antipodal reference direction x0. Closed (manifold) meshes have an empty boundary and the fractional term is exactly zero.
Querying the winding number additionally requires an Intersector that returns the signed ray-mesh crossing count along (p, x0) over the original mesh; the scene itself is intersector-agnostic. See igl::embree::EmbreeIntersector::signedIntersectionsRay for an optimized concrete implementation.
Intersector concept
A type I satisfies the concept when it exposes:
- using OriginType = ...; (3D row vector type)
- using DirectionType = ...; (3D row vector type)
- int signedIntersectionsRay(
OriginType origin, DirectionType direction,
/* defaulted tnear, tfar, mask */) const;
winding_number casts query point/direction to the intersector's types at the call site, so a double-precision scene against a float-only intersector works without an adaptor.
template<typename Scalar>
Half the signed solid angle subtended by the spherical triangle (x1, v0, v1) at the origin, via the unnormalized Van Oosterom-Strackee formula.
x1 is expected to be a unit vector (the antipodal "south pole" -x0); v0, v1 need not be normalized. Callers accumulate per-edge contributions and divide by 2π.
template<typename Scalar>
template<typename DerivedV, typename DerivedF>
| void igl::WindingNumberAntipodalScene< Scalar >::build_boundary_segments |
( |
const Eigen::MatrixBase< DerivedV > & | V, |
|
|
const Eigen::MatrixBase< DerivedF > & | F, |
|
|
std::vector< WeightedSeg > & | out ) |
|
inlinestatic |
Extract the open boundary as oriented, weighted edge segments.
Each undirected edge {min, max} accumulates +1 for every triangle that traverses it as min→max and -1 for every traversal max→min. Interior edges of an oriented manifold cancel to zero and are dropped. Surviving edges are emitted with positive weight; the segment direction is flipped when the net count is negative so the weight is always > 0. Non-manifold (≥3 incident triangles per edge) is handled the same way. The surviving net count becomes the weight.