50 : element_id_( std::move( edge_local_vertex.edge_id_ ) ),
51 local_vertex_id_( std::move( edge_local_vertex.local_vertex_id_ ) )
57 :
element_id_( std::move( polygon_local_edge.polygon_id_ ) ),
63 :
element_id_( std::move( cell_local_facet.cell_id_ ) ),
68 template < index_t DIMENSION >
69 std::unique_ptr< PointSetMesh< DIMENSION > >
73 if( new_type.empty() )
81 "Could not create mesh data structure: ", new_type );
83 "Falling back to GeogramPointSetMesh data structure" );
90 template < index_t DIMENSION >
91 std::tuple< index_t, std::vector< index_t > >
94 const auto nb_compoments = this->nb_vertices();
95 std::vector< index_t > components( nb_compoments );
96 std::iota( components.begin(), components.end(), 0 );
97 return std::make_tuple( nb_compoments, components );
100 template < index_t DIMENSION >
105 if( new_type.empty() )
112 Logger::warn(
"LineMesh",
"Could not create mesh data structure: ",
115 "LineMesh",
"Falling back to GeogramLineMesh data structure" );
122 template < index_t DIMENSION >
123 std::tuple< index_t, std::vector< index_t > >
126 std::vector< index_t > components( nb_edges(), NO_ID );
127 std::vector< index_t > vertex_components( this->nb_vertices(), NO_ID );
128 index_t nb_components{ 0 };
130 for(
auto edge :
range( nb_edges() ) )
133 const auto v0 = edge_vertex( { edge, 0 } );
134 const auto v1 = edge_vertex( { edge, 1 } );
135 if( vertex_components[v0] == NO_ID
136 && vertex_components[v1] == NO_ID )
138 vertex_components[v0] = nb_components;
139 vertex_components[v1] = nb_components;
140 components[edge] = nb_components;
143 else if( vertex_components[v0] != NO_ID
144 && vertex_components[v1] == NO_ID )
146 vertex_components[v1] = vertex_components[v0];
147 components[edge] = vertex_components[v0];
149 else if( vertex_components[v0] == NO_ID
150 && vertex_components[v1] != NO_ID )
152 vertex_components[v0] = vertex_components[v1];
153 components[edge] = vertex_components[v1];
158 if( vertex_components[v0] == vertex_components[v1] )
160 components[edge] = vertex_components[v0];
167 auto min_connected_components = std::min(
168 vertex_components[v0], vertex_components[v1] );
169 auto max_connected_components = std::max(
170 vertex_components[v0], vertex_components[v1] );
173 for(
auto previous_edge :
range( edge ) )
177 { previous_edge, 0 } )]
180 { previous_edge, 1 } )]
182 if( components[previous_edge]
183 == max_connected_components )
185 components[previous_edge] =
186 min_connected_components;
187 vertex_components[edge_vertex( { previous_edge,
188 0 } )] = min_connected_components;
189 vertex_components[edge_vertex( { previous_edge,
190 1 } )] = min_connected_components;
192 else if( components[previous_edge]
193 > max_connected_components )
196 components[previous_edge] - 1 >= 0 );
198 { previous_edge, 0 } )]
202 { previous_edge, 1 } )]
205 --components[previous_edge];
206 vertex_components[edge_vertex( { previous_edge,
207 0 } )] = components[previous_edge];
208 vertex_components[edge_vertex( { previous_edge,
209 1 } )] = components[previous_edge];
211 components[previous_edge] != NO_ID );
213 { previous_edge, 0 } )]
216 { previous_edge, 1 } )]
219 == vertex_components[edge_vertex(
220 { previous_edge, 0 } )] );
222 == vertex_components[edge_vertex(
223 { previous_edge, 1 } )] );
226 components[edge] = min_connected_components;
227 vertex_components[v0] = min_connected_components;
228 vertex_components[v1] = min_connected_components;
239 return std::make_tuple( nb_components, components );
242 template < index_t DIMENSION >
243 std::unique_ptr< SurfaceMesh< DIMENSION > >
247 if( new_type.empty() )
255 "Could not create mesh data structure: ", new_type );
257 "Falling back to GeogramSurfaceMesh data structure" );
264 template < index_t DIMENSION >
270 < nb_polygon_vertices( polygon_local_edge.
polygon_id_ ) );
275 polygon_vertex( next_polygon_vertex( polygon_local_edge ) );
280 auto polygons_around_next_v_id = polygons_around_vertex(
283 static_cast< index_t
>( polygons_around_next_v_id.size() );
287 auto& next_p = next_polygon_local_edge.
polygon_id_;
288 next_p = polygons_around_next_v_id[0];
289 auto& next_e = next_polygon_local_edge.local_edge_id_;
295 next_p = polygons_around_next_v_id[1];
301 next_e = vertex_index_in_polygon( next_p, next_v_id );
304 else if( nb_around == 1 )
307 next_e = vertex_index_in_polygon( next_p, next_v_id );
311 return next_polygon_local_edge;
314 template < index_t DIMENSION >
320 < nb_polygon_vertices( polygon_local_edge.
polygon_id_ ) );
324 auto v_id = polygon_vertex( { polygon_local_edge } );
329 auto polygons_around_v_id = polygons_around_vertex(
331 auto nb_around =
static_cast< index_t
>( polygons_around_v_id.size() );
335 auto& prev_p = prev_polygon_local_edge.
polygon_id_;
336 prev_p = polygons_around_v_id[0];
337 auto& prev_e = prev_polygon_local_edge.local_edge_id_;
343 prev_p = polygons_around_v_id[1];
349 auto v_in_prev_f = vertex_index_in_polygon( prev_p, v_id );
355 else if( nb_around == 1 )
358 auto v_in_next_polygon = vertex_index_in_polygon( prev_p, v_id );
359 prev_e = prev_polygon_vertex( { prev_p, v_in_next_polygon } )
364 return prev_polygon_local_edge;
367 template < index_t DIMENSION >
369 index_t in0, index_t in1 )
const 372 in0 < this->nb_vertices() && in1 < this->nb_vertices() );
380 for(
auto poly :
range( nb_polygons() ) )
384 polygon_vertex( { poly, nb_polygon_vertices( poly ) - 1 } );
385 for(
auto v :
range( nb_polygon_vertices( poly ) ) )
387 auto p = polygon_vertex( { poly, v } );
388 if( ( prev == in0 && p == in1 ) || ( prev == in1 && p == in0 ) )
403 template < index_t DIMENSION >
405 index_t polygon_index, index_t vertex_id )
const 408 for(
auto v :
range( nb_polygon_vertices( polygon_index ) ) )
410 if( polygon_vertex( { polygon_index, v } ) == vertex_id )
418 template < index_t DIMENSION >
423 double dist{ DBL_MAX };
424 for(
auto v_id :
range( nb_polygon_vertices( p ) ) )
426 double distance = length2(
430 if( dist > distance )
439 template < index_t DIMENSION >
441 index_t surf_vertex_id,
bool border_only, index_t p0 )
const 444 while( p0 == NO_ID && cur_p < nb_polygons() )
446 for(
auto lv :
range( nb_polygon_vertices( cur_p ) ) )
448 if( polygon_vertex( { cur_p, lv } ) == surf_vertex_id )
459 std::vector< index_t > visited;
460 visited.reserve( 10 );
463 std::stack< index_t > S;
465 visited.push_back( p0 );
467 std::vector< index_t > result;
468 result.reserve( 10 );
474 for(
auto v :
range( nb_polygon_vertices( p ) ) )
476 if( polygon_vertex( { p, v } ) == surf_vertex_id )
478 auto adj_P = polygon_adjacent( { p, v } );
481 auto adj_prev = polygon_adjacent( { p, prev } );
489 visited.push_back( adj_P );
492 if( adj_prev != NO_ID )
495 if( !
contains( visited, adj_prev ) )
498 visited.push_back( adj_prev );
504 if( adj_P == NO_ID || adj_prev == NO_ID )
506 result.push_back( p );
511 result.push_back( p );
518 }
while( !S.empty() );
526 if( nb_polygon_vertices( polygon_id ) == 0 )
532 for(
auto i :
range( 1, nb_polygon_vertices( polygon_id ) - 1 ) )
536 const vec3& p3 = vertex(
539 p1, p2, p3, polygon_normal( polygon_id ) );
541 return std::fabs( result );
544 template < index_t DIMENSION >
545 std::tuple< index_t, std::vector< index_t > >
548 std::vector< index_t > components( nb_polygons(), NO_ID );
549 index_t nb_components{ 0 };
550 for(
auto polygon :
range( nb_polygons() ) )
552 if( components[polygon] == NO_ID )
554 std::stack< index_t > S;
556 components[polygon] = nb_components;
559 auto cur_polygon = S.top();
562 range( nb_polygon_vertices( cur_polygon ) ) )
565 polygon_adjacent( { cur_polygon, edge } );
566 if( adj_polygon != NO_ID
567 && components[adj_polygon] == NO_ID )
569 S.push( adj_polygon );
570 components[adj_polygon] = nb_components;
573 }
while( !S.empty() );
577 return std::make_tuple( nb_components, components );
580 template < index_t DIMENSION >
581 std::unique_ptr< VolumeMesh< DIMENSION > >
584 auto new_type = type;
585 if( new_type.empty() )
593 "Could not create mesh data structure: ", new_type );
595 "Falling back to GeogramVolumeMesh data structure" );
602 template < index_t DIMENSION >
603 std::tuple< index_t, std::vector< index_t > >
606 std::vector< index_t > components( nb_cells(), NO_ID );
607 index_t nb_components{ 0 };
608 for(
auto cell :
range( nb_cells() ) )
610 if( components[cell] == NO_ID )
612 std::stack< index_t > S;
614 components[cell] = nb_components;
617 auto cur_cell = S.top();
619 for(
auto facet :
range( nb_cell_facets( cur_cell ) ) )
621 auto adj_cell = cell_adjacent( { cur_cell, facet } );
622 if( adj_cell != NO_ID && components[adj_cell] == NO_ID )
625 components[adj_cell] = nb_components;
628 }
while( !S.empty() );
632 return std::make_tuple( nb_components, components );
635 template < index_t DIMENSION >
637 index_t vertex_id, index_t cell_hint )
const 639 std::vector< index_t > result;
641 if( cell_hint == NO_ID )
644 index_t cell_vertex_not_used = NO_ID;
645 bool found = find_cell_from_colocated_vertex_within_distance_if_any(
646 cur_vec, global_epsilon, cell_hint, cell_vertex_not_used );
655 std::vector< index_t > visited;
656 visited.reserve( 10 );
659 std::stack< index_t > S;
661 visited.push_back( cell_hint );
668 bool cell_includes_vertex{
false };
669 for(
auto v :
range( nb_cell_vertices( c ) ) )
671 if( cell_vertex( { c, v } ) == vertex_id )
673 result.push_back( c );
674 cell_includes_vertex =
true;
678 if( !cell_includes_vertex )
683 for(
auto f :
range( nb_cell_facets( c ) ) )
685 for(
auto v :
range( nb_cell_facet_vertices( { c, f } ) ) )
687 auto vertex = cell_facet_vertex( { c, f }, v );
688 if( vertex == vertex_id )
690 auto adj_P = cell_adjacent( { c, f } );
697 visited.push_back( adj_P );
704 }
while( !S.empty() );
709 template < index_t DIMENSION >
715 index_t& cell_vertex_id )
const 718 cell_nn_search().get_neighbors( vertex_vec,
719 [
this, &vertex_vec, &result, &cell_id, &cell_vertex_id, distance](
721 for(
auto j :
range( nb_cell_vertices( i ) ) )
724 vertex_vec, distance ) )
726 cell_vertex_id = cell_vertex( { i, j } );
737 template < index_t DIMENSION >
740 create_point_set_mesh(
"" );
741 create_line_mesh(
"" );
742 create_well_mesh(
"" );
743 create_surface_mesh(
"" );
746 template < index_t DIMENSION >
752 template < index_t DIMENSION >
758 template < index_t DIMENSION >
764 template < index_t DIMENSION >
772 create_volume_mesh(
"" );
static std::unique_ptr< PointSetMesh< DIMENSION > > create_mesh(const MeshType type="")
index_t polygon_from_vertex_ids(index_t in0, index_t in1) const
Get the first polygon of the surface that has an edge linking the two vertices (ids in the surface) ...
virtual double polygon_area(index_t polygon_id) const =0
GEO::vecng< DIMENSION, double > vecn
std::tuple< index_t, std::vector< index_t > > connected_components() const final
static std::unique_ptr< BaseClass > create(const Key &key, const Args &... args)
std::tuple< index_t, std::vector< index_t > > connected_components() const final
static std::unique_ptr< LineMesh< DIMENSION > > create_mesh(const MeshType type="")
PolygonLocalEdge next_on_border(const PolygonLocalEdge &polygon_local_edge) const
Get the next edge on the border.
PolygonLocalEdge prev_on_border(const PolygonLocalEdge &polygon_local_edge) const
Get the previous edge on the border.
void create_point_set_mesh(MeshType type)
index_t closest_vertex_in_polygon(index_t polygon_index, const vecn< DIMENSION > &query_point) const
Compute closest vertex in a polygon to a point.
double RINGMESH_API triangle_signed_area(const vec3 &p0, const vec3 &p1, const vec3 &p2, const vec3 &triangle_normal)
index_t vertex_index_in_polygon(index_t polygon_index, index_t vertex_id) const
Get the vertex index in a polygon.
static void warn(const std::string &feature, const Args &... args)
std::vector< index_t > polygons_around_vertex(index_t vertex_id, bool border_only, index_t first_polygon) const
Determines the polygons around a vertex.
void create_well_mesh(MeshType type)
bool find_cell_from_colocated_vertex_within_distance_if_any(const vecn< DIMENSION > &vertex_vec, double distance, index_t &cell_id, index_t &cell_vertex_id) const
std::tuple< index_t, std::vector< index_t > > connected_components() const final
std::tuple< index_t, std::vector< index_t > > connected_components() const final
#define ringmesh_assert(x)
bool contains(const container &in, const T &value)
static std::unique_ptr< SurfaceMesh< DIMENSION > > create_mesh(const MeshType type="")
ElementLocalVertex()=default
Classes to build GeoModel from various inputs.
void create_line_mesh(MeshType type)
void create_surface_mesh(MeshType type)
std::vector< index_t > cells_around_vertex(index_t vertex_id, index_t cell_hint) const
static std::unique_ptr< VolumeMesh< DIMENSION > > create_mesh(const MeshType type="")
bool inexact_equal(const vecn< DIMENSION > &v1, const vecn< DIMENSION > &v2, double epsilon)