RINGMesh  Version 5.0.0
A programming library for geological model meshes
geomodel_builder_geology.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 <stack>
39 
41 
43 
50 namespace
51 {
52  using namespace RINGMesh;
53 
54  template < index_t DIMENSION >
55  gmme_id find_corner(
56  const GeoModel< DIMENSION >& geomodel, index_t geomodel_point_id )
57  {
58  const auto& geomodel_vertices = geomodel.mesh.vertices;
59  const auto& vertices =
60  geomodel_vertices.gme_vertices( geomodel_point_id );
61  for( const auto& vertex : vertices )
62  {
63  if( vertex.gmme.type() == Corner< DIMENSION >::type_name_static() )
64  {
65  return vertex.gmme;
66  }
67  }
68  return gmme_id{};
69  }
70 
76  template < index_t DIMENSION >
77  bool line_equal( const Line< DIMENSION >& line,
78  const std::vector< index_t >& rhs_vertices )
79  {
80  if( line.nb_vertices() != rhs_vertices.size() )
81  {
82  return false;
83  }
84  const auto& geomodel_vertices = line.geomodel().mesh.vertices;
85  bool equal = true;
86  for( auto i : range( line.nb_vertices() ) )
87  {
88  if( rhs_vertices[i]
89  != geomodel_vertices.geomodel_vertex_id( line.gmme(), i ) )
90  {
91  equal = false;
92  break;
93  }
94  }
95  if( equal )
96  {
97  return true;
98  }
99  // If the order is the other one
100  equal = true;
101  for( auto i : range( line.nb_vertices() ) )
102  {
103  if( rhs_vertices[i]
104  != geomodel_vertices.geomodel_vertex_id(
105  line.gmme(), line.nb_vertices() - i - 1 ) )
106  {
107  equal = false;
108  break;
109  }
110  }
111  return equal;
112  }
113 
118  template < index_t DIMENSION >
119  void reorder_closed_line_vertices_to_start_at_corner(
120  const GeoModel< DIMENSION >& geomodel,
121  std::vector< index_t >& line_vertices )
122  {
123  if( geomodel.nb_corners() == 0 )
124  {
125  // Maybe should throw an assertion, but I am not sure [JP]
126  // this really may happen for sure, so no throw [RM]
127  return;
128  }
129  if( line_vertices.empty() )
130  {
131  return;
132  }
133  for( auto i : range( 1, line_vertices.size() - 1 ) )
134  {
135  auto corner = find_corner( geomodel, line_vertices[i] );
136  if( corner.is_defined() )
137  {
138  line_vertices.pop_back();
139  std::rotate( line_vertices.begin(), line_vertices.begin() + i,
140  line_vertices.end() );
141  line_vertices.push_back( line_vertices.front() );
142  break;
143  }
144  }
145  }
146 
147 } // namespace
148 
149 namespace RINGMesh
150 {
151  template < index_t DIMENSION >
154  : builder_( builder ),
155  geomodel_( geomodel ),
156  geomodel_access_( geomodel )
157  {
158  }
159 
160  template < index_t DIMENSION >
162  const GeoModel< DIMENSION >& from )
163  {
164  for( auto t : range( from.nb_geological_entity_types() ) )
165  {
166  builder_.geology.copy_geological_entity_topology(
167  from, from.geological_entity_type( t ) );
168  }
169  }
170 
171  template < index_t DIMENSION >
173  const GeologicalEntityType& type, index_t nb_additional_entities )
174  {
176  auto& store = geomodel_access_.modifiable_geological_entities( type );
177  auto old_size = static_cast< index_t >( store.size() );
178  auto new_size = old_size + nb_additional_entities;
179  store.reserve( new_size );
180  for( auto i : range( old_size, new_size ) )
181  {
182  store.emplace_back( GeoModelGeologicalEntityAccess< DIMENSION >::
183  create_geological_entity( type, geomodel_, i ) );
184  }
185  return true;
186  }
187 
188  template < index_t DIMENSION >
191  const gmge_id& parent, const gmme_id& children )
192  {
193  const auto& children_mesh_entity = geomodel_.mesh_entity( children );
194  if( children_mesh_entity.has_parent( parent.type() ) )
195  {
197  parent == children_mesh_entity.parent_gmge( parent.type() ) );
198  return true;
199  }
200  return false;
201  }
202 
203  template < index_t DIMENSION >
205  const gmge_id& parent, const gmme_id& children )
206  {
207  auto& parent_entity =
208  geomodel_access_.modifiable_geological_entity( parent );
209  const auto& parent_entity_types =
210  geomodel_.entity_type_manager().relationship_manager.parent_types(
211  children.type() );
212  if( !contains( parent_entity_types, parent.type() ) )
213  {
214  throw RINGMeshException( "Entity",
215  "Wrong Parent type in the parent children relation between ",
216  parent, " and ", children );
217  }
218 
220  parent, children ) )
221  {
222  return;
223  }
224 
225  auto& children_entity =
226  geomodel_access_.modifiable_mesh_entity( children );
227  const auto& children_type =
228  geomodel_.entity_type_manager().relationship_manager.child_type(
229  parent.type() );
230 
231  if( children_type != children.type() )
232  {
233  throw RINGMeshException( "Entity",
234  "Wrong children type in the parent children relation between ",
235  parent, " and ", children );
236  }
237 
238  auto& manager = geomodel_access_.modifiable_entity_type_manager()
239  .relationship_manager;
240  auto relation_id =
241  manager.add_parent_child_relationship( parent, children );
243  parent_entity
244  };
245  parent_access.modifiable_children().push_back( relation_id );
247  children_entity
248  };
249  children_access.modifiable_parents().push_back( relation_id );
250  }
251 
252  template < index_t DIMENSION >
254  const gmge_id& parent, const gmme_id& children )
255  {
256  auto& manager = geomodel_access_.modifiable_entity_type_manager()
257  .relationship_manager;
258  auto relation_id =
259  manager.find_parent_child_relationship( parent, children );
260  if( relation_id == NO_ID )
261  {
262  std::ostringstream message;
263  throw RINGMeshException( "Entity",
264  "No parent children relation found between ", parent, " and ",
265  children );
266  }
268  geomodel_access_.modifiable_geological_entity( parent )
269  };
270  auto& childs = parent_access.modifiable_children();
271  std::remove_if(
272  childs.begin(), childs.end(), [relation_id]( index_t relation ) {
273  return relation == relation_id;
274  } );
276  geomodel_access_.modifiable_mesh_entity( children )
277  };
278  auto& parents = children_access.modifiable_parents();
279  std::remove_if(
280  parents.begin(), parents.end(), [relation_id]( index_t relation ) {
281  return relation == relation_id;
282  } );
283  }
284 
285  template < index_t DIMENSION >
287  const gmge_id& parent_gmge, index_t id, index_t child_id )
288  {
291  auto& geol_entity =
292  geomodel_access_.modifiable_geological_entity( parent_gmge );
293  const auto& child_type =
294  geomodel_.entity_type_manager().relationship_manager.child_type(
295  parent_gmge.type() );
296  gmme_id child{ child_type, child_id };
297  GeoModelGeologicalEntityAccess< DIMENSION > gmge_access{ geol_entity };
298  auto relationship_id = gmge_access.modifiable_children()[id];
299  auto& manager = geomodel_access_.modifiable_entity_type_manager()
300  .relationship_manager;
301  manager.set_child_to_parent_child_relationship(
302  relationship_id, child );
303  }
304 
305  template < index_t DIMENSION >
307  const GeologicalEntityType& type, index_t index )
308  {
309  geomodel_access_.modifiable_geological_entities( type )[index].reset();
310  }
311 
312  template < index_t DIMENSION >
314  const GeologicalEntityType& type )
315  {
316  auto index = find_or_create_geological_entity_type( type );
317  auto id =
318  static_cast< index_t >( geomodel_.nb_geological_entities( type ) );
319  geomodel_access_.modifiable_geological_entities()[index].emplace_back(
321  create_geological_entity( type, geomodel_, id ) );
322  return geomodel_access_.modifiable_geological_entities()[index]
323  .back()
324  ->gmge();
325  }
326 
327  template < index_t DIMENSION >
330  const GeologicalEntityType& type )
331  {
332  auto type_index =
333  geomodel_.entity_type_manager()
334  .geological_entity_manager.geological_entity_type_index( type );
335  if( type_index == NO_ID )
336  {
337  type_index = create_geological_entity_type( type );
338  }
339  return type_index;
340  }
341 
342  template < index_t DIMENSION >
344  const GeologicalEntityType& type )
345  {
348 
349  geomodel_access_.modifiable_entity_type_manager()
350  .geological_entity_manager.geological_entity_types_.push_back(
351  type );
352  geomodel_access_.modifiable_geological_entities().emplace_back();
354  type, geomodel_ );
355 
356  const auto child_type = geol_entity->child_type_name();
357  auto& parentage = geomodel_access_.modifiable_entity_type_manager()
358  .relationship_manager;
359  parentage.register_geology_relationship( type, child_type );
360 
361  return geomodel_.entity_type_manager()
362  .geological_entity_manager.nb_geological_entity_types()
363  - 1;
364  }
365 
366  template < index_t DIMENSION >
368  const GeoModel< DIMENSION >& from, const GeologicalEntityType& type )
369  {
371  parallel_for( geomodel_.nb_geological_entities( type ),
372  [&type, &from, this]( index_t i ) {
373  gmge_id id{ type, i };
375  geomodel_access_.modifiable_geological_entity( id )
376  };
377  gmge_access.copy( from.geological_entity( id ) );
378  } );
379  }
380 
381  template < index_t DIMENSION >
383  {
384  if( geomodel_.entity_type_manager()
385  .geological_entity_manager.is_valid_type(
387  && geomodel_.nb_geological_entities(
389  > 0 )
390  {
391  return;
392  }
393 
394  std::vector< std::set< gmge_id > > interfaces;
395  for( const auto& line : geomodel_.lines() )
396  {
397  std::set< gmge_id > cur_interfaces;
398  for( auto j : range( line.nb_incident_entities() ) )
399  {
400  const auto& surface = line.incident_entity( j );
401  auto parent_interface = surface.parent_gmge(
403  cur_interfaces.insert( parent_interface );
404  }
405  gmge_id contact_id;
406  for( auto j : range( interfaces.size() ) )
407  {
408  if( cur_interfaces.size() == interfaces[j].size()
409  && std::equal( cur_interfaces.begin(), cur_interfaces.end(),
410  interfaces[j].begin() ) )
411  {
412  contact_id =
414  break;
415  }
416  }
417  if( !contact_id.is_defined() )
418  {
419  contact_id = create_geological_entity(
421  ringmesh_assert( contact_id.index() == interfaces.size() );
422  interfaces.push_back( cur_interfaces );
423  // Create a name for this contact
424  std::string name = "contact";
425  for( const auto& it : cur_interfaces )
426  {
427  name += "_";
428  name += geomodel_.geological_entity( it ).name();
429  }
430  builder_.info.set_geological_entity_name( contact_id, name );
431  }
432  add_parent_children_relation( contact_id, line.gmme() );
433  }
434  }
435  template < index_t DIMENSION >
436  void
438  const gmge_id& gmge_id,
440  geol_feature )
441  {
443  geomodel_access_.modifiable_geological_entity( gmge_id )
444  };
445  gmge_access.modifiable_geol_feature() = geol_feature;
446  }
447 
448  template class RINGMESH_API GeoModelBuilderGeology< 2 >;
449  template class RINGMESH_API GeoModelBuilderGeology< 3 >;
450 
451 } // namespace RINGMesh
static GeologicalEntityType type_name_static()
const GeoModel< DIMENSION > & geomodel() const
GeoModelMesh< DIMENSION > mesh
Definition: geomodel.h:241
static std::unique_ptr< BaseClass > create(const Key &key, const Args &... args)
Definition: factory.h:85
void remove_parent_children_relation(const gmge_id &parent, const gmme_id &children)
The GeologicalEntityType described the type of the Geological entities User can defined there own Geo...
Definition: entity_type.h:137
bool check_if_boundary_incident_entity_relation_already_exists(const gmge_id &parent, const gmme_id &children)
GeoModelBuilder< DIMENSION > & builder_
void add_parent_children_relation(const gmge_id &parent, const gmme_id &children)
void RINGMESH_API rotate(GeoModel3D &geomodel, const vec3 &origin, const vec3 &axis, double angle, bool degrees=false)
Rotate the boundary geomodel.
void set_geological_entity_geol_feature(const gmge_id &gmge_id, typename GeoModelGeologicalEntity< DIMENSION >::GEOL_FEATURE geol_feature)
Entity_type_template type() const
Definition: entity_type.h:202
index_t nb_geological_entity_types() const
Returns the index of the geological entity type storage.
Definition: geomodel.h:146
GeoModelBuilderGeology(GeoModelBuilder< DIMENSION > &builder, GeoModel< DIMENSION > &geomodel)
GEOL_FEATURE
Geological feature types for GeoModelEntity.
GeoModelAccess< DIMENSION > geomodel_access_
index_t create_geological_entity_type(const GeologicalEntityType &type)
index_t find_or_create_geological_entity_type(const GeologicalEntityType &type)
void delete_geological_entity(const GeologicalEntityType &type, index_t index)
static MeshEntityType type_name_static()
bool create_geological_entities(const GeologicalEntityType &type, index_t nb)
const GeologicalEntityType & geological_entity_type(index_t index) const
Definition: geomodel.h:152
void set_geological_entity_child(const gmge_id &parent_gmge, index_t id, index_t child_id)
const Surface< DIMENSION > & incident_entity(index_t x) const
index_t nb_corners() const
Definition: geomodel.h:201
bool is_defined() const
Definition: entity_type.h:275
std::vector< index_t > & modifiable_parents()
#define ringmesh_assert(x)
gmge_id create_geological_entity(const GeologicalEntityType &type)
Create and store a geological entity of the given type.
bool contains(const container &in, const T &value)
Definition: algorithm.h:87
void copy_geology(const GeoModel< DIMENSION > &from)
void copy_geological_entity_topology(const GeoModel< DIMENSION > &from, const GeologicalEntityType &type)
This template is a specialization of a gme_id to the GeoModelGeologicalEntity.
Definition: entity_type.h:262
Classes to build GeoModel from various inputs.
Definition: algorithm.h:48
A GeoModelEntity of type LINE.
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
index_t nb_geological_entities(const GeologicalEntityType &type) const
Returns the number of geological entities of the given type.
Definition: geomodel.h:136
void parallel_for(index_t size, const ACTION &action)
Definition: common.h:244