42 #include <geogram/mesh/mesh.h> 43 #include <geogram/mesh/mesh_geometry.h> 63 template < index_t DIMENSION >
68 return length( v2 - v1 ) < epsilon;
80 const GeoModel3D& geomodel, index_t surface_part_id,
bool side )
83 gmme_id cur_surface( Surface3D::type_name_static(), surface_part_id );
84 const Surface3D& surface = geomodel.surface( surface_part_id );
85 for(
auto r :
range( surface.nb_incident_entities() ) )
87 const Region3D& cur_region = surface.incident_entity( r );
88 for(
auto s :
range( cur_region.nb_boundaries() ) )
90 if( cur_region.side( s ) == side
91 && cur_region.boundary_gmme( s ) == cur_surface )
100 struct LineInstersection
102 LineInstersection(
const vec3& intersection,
103 index_t surface_id = NO_ID,
104 index_t trgl_id = NO_ID )
105 : intersection_( intersection ),
106 surface_id_( surface_id ),
111 : intersection_(
vec3() ), surface_id_( NO_ID ), trgl_id_( NO_ID )
119 template < index_t DIMENSION >
122 const LineInstersection& corner,
125 index_t corner_id = well.
find_corner( corner.intersection_, epsilon );
126 if( corner_id == NO_ID )
128 bool is_on_surface = corner.surface_id_ != NO_ID;
132 id = corner.surface_id_;
139 well.
create_corner( corner.intersection_, is_on_surface,
id );
144 bool get_side(
const vec3& vertex,
145 const vec3& on_surface,
146 const Surface3D& surface,
149 vec3 direction = vertex - on_surface;
150 return dot( direction, surface.mesh().polygon_normal( triangle ) ) > 0;
153 index_t find_region_from_corners(
const GeoModel3D& geomodel,
154 const std::vector< vec3 > vertices,
155 const LineInstersection& start,
156 const LineInstersection& end )
158 if( start.surface_id_ != NO_ID )
160 bool sign = get_side( vertices[1], start.intersection_,
161 geomodel.surface( start.surface_id_ ), start.trgl_id_ );
162 return find_region( geomodel, start.surface_id_, sign );
164 else if( end.surface_id_ != NO_ID )
167 get_side( vertices[vertices.size() - 2], end.intersection_,
168 geomodel.surface( end.surface_id_ ), end.trgl_id_ );
169 return find_region( geomodel, end.surface_id_, sign );
173 double best_distance = max_float64();
174 index_t best_surface = NO_ID;
176 index_t best_triangle = NO_ID;
177 for(
const auto& surface : geomodel.surfaces() )
179 index_t triangle = NO_ID;
181 double distance = max_float64();
182 std::tie( triangle, nearest, distance ) =
183 surface.polygon_aabb().closest_triangle(
184 start.intersection_ );
185 if( distance < best_distance )
187 best_distance = distance;
188 best_nearest = nearest;
189 best_surface = surface.index();
190 best_triangle = triangle;
193 bool sign = get_side( start.intersection_, best_nearest,
194 geomodel.surface( best_surface ), best_triangle );
195 return find_region( geomodel, best_surface, sign );
199 template < index_t DIMENSION >
200 void create_well_part_and_corners(
const GeoModel3D& geomodel,
202 const std::vector< vec3 > vertices,
203 const LineInstersection& start,
204 const LineInstersection& end )
207 find_region_from_corners( geomodel, vertices, start, end );
208 if( region == NO_ID )
213 index_t new_well_part_id = well.
create_part( region );
217 find_or_create_corner( well, region, start, geomodel.epsilon() );
221 find_or_create_corner( well, region, end, geomodel.epsilon() );
226 class EdgeConformerAction
229 EdgeConformerAction(
const Surface3D& surface,
232 std::vector< LineInstersection >& intersections )
233 : surface_( surface ),
234 segment_( v_from, v_to ),
235 intersections_( intersections )
239 void operator()( index_t trgl )
241 bool does_seg_intersect_triangle =
false;
243 std::tie( does_seg_intersect_triangle, result ) =
245 { surface_.mesh_element_vertex( { trgl, 0 } ),
246 surface_.mesh_element_vertex( { trgl, 1 } ),
247 surface_.mesh_element_vertex( { trgl, 2 } ) } );
248 if( does_seg_intersect_triangle )
250 intersections_.push_back(
251 LineInstersection( result, surface_.index(), trgl ) );
256 const Surface3D& surface_;
257 Geometry::Segment3D segment_;
259 std::vector< LineInstersection >& intersections_;
265 const LineMesh3D& mesh, index_t edge, index_t vertex_from )
266 : edge_( edge ), vertex_from_( vertex_from )
282 index_t edge_vertex_;
283 index_t vertex_from_;
289 template < index_t DIMENSION >
297 template < index_t DIMENSION >
303 is_on_surface_( is_on_surface ),
309 ->create_vertex( point );
312 template < index_t DIMENSION >
315 return mesh_->vertex( 0 );
318 template < index_t DIMENSION >
319 GEO::AttributesManager&
322 return mesh_->vertex_attribute_manager();
327 template < index_t DIMENSION >
338 template < index_t DIMENSION >
342 index_t nb_points =
static_cast< index_t
>( points.size() );
343 std::unique_ptr< LineMeshBuilder< DIMENSION > > builder =
345 builder->create_vertices( nb_points );
346 for(
auto p :
range( nb_points ) )
348 builder->set_vertex( p, points[p] );
352 builder->create_edges( nb_edges );
353 for(
auto e :
range( nb_edges ) )
360 template < index_t DIMENSION >
363 return mesh_->nb_edges();
366 template < index_t DIMENSION >
369 return mesh_->nb_vertices();
372 template < index_t DIMENSION >
375 return mesh_->vertex( v );
378 template < index_t DIMENSION >
382 return vertex(
mesh_->edge_vertex( well_edge_local_vertex ) );
385 template < index_t DIMENSION >
389 return mesh_->vertex_nn_search();
392 template < index_t DIMENSION >
403 template < index_t DIMENSION >
404 GEO::AttributesManager&
407 return mesh_->vertex_attribute_manager();
409 template < index_t DIMENSION >
410 GEO::AttributesManager&
413 return mesh_->edge_attribute_manager();
418 template < index_t DIMENSION >
423 template < index_t DIMENSION >
437 template < index_t DIMENSION >
462 template < index_t DIMENSION >
470 nb_edges +=
part( part_id ).nb_edges();
477 template < index_t DIMENSION >
489 template < index_t DIMENSION >
504 template < index_t DIMENSION >
509 template < index_t DIMENSION >
526 template < index_t DIMENSION >
539 template < index_t DIMENSION >
542 wells_.resize( nb,
nullptr );
556 "Wells",
"2D Wells not fully implemented yet" );
561 const LineMesh3D& in, LineMesh3D& out )
564 std::unique_ptr< LineMeshBuilder3D > builder =
565 LineMeshBuilder3D::create_builder( out );
566 builder->clear(
false,
false );
568 GEO::Attribute< LineInstersection > vertex_info(
569 out.vertex_attribute_manager(),
"info" );
570 builder->create_vertices( in.nb_vertices() );
571 for(
auto v :
range( in.nb_vertices() ) )
573 const vec3& vertex = in.vertex( v );
574 builder->set_vertex( v, vertex );
575 vertex_info[v] = LineInstersection( vertex );
578 for(
auto e :
range( in.nb_edges() ) )
581 const vec3& from_vertex = in.vertex( from_id );
583 const vec3& to_vertex = in.vertex( to_id );
586 box.add_point( from_vertex );
587 box.add_point( to_vertex );
588 std::vector< LineInstersection > intersections;
589 for(
const auto& surface :
geomodel_->surfaces() )
591 EdgeConformerAction action(
592 surface, from_vertex, to_vertex, intersections );
593 surface.polygon_aabb().compute_bbox_element_bbox_intersections(
597 std::vector< index_t > indices( intersections.size() );
598 std::iota( indices.begin(), indices.end(), 0 );
599 std::vector< double > distances( intersections.size() );
600 for(
auto i :
range( intersections.size() ) )
603 length( from_vertex - intersections[i].intersection_ );
606 double edge_length = length( from_vertex - to_vertex );
607 index_t last_vertex = from_id;
608 for(
auto i :
range( intersections.size() ) )
610 if( distances[indices[i]] < epsilon )
612 vertex_info[from_id] = intersections[i];
614 else if( std::fabs( distances[indices[i]] - edge_length )
617 vertex_info[to_id] = intersections[i];
621 index_t vertex_id = builder->create_vertex(
622 intersections[i].intersection_ );
623 vertex_info[vertex_id] = intersections[i];
624 builder->create_edge( last_vertex, vertex_id );
625 last_vertex = vertex_id;
628 builder->create_edge( last_vertex, to_id );
639 "Wells",
"2D Wells not fully implemented yet" );
644 const LineMesh3D& mesh,
const std::string& name )
649 wells_.push_back(
new Well3D );
650 Well3D& new_well = *
wells_.back();
651 new_well.set_name( name );
653 GeogramLineMesh3D conformal_mesh;
656 std::vector< std::vector< index_t > > edges_around_vertices(
657 conformal_mesh.nb_vertices() );
658 for(
auto e :
range( conformal_mesh.nb_edges() ) )
660 for(
auto i :
range( 2 ) )
664 edges_around_vertices[v].push_back( e );
668 std::stack< OrientedEdge > S;
669 for(
auto v :
range( conformal_mesh.nb_vertices() ) )
671 const std::vector< index_t >& edges = edges_around_vertices[v];
672 if( edges.size() == 1 )
674 S.emplace( conformal_mesh, edges.front(), v );
680 "A well should have at least one starting or ending point" );
683 GEO::Attribute< LineInstersection > vertex_info(
684 conformal_mesh.vertex_attribute_manager(),
"info" );
685 std::vector< bool > edge_visited( conformal_mesh.nb_edges(), false );
688 OrientedEdge cur_edge = S.top();
690 if( edge_visited[cur_edge.edge_] )
694 edge_visited[cur_edge.edge_] =
true;
696 std::vector< vec3 > well_part_points;
697 std::stack< OrientedEdge > S_part;
698 S_part.push( cur_edge );
701 OrientedEdge cur_edge_part = S_part.top();
703 edge_visited[cur_edge_part.edge_] =
true;
705 conformal_mesh.vertex( cur_edge_part.vertex_from_ );
706 index_t v_to_id = conformal_mesh.edge_vertex(
708 ( cur_edge_part.edge_vertex_ + 1 ) % 2 ) );
709 const vec3& v_to = conformal_mesh.vertex( v_to_id );
710 well_part_points.push_back( v_from );
712 const std::vector< index_t >& edges =
713 edges_around_vertices[v_to_id];
714 if( edges.size() == 2 )
717 for(
auto edge : edges )
719 if( !edge_visited[edge] )
721 S_part.emplace( conformal_mesh, edge, v_to_id );
729 well_part_points.push_back( v_to );
730 create_well_part_and_corners( *
geomodel(), new_well,
731 well_part_points, vertex_info[cur_edge.vertex_from_],
732 vertex_info[v_to_id] );
733 for(
auto edge : edges )
735 S.emplace( conformal_mesh, edge, v_to_id );
738 }
while( !S_part.empty() );
739 }
while( !S.empty() );
742 template < index_t DIMENSION >
747 if(
well( w ).name() == name )
index_t part_region_id(index_t part_id) const
index_t find_corner(const vecn< DIMENSION > &vertex, double epsilon) const
index_t find_well(const std::string &name) const
GEO::vecng< DIMENSION, double > vecn
void get_region_edges(index_t part_id, std::vector< Edge< DIMENSION > > &edges) const
static std::unique_ptr< LineMeshBuilder > create_builder(LineMesh< DIMENSION > &mesh)
std::vector< index_t > part_region_id_
Vector of the region id of the parts.
static std::unique_ptr< PointSetMeshBuilder< DIMENSION > > create_builder(PointSetMesh< DIMENSION > &mesh)
std::vector< Well< DIMENSION > *> wells_
Vector of the wells.
std::unique_ptr< LineMesh< DIMENSION > > mesh_
WellEntity(const Well< DIMENSION > *well)
void ringmesh_unused(const T &)
index_t create_part(index_t region)
index_t id_
The id of the corresponding surface or region.
void copy_corners_and_informations(Well< DIMENSION > &well) const
std::array< index_t, 2 > corners_
id in the corners_ vector the the well
GEO::AttributesManager & vertex_attribute_manager() const
const vecn< DIMENSION > & edge_vertex(const ElementLocalVertex &well_edge_local_vertex) const
const Well< DIMENSION > & well(index_t w) const
index_t corner(index_t c) const
void get_region_edges(index_t region, std::vector< Edge< DIMENSION > > &edges) const
void compute_conformal_mesh(const LineMesh< DIMENSION > &in, LineMesh< DIMENSION > &out)
const WellCorner< DIMENSION > & corner(index_t c) const
index_t nb_corners() const
void get_part_edges(index_t part_id, std::vector< Edge< DIMENSION > > &edges) const
const vecn< DIMENSION > & point() const
void set_points(const std::vector< vecn< DIMENSION > > &points)
void set_corner(index_t c, index_t id)
std::unique_ptr< PointSetMesh< DIMENSION > > mesh_
const NNSearch< DIMENSION > & vertices_nn_search() const
index_t create_corner(const vecn< DIMENSION > &vertex, bool is_on_surface, index_t id)
std::tuple< bool, vec3 > RINGMESH_API segment_triangle(const Geometry::Segment3D &segment, const Geometry::Triangle3D &triangle)
#define ringmesh_assert(x)
index_t nb_vertices() const
const WellPart< DIMENSION > & part(index_t part_id) const
WellPart(const Well< DIMENSION > *well, index_t id)
std::string name_
Name of the well.
index_t nb_edges_
Number of edges in the well.
void create_wells(index_t nb_wells)
GEO::AttributesManager & edge_attribute_manager() const
Classes to build GeoModel from various inputs.
const vecn< DIMENSION > & vertex(index_t v) const
const GeoModel< DIMENSION > * geomodel() const
std::vector< std::unique_ptr< WellPart< DIMENSION > > > parts_
Vector of the parts of the well.
void indirect_sort(std::vector< T1 > &input, std::vector< T2 > &output)
Bubble sorting of input and output vectors according to values of input.
GeoModel< DIMENSION > * geomodel_
Associated GeoModel.
This template is a specialization of a gme_id to the GeoModelMeshEntity.
bool inexact_equal(const vecn< DIMENSION > &v1, const vecn< DIMENSION > &v2, double epsilon)
GEO::AttributesManager & vertex_attribute_manager() const
void add_well(const LineMesh< DIMENSION > &mesh, const std::string &name)
std::vector< std::unique_ptr< WellCorner< DIMENSION > > > corners_
Vector of the corners of the well.
WellCorner(const Well< DIMENSION > *well, const vecn< DIMENSION > &point, bool is_on_surface, index_t id)