RINGMesh  Version 5.0.0
A programming library for geological model meshes
geomodel_builder_geometry.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2017, Association Scientifique pour la Geologie et ses
3  * Applications (ASGA). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ASGA nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ASGA BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * http://www.ring-team.org
28  *
29  * RING Project
30  * Ecole Nationale Superieure de Geologie - GeoRessources
31  * 2 Rue du Doyen Marcel Roubault - TSA 70605
32  * 54518 VANDOEUVRE-LES-NANCY
33  * FRANCE
34  */
35 
37 
38 #include <geogram/basic/attributes.h>
39 
41 
43 
44 namespace
45 {
46  using namespace RINGMesh;
47 
48  template < index_t DIMENSION >
49  std::set< index_t > get_internal_borders(
50  const GeoModelMeshEntity< DIMENSION >& entity )
51  {
52  std::set< index_t > internal_borders;
53  for( auto i : range( entity.nb_boundaries() ) )
54  {
55  const GeoModelMeshEntity< DIMENSION >& border =
56  entity.boundary( i );
57  if( border.is_inside_border( entity ) )
58  {
59  internal_borders.insert( border.index() );
60  }
61  }
62  return internal_borders;
63  }
64 
75  template < index_t DIMENSION >
76  std::tuple< bool, index_t, index_t > find_polygon_from_edge_vertices(
77  const Surface< DIMENSION >& surface,
78  const vecn< DIMENSION >& v0,
79  const vecn< DIMENSION >& v1 )
80  {
81  index_t polygon = NO_ID;
82  index_t edge = NO_ID;
83  vecn< DIMENSION > v_bary = 0.5 * ( v0 + v1 );
84  bool result = false;
85  surface.polygon_nn_search().get_neighbors( v_bary,
86  [&surface, &v0, &v1, &result, &edge, &polygon]( index_t i ) {
87  for( auto j : range( surface.nb_mesh_element_vertices( i ) ) )
88  {
90  ElementLocalVertex( i, j ) ),
91  v0, surface.geomodel().epsilon() ) )
92  {
93  index_t j_next = surface.mesh()
94  .next_polygon_vertex(
95  ElementLocalVertex( i, j ) )
96  .local_vertex_id_;
97  if( inexact_equal(
98  surface.mesh_element_vertex(
99  ElementLocalVertex( i, j_next ) ),
100  v1, surface.geomodel().epsilon() ) )
101  {
102  edge = j;
103  polygon = i;
104  result = true;
105  break;
106  }
107  }
108  }
109  return result;
110  } );
111  return std::make_tuple( result, polygon, edge );
112  }
113 
114  template < index_t DIMENSION >
115  bool are_cell_facet_and_polygon_equal( const Region< DIMENSION >& region,
116  index_t cell,
117  index_t cell_facet,
118  const Surface< DIMENSION >& surface,
119  index_t polygon )
120  {
121  index_t nb_cell_facet_vertices =
122  region.nb_cell_facet_vertices( cell, cell_facet );
123  index_t nb_polygon_vertices =
124  surface.nb_mesh_element_vertices( polygon );
125  if( nb_cell_facet_vertices != nb_polygon_vertices )
126  {
127  return false;
128  }
129  vec3 cell_facet_barycenter = region.mesh().cell_facet_barycenter(
130  CellLocalFacet( cell, cell_facet ) );
131  vec3 polygon_barycenter = surface.mesh_element_barycenter( polygon );
132  return inexact_equal( cell_facet_barycenter, polygon_barycenter,
133  region.geomodel().epsilon() );
134  }
135 
136  template < index_t DIMENSION >
137  std::tuple< bool, index_t, index_t > find_cell_facet_from_polygon(
138  const Region< DIMENSION >& region,
139  const Surface< DIMENSION >& surface,
140  index_t polygon )
141  {
142  index_t cell = NO_ID;
143  index_t cell_facet = NO_ID;
144  vec3 v_bary = surface.mesh_element_barycenter( polygon );
145  bool result = false;
146  region.cell_nn_search().get_neighbors(
147  v_bary, [&region, &surface, polygon, &result, &cell_facet, &cell](
148  index_t i ) {
149  for( auto cell_facet_i : range( region.nb_cell_facets( i ) ) )
150  {
151  if( are_cell_facet_and_polygon_equal(
152  region, i, cell_facet_i, surface, polygon ) )
153  {
154  cell_facet = cell_facet_i;
155  cell = i;
156  result = true;
157  break;
158  }
159  }
160  return result;
161  } );
162  return std::make_tuple( result, cell, cell_facet );
163  }
164 
165  template < index_t DIMENSION >
166  bool find_polygon_from_vertex( const Surface< DIMENSION >& surface,
167  const vecn< DIMENSION >& v,
168  index_t& element_id,
169  index_t& vertex_id )
170  {
171  bool result = false;
172  surface.polygon_nn_search().get_neighbors(
173  v, [&surface, &v, &result, &vertex_id, &element_id]( index_t i ) {
174  for( auto j : range( surface.nb_mesh_element_vertices( i ) ) )
175  {
176  if( inexact_equal( surface.mesh_element_vertex(
177  ElementLocalVertex( i, j ) ),
178  v, surface.geomodel().epsilon() ) )
179  {
180  vertex_id = surface.mesh_element_vertex_index(
181  ElementLocalVertex( i, j ) );
182  element_id = i;
183  result = true;
184  break;
185  }
186  }
187  return result;
188  } );
189  return result;
190  }
191 
192  template < index_t DIMENSION >
193  index_t edge_index_from_polygon_and_edge_vertex_indices(
194  const Surface< DIMENSION >& surface,
195  index_t p,
196  const vecn< DIMENSION >& v0,
197  const vecn< DIMENSION >& v1 )
198  {
199  const SurfaceMesh< DIMENSION >& mesh = surface.mesh();
200  for( auto v : range( surface.nb_mesh_element_vertices( p ) ) )
201  {
202  if( !inexact_equal( surface.mesh_element_vertex( { p, v } ), v0,
203  surface.geomodel().epsilon() ) )
204  {
205  continue;
206  }
207  index_t prev_v =
208  mesh.prev_polygon_vertex( { p, v } ).local_vertex_id_;
209  index_t next_v =
210  mesh.next_polygon_vertex( { p, v } ).local_vertex_id_;
211  if( inexact_equal( surface.mesh_element_vertex( { p, prev_v } ), v1,
212  surface.geomodel().epsilon() ) )
213  {
214  return prev_v;
215  }
216  if( inexact_equal( surface.mesh_element_vertex( { p, next_v } ), v1,
217  surface.geomodel().epsilon() ) )
218  {
219  return v;
220  }
221  }
222  return NO_ID;
223  }
224 
225  template < index_t DIMENSION >
226  index_t cell_facet_index_from_cell_and_polygon(
227  const Region< DIMENSION >& region,
228  index_t cell,
229  const Surface< DIMENSION >& surface,
230  index_t polygon )
231  {
232  const VolumeMesh< DIMENSION >& mesh = region.mesh();
233  vec3 polygon_barycenter = surface.mesh_element_barycenter( polygon );
234  for( auto f : range( region.nb_cell_facets( cell ) ) )
235  {
236  vec3 cell_facet_barycenter =
237  mesh.cell_facet_barycenter( CellLocalFacet( cell, f ) );
238  if( inexact_equal( cell_facet_barycenter, polygon_barycenter,
239  surface.geomodel().epsilon() ) )
240  {
241  return f;
242  }
243  }
244  return NO_ID;
245  }
246 
247  template < index_t DIMENSION >
248  void check_and_initialize_corner_vertex(
249  GeoModel< DIMENSION >& geomodel, index_t corner_id )
250  {
251  if( geomodel.corner( corner_id ).nb_vertices() == 0 )
252  {
253  GeoModelBuilder< DIMENSION > builder( geomodel );
254  builder.geometry.create_mesh_entity_vertices(
256  1 );
257  }
258  }
259 } // namespace
260 
261 namespace RINGMesh
262 {
263  template < index_t DIMENSION >
266  : builder_( builder ),
267  geomodel_( geomodel ),
268  geomodel_access_( geomodel )
269  {
270  }
271 
272  template < index_t DIMENSION >
274  {
275  geomodel_.mesh.vertices.clear();
276  }
277 
278  template < index_t DIMENSION >
280  const GeoModel< DIMENSION >& geomodel )
281  {
282  copy_meshes( geomodel, Corner< DIMENSION >::type_name_static() );
283  copy_meshes( geomodel, Line< DIMENSION >::type_name_static() );
284  copy_meshes( geomodel, Surface< DIMENSION >::type_name_static() );
285  }
286 
287  template < index_t DIMENSION >
289  const gmme_id& t,
290  index_t v,
291  const vecn< DIMENSION >& point,
292  bool update )
293  {
295  geomodel_access_.modifiable_mesh_entity( t );
296  GeoModelMeshVertices< DIMENSION >& geomodel_vertices =
297  geomodel_.mesh.vertices;
298  ringmesh_assert( v < E.nb_vertices() );
299  if( update )
300  {
301  geomodel_vertices.update_point(
302  geomodel_vertices.geomodel_vertex_id( E.gmme(), v ), point );
303  }
304  else
305  {
306  GeoModelMeshEntityAccess< DIMENSION > gmme_access( E );
307  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
309  *gmme_access.modifiable_mesh() );
310  builder->set_vertex( v, point );
311  }
312  }
313 
314  template < index_t DIMENSION >
316  const gmme_id& entity_id, index_t v, index_t geomodel_vertex )
317  {
318  GeoModelMeshVertices< DIMENSION >& geomodel_vertices =
319  geomodel_.mesh.vertices;
320  set_mesh_entity_vertex(
321  entity_id, v, geomodel_vertices.vertex( geomodel_vertex ), false );
322 
323  ringmesh_assert( v < geomodel_.mesh_entity( entity_id ).nb_vertices() );
324  geomodel_vertices.update_vertex_mapping(
325  entity_id, v, geomodel_vertex );
326  }
327 
328  template < index_t DIMENSION >
330  const gmme_id& id,
331  const std::vector< vecn< DIMENSION > >& points,
332  bool clear )
333  {
335  geomodel_access_.modifiable_mesh_entity( id );
336  GeoModelMeshEntityAccess< DIMENSION > gmme_access( E );
337  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
339  *gmme_access.modifiable_mesh() );
340  // Clear the mesh, but keep the attributes and the space
341  if( clear )
342  {
343  builder->clear( true, true );
344  }
345  if( !points.empty() )
346  {
347  auto nb_points = static_cast< index_t >( points.size() );
348  index_t start = builder->create_vertices( nb_points );
349  for( auto v : range( nb_points ) )
350  {
351  builder->set_vertex( start + v, points[v] );
352  }
353  }
354  }
355 
356  template < index_t DIMENSION >
357  index_t
359  const gmme_id& entity_id, index_t nb_vertices )
360  {
362  geomodel_access_.modifiable_mesh_entity( entity_id );
363  GeoModelMeshEntityAccess< DIMENSION > gmme_access( E );
364  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
366  *gmme_access.modifiable_mesh() );
367  return builder->create_vertices( nb_vertices );
368  }
369 
370  template < index_t DIMENSION >
372  const gmme_id& entity_id,
373  const std::vector< index_t >& geomodel_vertices,
374  bool clear )
375  {
377  geomodel_access_.modifiable_mesh_entity( entity_id );
378  GeoModelMeshEntityAccess< DIMENSION > gmme_access( E );
379  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
381  *gmme_access.modifiable_mesh() );
382  // Clear the mesh, but keep the attributes and the space
383  if( clear )
384  {
385  builder->clear( true, true );
386  }
387  auto nb_model_vertices =
388  static_cast< index_t >( geomodel_vertices.size() );
389  index_t start = builder->create_vertices( nb_model_vertices );
390  for( auto v : range( nb_model_vertices ) )
391  {
392  set_mesh_entity_vertex(
393  entity_id, start + v, geomodel_vertices[v] );
394  }
395  }
396 
397  template < index_t DIMENSION >
399  index_t corner_id, const vecn< DIMENSION >& point )
400  {
401  check_and_initialize_corner_vertex( geomodel_, corner_id );
402  set_mesh_entity_vertex(
404  point, false );
405  }
406 
407  template < index_t DIMENSION >
409  index_t line_id, const std::vector< vecn< DIMENSION > >& vertices )
410  {
411  set_mesh_entity_vertices(
412  gmme_id( Line< DIMENSION >::type_name_static(), line_id ), vertices,
413  true );
414 
415  auto& line = dynamic_cast< Line< DIMENSION >& >(
416  geomodel_access_.modifiable_mesh_entity(
418  std::unique_ptr< LineMeshBuilder< DIMENSION > > builder =
419  create_line_builder( line_id );
420  for( auto e : range( 1, line.nb_vertices() ) )
421  {
422  builder->create_edge( e - 1, e );
423  }
424  }
425 
426  template < index_t DIMENSION >
428  index_t surface_id,
429  const std::vector< vecn< DIMENSION > >& surface_vertices,
430  const std::vector< index_t >& surface_polygons,
431  const std::vector< index_t >& surface_polygon_ptr )
432  {
433  set_mesh_entity_vertices(
435  surface_vertices, true );
436  set_surface_geometry(
437  surface_id, surface_polygons, surface_polygon_ptr );
438  }
439 
440  template < index_t DIMENSION >
442  index_t surface_id,
443  const std::vector< index_t >& polygons,
444  const std::vector< index_t >& polygon_ptr )
445  {
446  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
447  create_surface_builder( surface_id );
448  builder->create_polygons( polygons, polygon_ptr );
449  compute_surface_adjacencies( surface_id );
450  }
451 
452  template < index_t DIMENSION >
454  index_t corner_id, index_t geomodel_vertex_id )
455  {
456  check_and_initialize_corner_vertex( geomodel_, corner_id );
457  set_mesh_entity_vertex(
459  geomodel_vertex_id );
460  }
461 
462  template < index_t DIMENSION >
464  index_t line_id, const std::vector< index_t >& unique_vertices )
465  {
466  bool clear_vertices = false;
468  geomodel_access_.modifiable_mesh_entity(
470 
471  ringmesh_assert( E.nb_vertices() == 0 );
472  // If there are already some vertices
473  // we are doomed because they are not removed
475  set_mesh_entity_vertices( E.gmme(), unique_vertices, clear_vertices );
476 
477  std::unique_ptr< LineMeshBuilder< DIMENSION > > builder =
478  create_line_builder( line_id );
479  for( auto e : range( 1, E.nb_vertices() ) )
480  {
481  builder->create_edge( e - 1, e );
482  }
483  }
484 
485  template < index_t DIMENSION >
487  index_t surface_id,
488  index_t polygon_id,
489  const std::vector< index_t >& corners )
490  {
491  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
492  create_surface_builder( surface_id );
493  for( auto polygon_vertex : range( corners.size() ) )
494  {
495  builder->set_polygon_vertex(
496  PolygonLocalEdge( polygon_id, polygon_vertex ),
497  corners[polygon_vertex] );
498  }
499  }
500 
501  template < index_t DIMENSION >
503  index_t surface_id, const std::vector< index_t >& vertex_indices )
504  {
505  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
506  create_surface_builder( surface_id );
507  return builder->create_polygon( vertex_indices );
508  }
509 
510  template < index_t DIMENSION >
512  const gmme_id& E_id )
513  {
515  geomodel_access_.modifiable_mesh_entity( E_id ) );
516  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
518  *gmme_access.modifiable_mesh() );
519  builder->clear( true, false );
520  }
521 
522  template < index_t DIMENSION >
525  {
526  if( geomodel_.entity_type_manager().mesh_entity_manager.is_line(
527  E_id.type() ) )
528  {
529  std::unique_ptr< LineMeshBuilder< DIMENSION > > builder =
530  create_line_builder( E_id.index() );
531  builder->remove_isolated_vertices();
532  }
533  else if( geomodel_.entity_type_manager().mesh_entity_manager.is_surface(
534  E_id.type() ) )
535  {
536  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
537  create_surface_builder( E_id.index() );
538  builder->remove_isolated_vertices();
539  }
540  else if( geomodel_.entity_type_manager().mesh_entity_manager.is_corner(
541  E_id.type() ) )
542  {
543  std::unique_ptr< PointSetMeshBuilder< DIMENSION > > builder =
544  create_corner_builder( E_id.index() );
545  builder->remove_isolated_vertices();
546  }
547  else
548  {
550  }
551  }
552 
553  template < index_t DIMENSION >
555  const gmme_id& E_id, const std::vector< bool >& to_delete )
556  {
558  geomodel_access_.modifiable_mesh_entity( E_id ) );
559  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
561  *gmme_access.modifiable_mesh() );
562  builder->delete_vertices( to_delete );
563  }
564 
565  template < index_t DIMENSION >
567  index_t corner_id )
568  {
569  gmme_id corner( Corner< DIMENSION >::type_name_static(), corner_id );
570  std::vector< bool > to_delete;
571  to_delete.push_back( true );
572  delete_mesh_entity_vertices( corner, to_delete );
573  }
574  template < index_t DIMENSION >
576  index_t line_id,
577  const std::vector< bool >& to_delete,
578  bool remove_isolated_vertices )
579  {
580  std::unique_ptr< LineMeshBuilder< DIMENSION > > builder =
581  create_line_builder( line_id );
582  builder->delete_edges( to_delete, remove_isolated_vertices );
583  }
584  template < index_t DIMENSION >
586  index_t surface_id,
587  const std::vector< bool >& to_delete,
588  bool remove_isolated_vertices )
589  {
590  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
591  create_surface_builder( surface_id );
592  builder->delete_polygons( to_delete, remove_isolated_vertices );
593  }
594 
595  template < index_t DIMENSION >
596  void
598  index_t surface_id,
599  index_t polygon_id,
600  const std::vector< index_t >& adjacents )
601  {
602  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
603  create_surface_builder( surface_id );
604  for( auto polygon_edge : range( adjacents.size() ) )
605  {
606  builder->set_polygon_adjacent(
607  PolygonLocalEdge( polygon_id, polygon_edge ),
608  adjacents[polygon_edge] );
609  }
610  }
611 
612  template < index_t DIMENSION >
614  index_t surface_id, bool recompute_adjacency )
615  {
616  const Surface< DIMENSION >& surface = geomodel_.surface( surface_id );
617  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
618  create_surface_builder( surface_id );
619 
620  if( recompute_adjacency )
621  {
622  for( auto p : range( surface.nb_mesh_elements() ) )
623  {
624  for( auto v : range( surface.nb_mesh_element_vertices( p ) ) )
625  {
626  builder->set_polygon_adjacent(
627  PolygonLocalEdge( p, v ), NO_ID );
628  }
629  }
630  }
631  builder->connect_polygons();
632  }
633 
634  template < index_t DIMENSION >
637  {
638  for( const auto& surface : geomodel_.surfaces() )
639  {
640  std::set< index_t > cutting_lines = get_internal_borders( surface );
641  for( auto line_id : cutting_lines )
642  {
643  cut_surface_by_line( surface.index(), line_id );
644  }
645  if( !cutting_lines.empty() )
646  {
647  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > >
648  surface_mesh_builder =
649  create_surface_builder( surface.index() );
650  surface_mesh_builder->remove_isolated_vertices();
651  }
652  }
653  }
654 
655  template < index_t DIMENSION >
657  index_t surface_id, index_t line_id )
658  {
659  index_t nb_disconnected_edges =
660  disconnect_surface_polygons_along_line_edges( surface_id, line_id );
661  if( nb_disconnected_edges > 0 )
662  {
663  duplicate_surface_vertices_along_line( surface_id, line_id );
664  }
665  }
666 
668  {
669  index_t element_;
670  index_t vertex_;
671  };
672 
673  template < index_t DIMENSION >
676  index_t surface_id, index_t line_id )
677  {
678  ringmesh_assert( surface_id < geomodel_.nb_surfaces() );
679  ringmesh_assert( line_id < geomodel_.nb_lines() );
680 
681  gmme_id surface_gme(
683  const Surface< DIMENSION >& surface = geomodel_.surface( surface_id );
684  const Line< DIMENSION >& line = geomodel_.line( line_id );
685 
686  std::vector< ElementVertex > polygon_vertices( line.nb_vertices() );
687  for( auto v : range( line.nb_vertices() ) )
688  {
689  const vecn< DIMENSION >& p = line.vertex( v );
690 
691  index_t& polygon_vertex = polygon_vertices[v].vertex_;
692  index_t& polygon = polygon_vertices[v].element_;
693  bool found =
694  find_polygon_from_vertex( surface, p, polygon, polygon_vertex );
695  ringmesh_unused( found );
697  found && polygon != NO_ID && polygon_vertex != NO_ID );
698  }
699 
700  index_t vertex_id =
701  create_mesh_entity_vertices( surface_gme, line.nb_vertices() );
702  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > >
703  surface_mesh_builder = create_surface_builder( surface_id );
704  const SurfaceMesh< DIMENSION >& mesh = surface.mesh();
705  for( auto v : range( line.nb_vertices() ) )
706  {
707  const vecn< DIMENSION >& p = line.vertex( v );
708  const index_t& polygon_vertex = polygon_vertices[v].vertex_;
709  const index_t& polygon = polygon_vertices[v].element_;
710 
711  std::vector< index_t > polygons =
712  mesh.polygons_around_vertex( polygon_vertex, false, polygon );
713  update_polygon_vertex(
714  surface_id, polygons, polygon_vertex, vertex_id );
715  surface_mesh_builder->set_vertex( vertex_id, p );
716  vertex_id++;
717  }
718  }
719 
720  template < index_t DIMENSION >
723  index_t surface_id, index_t line_id )
724  {
725  ringmesh_assert( surface_id < geomodel_.nb_surfaces() );
726  ringmesh_assert( line_id < geomodel_.nb_lines() );
727 
728  const Surface< DIMENSION >& surface = geomodel_.surface( surface_id );
729  const Line< DIMENSION >& line = geomodel_.line( line_id );
730  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
731  create_surface_builder( surface_id );
732  index_t nb_disconnected_edges{ 0 };
733  for( auto i : range( line.nb_mesh_elements() ) )
734  {
735  const vecn< DIMENSION >& p0 = line.vertex( i );
736  const vecn< DIMENSION >& p1 = line.vertex( i + 1 );
737 
738  bool found = false;
739  index_t p = NO_ID;
740  index_t e = NO_ID;
741  std::tie( found, p, e ) =
742  find_polygon_from_edge_vertices( surface, p0, p1 );
743  ringmesh_unused( found );
744  ringmesh_assert( found && p != NO_ID && e != NO_ID );
745 
746  index_t adj_f =
747  surface.polygon_adjacent_index( PolygonLocalEdge( p, e ) );
748  if( adj_f != NO_ID )
749  {
750  index_t adj_e = edge_index_from_polygon_and_edge_vertex_indices(
751  surface, adj_f, p0, p1 );
752  ringmesh_assert( adj_e != NO_ID );
753  builder->set_polygon_adjacent(
754  PolygonLocalEdge( p, e ), NO_ID );
755  builder->set_polygon_adjacent(
756  PolygonLocalEdge( adj_f, adj_e ), NO_ID );
757  nb_disconnected_edges++;
758  }
759  }
760  return nb_disconnected_edges;
761  }
762  template < index_t DIMENSION >
764  index_t surface_id,
765  const std::vector< index_t >& polygons,
766  index_t old_vertex,
767  index_t new_vertex )
768  {
769  const Surface< DIMENSION >& surface = geomodel_.surface( surface_id );
770  std::unique_ptr< SurfaceMeshBuilder< DIMENSION > > builder =
771  create_surface_builder( surface_id );
772  for( auto cur_p : polygons )
773  {
774  for( auto cur_v :
775  range( surface.nb_mesh_element_vertices( cur_p ) ) )
776  {
777  if( surface.mesh_element_vertex_index(
778  ElementLocalVertex( cur_p, cur_v ) )
779  == old_vertex )
780  {
781  builder->set_polygon_vertex(
782  PolygonLocalEdge( cur_p, cur_v ), new_vertex );
783  }
784  }
785  }
786  }
787  template < index_t DIMENSION >
789  const GeoModel< DIMENSION >& from, const MeshEntityType& entity_type )
790  {
791  for( auto i : range( geomodel_.nb_mesh_entities( entity_type ) ) )
792  {
793  copy_mesh( from, gmme_id( entity_type, i ) );
794  }
795  }
796 
797  template < index_t DIMENSION >
799  const GeoModel< DIMENSION >& from, const gmme_id& mesh_entity )
800  {
801  const GeoModelMeshEntityConstAccess< DIMENSION > from_E_const_access(
802  from.mesh_entity( mesh_entity ) );
803  assign_mesh_to_entity( *from_E_const_access.mesh(), mesh_entity );
804  }
805 
806  template < index_t DIMENSION >
808  const MeshBase< DIMENSION >& mesh, const gmme_id& to )
809  {
811  geomodel_access_.modifiable_mesh_entity( to );
812  GeoModelMeshEntityAccess< DIMENSION > gmme_access( E );
813  std::unique_ptr< MeshBaseBuilder< DIMENSION > > builder =
815  *gmme_access.modifiable_mesh() );
816  builder->copy( mesh, true );
817  }
818 
820  const std::vector< index_t >& cells,
821  index_t old_vertex,
822  index_t new_vertex )
823  {
824  const Region3D& region = geomodel_.region( region_id );
825  std::unique_ptr< VolumeMeshBuilder3D > builder =
826  create_region_builder( region_id );
827  for( auto cur_c : cells )
828  {
829  for( auto cur_v :
830  range( region.nb_mesh_element_vertices( cur_c ) ) )
831  {
832  if( region.mesh_element_vertex_index(
833  ElementLocalVertex( cur_c, cur_v ) )
834  == old_vertex )
835  {
836  builder->set_cell_vertex(
837  ElementLocalVertex( cur_c, cur_v ), new_vertex );
838  }
839  }
840  }
841  }
842 
844  index_t region_id, const std::vector< index_t >& tet_vertices )
845  {
846  std::unique_ptr< VolumeMeshBuilder3D > builder =
847  create_region_builder( region_id );
848  builder->assign_cell_tet_mesh( tet_vertices );
849  builder->connect_cells();
850  }
851 
854  index_t region_id, index_t surface_id )
855  {
856  ringmesh_assert( region_id < geomodel_.nb_regions() );
857  ringmesh_assert( surface_id < geomodel_.nb_surfaces() );
858 
859  const Region3D& region = geomodel_.region( region_id );
860  const Surface3D& surface = geomodel_.surface( surface_id );
861  std::unique_ptr< VolumeMeshBuilder3D > builder =
862  create_region_builder( region_id );
863  index_t nb_disconnected_polygons{ 0 };
864  for( auto polygon : range( surface.nb_mesh_elements() ) )
865  {
866  bool found = false;
867  index_t cell = NO_ID;
868  index_t cell_facet = NO_ID;
869  std::tie( found, cell, cell_facet ) =
870  find_cell_facet_from_polygon( region, surface, polygon );
871  ringmesh_unused( found );
872  ringmesh_assert( found && cell != NO_ID && cell_facet != NO_ID );
873 
874  index_t adj_cell = region.cell_adjacent_index( cell, cell_facet );
875  if( adj_cell != NO_ID )
876  {
877  index_t adj_cell_facet = cell_facet_index_from_cell_and_polygon(
878  region, adj_cell, surface, polygon );
879  ringmesh_assert( adj_cell_facet != NO_ID );
880  builder->set_cell_adjacent(
881  CellLocalFacet( cell, cell_facet ), NO_ID );
882  builder->set_cell_adjacent(
883  CellLocalFacet( adj_cell, adj_cell_facet ), NO_ID );
884  nb_disconnected_polygons++;
885  }
886  }
887  return nb_disconnected_polygons;
888  }
889 
891  index_t region_id, index_t surface_id )
892  {
893  ringmesh_assert( region_id < geomodel_.nb_regions() );
894  ringmesh_assert( surface_id < geomodel_.nb_surfaces() );
895 
896  gmme_id region_gme( Region3D::type_name_static(), region_id );
897  const Region3D& region = geomodel_.region( region_id );
898  const Surface3D& surface = geomodel_.surface( surface_id );
899 
900  std::vector< ElementVertex > cell_vertices( surface.nb_vertices() );
901  for( auto v : range( surface.nb_vertices() ) )
902  {
903  const vec3& p = surface.vertex( v );
904 
905  index_t& cell = cell_vertices[v].element_;
906  index_t& cell_vertex = cell_vertices[v].vertex_;
907  ElementLocalVertex element_local_vertex =
908  region.find_cell_from_colocated_vertex_if_any( p );
909  cell = element_local_vertex.element_id_;
910  cell_vertex = element_local_vertex.local_vertex_id_;
911 
912  ringmesh_assert( cell != NO_ID && cell_vertex != NO_ID );
913  }
914 
915  GEO::vector< std::string > names;
916  geomodel_.region( region_id )
917  .vertex_attribute_manager()
918  .list_attribute_names( names );
919 
920  GeoModelMeshEntity3D& E =
921  geomodel_access_.modifiable_mesh_entity( region_gme );
922  index_t vertices_nb = E.nb_vertices();
923 
924  index_t vertex_id =
925  create_mesh_entity_vertices( region_gme, surface.nb_vertices() );
926 
927  std::unique_ptr< VolumeMeshBuilder3D > region_mesh_builder =
928  create_region_builder( region_id );
929  const VolumeMesh3D& mesh = region.mesh();
930  for( auto v : range( surface.nb_vertices() ) )
931  {
932  const vec3& p = surface.vertex( v );
933  const index_t& cell = cell_vertices[v].element_;
934  const index_t& cell_vertex = cell_vertices[v].vertex_;
935 
936  std::vector< index_t > cells =
937  mesh.cells_around_vertex( cell_vertex, cell );
938  update_cell_vertex( region_id, cells, cell_vertex, vertex_id );
939  region_mesh_builder->set_vertex( vertex_id, p );
940  vertex_id++;
941 
942  for( const auto& name : names )
943  {
944  if( name != "model_vertex_map" && name != "point" )
945  {
946  GEO::Attribute< double > attr(
947  geomodel_.region( region_id )
948  .vertex_attribute_manager(),
949  name );
950  index_t dim_nb = attr.dimension();
951  for( auto dim : range( dim_nb ) )
952  {
953  attr[( vertices_nb + v ) * dim_nb + dim] =
954  attr[cell_vertex * dim_nb + dim];
955  }
956  }
957  }
958  }
959  }
960 
962  index_t region_id, index_t surface_id )
963  {
964  index_t nb_disconnected_polygons =
965  disconnect_region_cells_along_surface_polygons(
966  region_id, surface_id );
967  if( nb_disconnected_polygons > 0 )
968  {
969  duplicate_region_vertices_along_surface( region_id, surface_id );
970  }
971  }
972 
974  {
975  for( const auto& region : geomodel_.regions() )
976  {
977  if( region.nb_mesh_elements() == 0 )
978  {
979  continue;
980  }
981  std::set< index_t > cutting_surfaces =
982  get_internal_borders( region );
983  for( auto surface_id : cutting_surfaces )
984  {
985  cut_region_by_surface( region.index(), surface_id );
986  }
987  if( !cutting_surfaces.empty() )
988  {
989  std::unique_ptr< VolumeMeshBuilder3D > region_mesh_builder =
990  create_region_builder( region.index() );
991  region_mesh_builder->remove_isolated_vertices();
992  }
993  }
994  }
995 
997  const std::vector< vec3 >& points,
998  const std::vector< index_t >& tetras )
999  {
1000  set_mesh_entity_vertices(
1001  gmme_id( Region3D::type_name_static(), region_id ), points, true );
1002  assign_region_tet_mesh( region_id, tetras );
1003  }
1004 
1006  index_t region_id, bool recompute_adjacency )
1007  {
1008  const Region3D& region = geomodel_.region( region_id );
1009  std::unique_ptr< VolumeMeshBuilder3D > builder =
1010  create_region_builder( region_id );
1011  if( recompute_adjacency )
1012  {
1013  for( auto c : range( region.nb_mesh_elements() ) )
1014  {
1015  for( auto f : range( region.nb_cell_facets( c ) ) )
1016  {
1017  builder->set_cell_adjacent( CellLocalFacet( c, f ), NO_ID );
1018  }
1019  }
1020  }
1021  builder->connect_cells();
1022  }
1023 
1025  const std::vector< bool >& to_delete,
1026  bool remove_isolated_vertices )
1027  {
1028  std::unique_ptr< VolumeMeshBuilder3D > builder =
1029  create_region_builder( region_id );
1030  builder->delete_cells( to_delete, remove_isolated_vertices );
1031  }
1032 
1034  index_t region_id, CellType type, index_t nb_cells )
1035  {
1036  std::unique_ptr< VolumeMeshBuilder3D > builder =
1037  create_region_builder( region_id );
1038  return builder->create_cells( nb_cells, type );
1039  }
1040 
1042  index_t region_id,
1043  index_t cell_id,
1044  const std::vector< index_t >& corners )
1045  {
1046  std::unique_ptr< VolumeMeshBuilder3D > builder =
1047  create_region_builder( region_id );
1048  for( auto cell_vertex : range( corners.size() ) )
1049  {
1050  builder->set_cell_vertex(
1051  ElementLocalVertex( cell_id, cell_vertex ),
1052  corners[cell_vertex] );
1053  }
1054  }
1056  const gmme_id& E_id )
1057  {
1058  if( geomodel_.entity_type_manager().mesh_entity_manager.is_region(
1059  E_id.type() ) )
1060  {
1061  std::unique_ptr< VolumeMeshBuilder3D > builder =
1062  create_region_builder( E_id.index() );
1063  builder->remove_isolated_vertices();
1064  }
1065  else
1066  {
1069  }
1070  }
1071 
1073  CellType type,
1074  const std::vector< index_t >& vertex_indices )
1075  {
1076  index_t cell_id = create_region_cells( region_id, type, 1 );
1077  set_region_element_geometry( region_id, cell_id, vertex_indices );
1078  return cell_id;
1079  }
1080 
1081  void GeoModelBuilderGeometry< 3 >::copy_meshes( const GeoModel3D& geomodel )
1082  {
1083  GeoModelBuilderGeometryBase3D::copy_meshes( geomodel );
1084  GeoModelBuilderGeometryBase3D::copy_meshes(
1085  geomodel, Region3D::type_name_static() );
1086  }
1087 
1088  template class RINGMESH_API GeoModelBuilderGeometry< 2 >;
1089  template class RINGMESH_API GeoModelBuilderGeometryBase< 2 >;
1090 
1091  template class RINGMESH_API GeoModelBuilderGeometryBase< 3 >;
1092 } // namespace RINGMesh
const GeoModel< DIMENSION > & geomodel() const
const VolumeMesh< DIMENSION > & mesh() const
Get the low level mesh data structure.
void update_point(index_t v, const vecn< DIMENSION > &point)
Set the point coordinates of all the vertices that share this unique vertex, including the unique ver...
Abstract base class for GeoModelMeshEntity.
GEO::vecng< DIMENSION, double > vecn
Definition: types.h:74
const NNSearch< DIMENSION > & polygon_nn_search() const
Return the NNSearch for the polygons of the surface.
index_t mesh_element_vertex_index(const ElementLocalVertex &element_local_vertex) const final
Index of the vertex in the Surface from its index in a polygon of the mesh.
void update_vertex_mapping(const gmme_id &entity_id, index_t entity_vertex_index, index_t geomodel_vertex_index)
bool is_inside_border(const GeoModelMeshEntity &rhs) const
Check if this entity is an inside border of rhs.
virtual const vecn< DIMENSION > & vertex(index_t v_id) const =0
Gets a point.
const vecn< DIMENSION > & vertex(index_t vertex_index) const
Coordinates of the vertex_index.
index_t nb_cell_facets(index_t cell_index) const
index_t nb_mesh_element_vertices(index_t polygon_index) const final
virtual const GeoModelMeshEntity< DIMENSION > & mesh_entity(const gmme_id &id) const
Generic access to a meshed entity.
Definition: geomodel.cpp:131
vecn< 3 > vec3
Definition: types.h:76
void ringmesh_unused(const T &)
Definition: common.h:105
A GeoModelEntity of type CORNER.
const Corner< DIMENSION > & corner(index_t index) const
Definition: geomodel.cpp:177
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.
Definition: mesh.cpp:440
void copy(const MeshBase< DIMENSION > &rhs, bool copy_attributes)
Copy a mesh into this one.
Definition: mesh_builder.h:75
Entity_type_template type() const
Definition: entity_type.h:202
const SurfaceMesh< DIMENSION > & mesh() const
Get the low level mesh data structure.
vecn< DIMENSION > mesh_element_barycenter(index_t polygon_index) const final
index_t nb_mesh_elements() const final
index_t nb_mesh_elements() const final
const NNSearch< DIMENSION > & cell_nn_search() const
Return the NNSearch for the cells of the region.
CellType
Definition: types.h:89
index_t create_vertices(index_t nb)
Creates a contiguous chunk of vertices.
Definition: mesh_builder.h:148
void set_vertex(index_t v_id, const vecn< DIMENSION > &vertex)
Sets a point.
Definition: mesh_builder.h:117
const vecn< DIMENSION > & vertex(index_t v) const
Coordinates of a vertex of the GeoModel.
encapsulate adimensional mesh functionalities in order to provide an API on which we base the RINGMes...
Definition: mesh.h:138
ElementLocalVertex prev_polygon_vertex(const ElementLocalVertex &polygon_local_vertex) const
Gets the previous vertex index in the polygon.
Definition: mesh.h:443
GeoModelBuilderGeometryBase(GeoModelBuilder< DIMENSION > &builder, GeoModel< DIMENSION > &geomodel)
index_t nb_cell_facet_vertices(index_t cell_index, index_t facet_index) const
index_t geomodel_vertex_id(const gmme_id &mesh_entity, index_t entity_vertex_index=0) const
Get the GeoModelMesh index of a GeoModelMeshEntity vertex from its index in that GeoModelMeshEntity.
#define ringmesh_assert(x)
vecn< DIMENSION > cell_facet_barycenter(const CellLocalFacet &cell_local_facet) const
Definition: mesh.h:1010
A GeoModelEntity of type REGION.
The MeshEntityType described the type of the meshed entities There are 4 MeshEntityTypes correspondin...
Definition: entity_type.h:117
Classes to build GeoModel from various inputs.
Definition: algorithm.h:48
ElementLocalVertex next_polygon_vertex(const ElementLocalVertex &polygon_local_vertex) const
Gets the next vertex index in the polygon vertex.
Definition: mesh.h:404
A GeoModelEntity of type LINE.
const vecn< DIMENSION > & mesh_element_vertex(const ElementLocalVertex &element_local_vertex) const
Coordinates of a vertex of a mesh element.
index_t nb_mesh_elements() const final
std::vector< index_t > cells_around_vertex(index_t vertex_id, index_t cell_hint) const
Definition: mesh.cpp:636
index_t index() const
Definition: entity_type.h:197
This template is a specialization of a gme_id to the GeoModelMeshEntity.
Definition: entity_type.h:285
bool inexact_equal(const vecn< DIMENSION > &v1, const vecn< DIMENSION > &v2, double epsilon)
Definition: geometry.h:67
void clear(bool keep_attributes, bool keep_memory)
Removes all the entities and attributes of this mesh.
Definition: mesh_builder.h:90
#define ringmesh_assert_not_reached
const GeoModelMeshEntity< DIMENSION > & boundary(index_t x) const
std::shared_ptr< MeshBase< DIMENSION > > & modifiable_mesh()