LCOV - code coverage report
Current view: top level - include/utils - TriangleManifold.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 2 2 100.0 %
Date: 2026-05-29 20:35:17 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "MooseTypes.h"
      13             : 
      14             : #include "libmesh/bounding_box.h"
      15             : #include "libmesh/face_tri3.h"
      16             : #include "libmesh/mesh_tet_interface.h"
      17             : 
      18             : #include <iosfwd>
      19             : #include <memory>
      20             : #include <cstdint>
      21             : #include <string>
      22             : #include <unordered_map>
      23             : #include <vector>
      24             : 
      25             : /**
      26             :  * Utility for querying point containment against a closed triangulated surface mesh.
      27             :  *
      28             :  * The class takes ownership of a reference to a prepared 2D surface mesh, validates that it forms
      29             :  * a closed 2-manifold (every triangle has exactly three neighbors, all elements are Tri3, and the
      30             :  * mesh is consistently oriented), builds a lightweight yz-plane acceleration grid, and exposes
      31             :  * `contains()` for point-in-solid queries.
      32             :  *
      33             :  * Containment is resolved in three stages:
      34             :  *
      35             :  * 1. Cheap global bounding-box rejection.
      36             :  * 2. Near-surface detection via a pre-built point locator (points within `surface_tolerance` of
      37             :  *    the mesh surface are treated as inside).
      38             :  * 3. Odd/even parity counting on a fixed +x ray, with automatic fallback to a solid-angle
      39             :  *    accumulation test when the ray grazes a triangle edge or vertex.
      40             :  *
      41             :  * The referenced mesh must outlive this object. Any geometric transforms (scale, rotation,
      42             :  * translation) should be applied to the mesh before constructing a `TriangleManifold`.
      43             :  */
      44             : class TriangleManifold
      45             : {
      46             : public:
      47             :   /**
      48             :    * Build a manifold classifier from a prepared surface mesh.
      49             :    *
      50             :    * @param mesh Serialized 2D surface mesh that defines the closed manifold. Must outlive this
      51             :    * object. Any desired transforms should already be applied to the mesh.
      52             :    * @param surface_tolerance Absolute tolerance used for manifold validation and near-surface
      53             :    * classification. Choose this relative to the mesh length scale and expected coordinate noise
      54             :    * from the export pipeline.
      55             :    */
      56             :   TriangleManifold(MeshBase & mesh, const Real surface_tolerance);
      57             : 
      58             :   /**
      59             :    * @return True if the point is inside the manifold or lies on the surface.
      60             :    */
      61             :   bool contains(const Point & point) const;
      62             : 
      63             :   /**
      64             :    * @return The manifold bounding box.
      65             :    */
      66      192438 :   const libMesh::BoundingBox & boundingBox() const { return _bounding_box; };
      67             : 
      68             :   /**
      69             :    * @return The number of triangles in the loaded manifold.
      70             :    */
      71          83 :   std::size_t numTriangles() const { return _mesh.n_active_elem(); }
      72             : 
      73             : private:
      74             :   /**
      75             :    * Result of intersecting the positive x-direction ray with a triangle.
      76             :    *
      77             :    * `Ambiguous` is returned when the hit is too close to an edge, vertex, or the ray origin. In
      78             :    * that case we abandon parity counting and fall back to the more expensive but robust solid-angle
      79             :    * test.
      80             :    */
      81             :   enum class RayIntersection
      82             :   {
      83             :     Miss,
      84             :     Hit,
      85             :     Ambiguous
      86             :   };
      87             : 
      88             :   /// Complete post-parse validation and acceleration-structure setup.
      89             :   void finalize();
      90             : 
      91             :   /// Build the yz-plane lookup grid used to accelerate +x ray queries.
      92             :   void buildCandidateGrid();
      93             : 
      94             :   /// Cheap global bounding-box rejection for containment queries.
      95             :   bool pointInsideBoundingBox(const Point & point) const;
      96             : 
      97             :   /// Detect whether a query point lies on or extremely near the manifold surface.
      98             :   bool pointOnSurface(const Point & point) const;
      99             : 
     100             :   /// Intersect a positive x-direction ray with a single triangle.
     101             :   RayIntersection rayIntersectsTriangle(const Point & point, const libMesh::Elem & tri) const;
     102             : 
     103             :   /// Robust fallback containment query based on accumulated solid angle.
     104             :   bool containsBySolidAngle(const Point & point) const;
     105             : 
     106             :   /// Get the subset of triangles whose yz extents may intersect the query ray.
     107             :   std::vector<dof_id_type> rayCandidates(const Point & point) const;
     108             : 
     109             :   /// Number of yz-grid bins in the y direction.
     110             :   std::size_t _num_y_cells = 1;
     111             : 
     112             :   /// Number of yz-grid bins in the z direction.
     113             :   std::size_t _num_z_cells = 1;
     114             : 
     115             :   /// Minimum global y coordinate used to map query points into yz-grid bins.
     116             :   Real _y_min = 0.0;
     117             : 
     118             :   /// Minimum global z coordinate used to map query points into yz-grid bins.
     119             :   Real _z_min = 0.0;
     120             : 
     121             :   /// Width of one yz-grid cell in the y direction.
     122             :   Real _y_cell_size = 1.0;
     123             : 
     124             :   /// Width of one yz-grid cell in the z direction.
     125             :   Real _z_cell_size = 1.0;
     126             : 
     127             :   /// Lookup from packed yz-grid cell index to triangles that could intersect the +x query ray.
     128             :   std::unordered_map<dof_id_type, std::vector<dof_id_type>> _ray_grid;
     129             : 
     130             :   MeshBase & _mesh;
     131             : 
     132             :   /// Absolute tolerance used throughout validation and geometric classification.
     133             :   const Real _surface_tolerance;
     134             : 
     135             :   /// Global bounding box of the transformed manifold.
     136             :   const libMesh::BoundingBox _bounding_box;
     137             : 
     138             :   /// Pre-built point locator for fast proximity-to-surface detection.
     139             :   const std::unique_ptr<libMesh::PointLocatorBase> _point_locator;
     140             : };

Generated by: LCOV version 1.14