50 class AttributesManager;
62 struct EdgeLocalVertex;
63 struct PolygonLocalEdge;
64 struct CellLocalFacet;
75 : element_id_( element_id ), local_vertex_id_( local_vertex_id )
81 index_t element_id_{ NO_ID };
82 index_t local_vertex_id_{ NO_ID };
89 : edge_id_( edge_id ), local_vertex_id_( local_vertex_id )
93 : edge_id_( std::move( edge_local_vertex.element_id_ ) ),
95 std::move( edge_local_vertex.local_vertex_id_ ) )
98 index_t edge_id_{ NO_ID };
99 index_t local_vertex_id_{ NO_ID };
106 : polygon_id_( polygon_id ), local_edge_id_( local_edge_id )
110 : polygon_id_( std::move( polygon_local_vertex.element_id_ ) ),
112 std::move( polygon_local_vertex.local_vertex_id_ ) )
115 index_t polygon_id_{ NO_ID };
116 index_t local_edge_id_{ NO_ID };
123 : cell_id_( cell_id ), local_facet_id_( local_facet_id )
126 index_t cell_id_{ NO_ID };
127 index_t local_facet_id_{ NO_ID };
137 template < index_t DIMENSION >
147 virtual void save_mesh(
const std::string& filename )
const = 0;
149 virtual std::tuple< index_t, std::vector< index_t > >
150 connected_components()
const = 0;
153 virtual void print_mesh_bounded_attributes()
const = 0;
167 virtual index_t nb_vertices()
const = 0;
169 virtual GEO::AttributesManager& vertex_attribute_manager()
const = 0;
179 if( !vertex_nn_search_ )
181 std::vector< vecn< DIMENSION > > vec_vertices( nb_vertices() );
182 for(
auto v :
range( nb_vertices() ) )
184 vec_vertices[v] = vertex( v );
186 vertex_nn_search_.reset(
189 return *vertex_nn_search_.get();
192 virtual MeshType type_name()
const = 0;
194 virtual std::string default_extension()
const = 0;
196 virtual bool is_mesh_valid()
const = 0;
205 mutable std::unique_ptr< NNSearch< DIMENSION > > vertex_nn_search_{};
212 template < index_t DIMENSION >
218 static std::unique_ptr< PointSetMesh< DIMENSION > > create_mesh(
220 std::tuple< index_t, std::vector< index_t > >
221 connected_components() const final;
222 bool is_mesh_valid()
const override 232 template < index_t DIMENSION >
239 template < index_t DIMENSION >
245 static std::unique_ptr< LineMesh< DIMENSION > > create_mesh(
254 virtual index_t edge_vertex(
260 virtual index_t nb_edges()
const = 0;
271 return ( e1 - e0 ).length();
280 return ( e1 + e0 ) / 2.;
291 if( !edge_nn_search_ )
293 std::vector< vecn< DIMENSION > > edge_centers( nb_edges() );
294 for(
auto e :
range( nb_edges() ) )
296 edge_centers[e] = edge_barycenter( e );
298 edge_nn_search_.reset(
301 return *edge_nn_search_.get();
312 return *edge_aabb_.get();
315 virtual GEO::AttributesManager& edge_attribute_manager()
const = 0;
321 if( this->nb_vertices() < 2 )
323 Logger::err(
"LineMesh",
"Mesh has less than 2 vertices " );
327 if( nb_edges() == 0 )
329 Logger::err(
"LineMesh",
"Mesh has no edge" );
334 std::vector< index_t > nb( this->nb_vertices(), 0 );
335 for(
auto p :
range( nb_edges() ) )
337 for(
auto v :
range( 2 ) )
339 nb[edge_vertex( { p, v } )]++;
342 auto nb_isolated_vertices =
343 static_cast< index_t
>( std::count( nb.begin(), nb.end(), 0 ) );
344 if( nb_isolated_vertices > 0 )
346 Logger::warn(
"LineMesh",
"Mesh has ", nb_isolated_vertices,
347 " isolated vertices " );
353 std::tuple< index_t, std::vector< index_t > >
354 connected_components()
const final;
360 mutable std::unique_ptr< NNSearch< DIMENSION > > edge_nn_search_{};
361 mutable std::unique_ptr< LineAABBTree< DIMENSION > > edge_aabb_{};
365 template < index_t DIMENSION >
372 template < index_t DIMENSION >
378 static std::unique_ptr< SurfaceMesh< DIMENSION > > create_mesh(
386 virtual index_t polygon_vertex(
392 virtual index_t nb_polygons()
const = 0;
397 virtual index_t nb_polygon_vertices( index_t polygon_id )
const = 0;
407 const index_t local_vertex_id =
411 < nb_polygon_vertices( polygon_local_vertex.
element_id_ ) );
413 != nb_polygon_vertices( polygon_local_vertex.
element_id_ ) - 1 )
416 local_vertex_id + 1 };
448 < nb_polygon_vertices( polygon_local_vertex.
element_id_ ) );
455 nb_polygon_vertices( polygon_local_vertex.
element_id_ ) - 1 };
482 index_t vertex_index_in_polygon(
483 index_t polygon_index, index_t vertex_id )
const;
493 index_t closest_vertex_in_polygon(
504 index_t polygon_from_vertex_ids( index_t in0, index_t in1 )
const;
521 std::vector< index_t > polygons_around_vertex(
522 index_t vertex_id,
bool border_only, index_t first_polygon )
const;
534 virtual index_t polygon_adjacent(
537 virtual GEO::AttributesManager& polygon_attribute_manager()
const = 0;
543 virtual bool polygons_are_simplicies()
const = 0;
549 return nb_polygon_vertices( polygon_id ) == 3;
554 if( is_triangle( polygon_id ) )
556 return PolygonType::TRIANGLE;
558 if( nb_polygon_vertices( polygon_id ) == 4 )
560 return PolygonType::QUAD;
562 return PolygonType::UNDEFINED;
572 return polygon_adjacent( polygon_local_edge ) == NO_ID;
580 for(
auto v :
range( nb_polygon_vertices( polygon_index ) ) )
599 this->vertex( polygon_edge_vertex( polygon_local_edge, 0 ) );
601 this->vertex( polygon_edge_vertex( polygon_local_edge, 1 ) );
602 return ( e1 - e0 ).length();
613 this->vertex( polygon_edge_vertex( polygon_local_edge, 0 ) );
615 this->vertex( polygon_edge_vertex( polygon_local_edge, 1 ) );
616 return ( e1 + e0 ) / 2.;
627 index_t vertex_id )
const 632 return polygon_vertex( polygon_local_edge );
637 % nb_polygon_vertices( polygon_local_edge.
polygon_id_ ) ) );
649 for(
auto v :
range( nb_polygon_vertices( polygon_id ) ) )
651 result += this->vertex(
654 return ( 1.0 / nb_polygon_vertices( polygon_id ) ) * result;
661 virtual double polygon_area( index_t polygon_id )
const = 0;
670 std::vector< vecn< DIMENSION > > polygon_centers(
672 for(
auto p :
range( nb_polygons() ) )
674 polygon_centers[p] = polygon_barycenter( p );
679 return *nn_search_.get();
691 return *polygon_aabb_;
698 if( this->nb_vertices() < 3 )
700 Logger::warn(
"SurfaceMesh has less than 3 vertices " );
703 if( nb_polygons() == 0 )
705 Logger::warn(
"SurfaceMesh has no polygon" );
710 std::vector< index_t > nb( this->nb_vertices(), 0 );
711 for(
auto p :
range( nb_polygons() ) )
713 for(
auto v :
range( nb_polygon_vertices( p ) ) )
715 nb[polygon_vertex( { p, v } )]++;
718 auto nb_isolated_vertices =
719 static_cast< index_t
>( std::count( nb.begin(), nb.end(), 0 ) );
720 if( nb_isolated_vertices > 0 )
722 Logger::warn(
"SurfaceMesh",
"Mesh has ", nb_isolated_vertices,
723 " isolated vertices " );
729 std::tuple< index_t, std::vector< index_t > >
730 connected_components()
const final;
736 mutable std::unique_ptr< NNSearch< DIMENSION > > nn_search_{};
737 mutable std::unique_ptr< SurfaceAABBTree< DIMENSION > > polygon_aabb_{};
741 template < index_t DIMENSION >
746 template < index_t DIMENSION >
759 double polygon_area( index_t polygon_id )
const;
768 const vec3& p1 = this->vertex(
770 const vec3& p2 = this->vertex(
772 const vec3& p3 = this->vertex(
774 vec3 norm = cross( p2 - p1, p3 - p1 );
775 return normalize( norm );
790 while( p0 == NO_ID && p < nb_polygons() )
792 for(
auto lv :
range( nb_polygon_vertices( p ) ) )
804 std::vector< index_t > polygon_ids =
805 polygons_around_vertex( vertex_id,
false, p0 );
807 for(
auto polygon_id : polygon_ids )
809 norm += polygon_normal( polygon_id );
811 return normalize( norm );
827 if( nb_polygon_vertices( polygon_id ) == 0 )
833 for(
auto i :
range( 1, nb_polygon_vertices( polygon_id ) - 1 ) )
835 const vec2& p2 = vertex(
837 const vec2& p3 = vertex(
841 return std::fabs( result );
850 template < index_t DIMENSION >
857 static std::unique_ptr< VolumeMesh< DIMENSION > > create_mesh(
867 virtual index_t cell_vertex(
879 virtual index_t cell_edge_vertex(
880 index_t cell_id, index_t edge_id, index_t vertex_id )
const = 0;
892 virtual index_t cell_facet_vertex(
894 index_t vertex_id )
const = 0;
902 virtual index_t cell_facet(
914 this->vertex( cell_edge_vertex( cell_id, edge_id, 0 ) );
916 this->vertex( cell_edge_vertex( cell_id, edge_id, 1 ) );
917 return ( e1 - e0 ).length();
927 index_t cell_id, index_t edge_id )
const 930 this->vertex( cell_edge_vertex( cell_id, edge_id, 0 ) );
932 this->vertex( cell_edge_vertex( cell_id, edge_id, 1 ) );
933 return ( e1 + e0 ) / 2.;
941 virtual index_t nb_cell_facets( index_t cell_id )
const = 0;
945 virtual index_t nb_cell_facets()
const = 0;
952 virtual index_t nb_cell_edges( index_t cell_id )
const = 0;
961 virtual index_t nb_cell_facet_vertices(
969 virtual index_t nb_cell_vertices( index_t cell_id )
const = 0;
974 virtual index_t nb_cells()
const = 0;
976 virtual index_t cell_begin( index_t cell_id )
const = 0;
978 virtual index_t cell_end( index_t cell_id )
const = 0;
983 virtual index_t cell_adjacent(
986 virtual GEO::AttributesManager& cell_attribute_manager()
const = 0;
988 virtual GEO::AttributesManager&
989 cell_facet_attribute_manager()
const = 0;
995 virtual CellType cell_type( index_t cell_id )
const = 0;
1002 virtual bool cells_are_simplicies()
const = 0;
1014 index_t nb_vertices = nb_cell_facet_vertices( cell_local_facet );
1015 for(
auto v :
range( nb_vertices ) )
1018 this->vertex( cell_facet_vertex( cell_local_facet, v ) );
1022 return result /
static_cast< double >( nb_vertices );
1031 for(
auto v :
range( nb_cell_vertices( cell_id ) ) )
1033 result += this->vertex(
1036 return ( 1.0 / nb_cell_vertices( cell_id ) ) * result;
1049 < nb_cell_facets( cell_local_facet.
cell_id_ ) );
1052 this->vertex( cell_facet_vertex( cell_local_facet, 0 ) );
1054 this->vertex( cell_facet_vertex( cell_local_facet, 1 ) );
1056 this->vertex( cell_facet_vertex( cell_local_facet, 2 ) );
1058 return cross( p2 - p1, p3 - p1 );
1064 virtual double cell_volume( index_t cell_id )
const = 0;
1066 std::vector< index_t > cells_around_vertex(
1067 index_t vertex_id, index_t cell_hint )
const;
1071 for(
auto v :
range( nb_cell_vertices( cell_id ) ) )
1082 bool find_cell_from_colocated_vertex_within_distance_if_any(
1086 index_t& cell_vertex_id )
const;
1096 if( !cell_facet_nn_search_ )
1098 std::vector< vecn< DIMENSION > > cell_facet_centers(
1101 for(
auto c :
range( nb_cells() ) )
1103 for(
auto f :
range( nb_cell_facets( c ) ) )
1105 cell_facet_centers[cf] =
1110 cell_facet_nn_search_.reset(
1113 return *cell_facet_nn_search_.get();
1120 if( !cell_nn_search_ )
1122 std::vector< vecn< DIMENSION > > cell_centers( nb_cells() );
1123 for(
auto c :
range( nb_cells() ) )
1125 cell_centers[c] = cell_barycenter( c );
1127 cell_nn_search_.reset(
1130 return *cell_nn_search_.get();
1141 return *cell_aabb_.get();
1148 if( this->nb_vertices() < 4 )
1150 Logger::warn(
"VolumeMesh has less than 4 vertices " );
1153 if( nb_cells() == 0 )
1155 Logger::warn(
"VolumeMesh has no cell" );
1160 std::vector< index_t > nb( this->nb_vertices(), 0 );
1161 for(
auto c :
range( nb_cells() ) )
1163 for(
auto v :
range( nb_cell_vertices( c ) ) )
1165 nb[cell_vertex( { c, v } )]++;
1168 auto nb_isolated_vertices =
1169 static_cast< index_t
>( std::count( nb.begin(), nb.end(), 0 ) );
1170 if( nb_isolated_vertices > 0 )
1172 Logger::warn(
"VolumeMesh",
"Mesh has ", nb_isolated_vertices,
1173 " isolated vertices " );
1179 std::tuple< index_t, std::vector< index_t > >
1180 connected_components()
const final;
1186 mutable std::unique_ptr< NNSearch< DIMENSION > >
1187 cell_facet_nn_search_{};
1188 mutable std::unique_ptr< NNSearch< DIMENSION > > cell_nn_search_{};
1189 mutable std::unique_ptr< VolumeAABBTree< DIMENSION > > cell_aabb_{};
1194 template < index_t DIMENSION >
1201 template < index_t DIMENSION >
1208 void create_point_set_mesh(
MeshType type );
1209 void create_line_mesh(
MeshType type );
1210 void create_well_mesh(
MeshType type );
1211 void create_surface_mesh(
MeshType type );
1218 std::unique_ptr< PointSetMesh< DIMENSION > > point_set_mesh{};
1219 std::unique_ptr< LineMesh< DIMENSION > > well_mesh{};
1220 std::unique_ptr< LineMesh< DIMENSION > > line_mesh{};
1221 std::unique_ptr< SurfaceMesh< DIMENSION > > surface_mesh{};
1224 template < index_t DIMENSION >
1237 void create_volume_mesh(
MeshType type );
1240 std::unique_ptr< VolumeMesh3D > volume_mesh{};
#define ringmesh_disable_copy_and_move(Class)
vecn< DIMENSION > cell_edge_barycenter(index_t cell_id, index_t edge_id) const
GEO::vecng< DIMENSION, double > vecn
double edge_length(index_t edge_id) const
Gets the length of the edge.
const VolumeAABBTree< DIMENSION > & cell_aabb() const
Creates an AABB tree for a Mesh cells.
CellLocalFacet(index_t cell_id, index_t local_facet_id)
const NNSearch< DIMENSION > & edge_nn_search() const
return the NNSearch at edges
double RINGMESH_API triangle_signed_area(const vec3 &p0, const vec3 &p1, const vec3 &p2, const vec3 &triangle_normal)
const SurfaceAABBTree< DIMENSION > & polygon_aabb() const
Creates an AABB tree for a Mesh polygons.
#define ringmesh_template_assert_2d_or_3d(type)
vecn< DIMENSION > cell_facet_normal(const CellLocalFacet &cell_local_facet) const
#define ringmesh_template_assert_3d(type)
vec3 polygon_normal(index_t polygon_id) const
index_t polygon_edge_vertex(const PolygonLocalEdge &polygon_local_edge, index_t vertex_id) const
Gets the vertex index on the polygon edge.
bool is_mesh_valid() const override
#define FORWARD_DECLARATION_DIMENSION_CLASS(Class)
vecn< DIMENSION > cell_barycenter(index_t cell_id) const
EdgeLocalVertex(ElementLocalVertex edge_local_vertex)
double polygon_edge_length(const PolygonLocalEdge &polygon_local_edge) const
Gets the length of the edge starting at a given vertex.
vec3 normal_at_vertex(index_t vertex_id, index_t p0=NO_ID) const
Computes the normal of the Mesh2D at the vertex location it computes the average value of polygon nor...
const NNSearch< DIMENSION > & cell_nn_search() const
return the NNSearch at cells
vecn< DIMENSION > edge_barycenter(index_t edge_id) const
const NNSearch< DIMENSION > & vertex_nn_search() const
return the NNSearch at vertices
encapsulate adimensional mesh functionalities in order to provide an API on which we base the RINGMes...
bool is_triangle(index_t polygon_id) const
bool is_mesh_valid() const override
ElementLocalVertex prev_polygon_vertex(const ElementLocalVertex &polygon_local_vertex) const
Gets the previous vertex index in the polygon.
const NNSearch< DIMENSION > & cell_facet_nn_search() const
return the NNSearch at cell facets
const LineAABBTree< DIMENSION > & edge_aabb() const
Creates an AABB tree for a Mesh edges.
PolygonLocalEdge(index_t polygon_id, index_t local_edge_id)
vecn< DIMENSION > polygon_barycenter(index_t polygon_id) const
#define ringmesh_assert(x)
bool is_mesh_valid() const override
vecn< DIMENSION > cell_facet_barycenter(const CellLocalFacet &cell_local_facet) const
double polygon_area(index_t polygon_id) const override
Classes to build GeoModel from various inputs.
ElementLocalVertex next_polygon_vertex(const ElementLocalVertex &polygon_local_vertex) const
Gets the next vertex index in the polygon vertex.
ElementLocalVertex(index_t element_id, index_t local_vertex_id)
index_t find_cell_corner(index_t cell_id, index_t vertex_id) const
PolygonType polygone_type(index_t polygon_id) const
bool is_polygon_on_border(index_t polygon_index) const
#define ALIAS_2D_AND_3D(Class)
vecn< DIMENSION > polygon_edge_barycenter(const PolygonLocalEdge &polygon_local_edge) const
Gets the barycenter of the edge starting at a given vertex.
const NNSearch< DIMENSION > & polygon_nn_search() const
return the NNSearch at polygons
bool is_edge_on_border(const PolygonLocalEdge &polygon_local_edge) const
double cell_edge_length(index_t cell_id, index_t edge_id) const
EdgeLocalVertex(index_t edge_id, index_t local_vertex_id)
PolygonLocalEdge(ElementLocalVertex polygon_local_vertex)