RINGMesh  Version 5.0.0
A programming library for geological model meshes
io_gprs.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 
36 namespace {
37  class GPRSIOHandler final: public GeoModelIOHandler< 3 > {
38  public:
39  struct Pipe {
40  Pipe( index_t v0_in, index_t v1_in )
41  : v0( v0_in ), v1( v1_in )
42  {
43  }
44  index_t v0;
45  index_t v1;
46  };
47  void load( const std::string& filename, GeoModel3D& geomodel ) final
48  {
49  ringmesh_unused( filename );
50  ringmesh_unused( geomodel );
51  throw RINGMeshException( "I/O",
52  "Loading of a GeoModel from GPRS not implemented yet" );
53  }
54  void save(
55  const GeoModel3D& geomodel,
56  const std::string& filename ) final
57  {
58  std::string path = GEO::FileSystem::dir_name( filename );
59  std::string directory = GEO::FileSystem::base_name( filename );
60  if( path == "." ) {
61  path = GEO::FileSystem::get_current_working_directory();
62  }
63  std::ostringstream oss;
64  oss << path << "/" << directory;
65  std::string full_path = oss.str();
66  GEO::FileSystem::create_directory( full_path );
67 
68  std::ostringstream oss_pipes;
69  oss_pipes << full_path << "/pipes.in";
70  std::ofstream out_pipes( oss_pipes.str().c_str() );
71 
72  std::ostringstream oss_vol;
73  oss_vol << full_path << "/vol.in";
74  std::ofstream out_vol( oss_vol.str().c_str() );
75  out_vol.precision( 16 );
76 
77  std::ostringstream oss_xyz;
78  oss_xyz << full_path << "/gprs.xyz";
79  std::ofstream out_xyz( oss_xyz.str().c_str() );
80  out_xyz.precision( 16 );
81 
82  const GeoModelMesh3D& mesh = geomodel.mesh;
83  std::deque< Pipe > pipes;
84  index_t cell_offset = mesh.cells.nb();
85  for( auto c :range( mesh.cells.nb() ) ) {
86  for( auto f : range( mesh.cells.nb_facets( c ) ) ) {
87  index_t facet { NO_ID };
88  bool not_used;
89  if( mesh.cells.is_cell_facet_on_surface( c, f, facet,
90  not_used ) ) {
91  pipes.emplace_back( c, facet + cell_offset );
92  } else {
93  index_t adj = mesh.cells.adjacent( c, f );
94  if( adj != GEO::NO_CELL && adj < c ) {
95  pipes.emplace_back( c, adj );
96  }
97  }
98  }
99  }
100 
101  index_t nb_edges = 0;
102  for( const auto& line : geomodel.lines() ) {
103  nb_edges += line.nb_mesh_elements();
104  }
105  std::vector< index_t > temp;
106  temp.reserve( 3 );
107  std::vector< std::vector< index_t > > edges( nb_edges, temp );
108  std::vector< vec3 > edge_vertices( nb_edges );
109  index_t count_edge = 0;
110  for( const auto& line : geomodel.lines() ) {
111  for( index_t e : range( line.nb_mesh_elements() ) ) {
112  edge_vertices[count_edge++ ] = 0.5
113  * ( line.vertex( e ) + line.vertex( e + 1 ) );
114  }
115  }
116  NNSearch3D nn_search( edge_vertices, false );
117 
118  const GeoModelMeshPolygons3D& polygons = geomodel.mesh.polygons;
119  for( index_t p : range( polygons.nb() ) ) {
120  for( index_t e : range( polygons.nb_vertices( p ) ) ) {
121  index_t adj = polygons.adjacent( PolygonLocalEdge( p, e ) );
122  if( adj != GEO::NO_CELL && adj < p ) {
123  pipes.emplace_back( p + cell_offset, adj + cell_offset );
124  } else {
125  const vec3& e0 = mesh.vertices.vertex(
126  polygons.vertex( ElementLocalVertex( p, e ) ) );
127  const vec3& e1 = mesh.vertices.vertex(
128  polygons.vertex(
129  ElementLocalVertex( p,
130  ( e + 1 ) % polygons.nb_vertices( p ) ) ) );
131  vec3 query = 0.5 * ( e0 + e1 );
132  std::vector< index_t > results = nn_search.get_neighbors(
133  query, geomodel.epsilon() );
134  if( !results.empty() ) {
135  edges[results[0]].push_back( cell_offset + p );
136  } else {
138  }
139  }
140  }
141  }
142 
143  auto nb_pipes = static_cast< index_t > ( pipes.size() );
144  for( const auto& vertices : edges ) {
145  nb_pipes += binomial_coef( static_cast< index_t > ( vertices.size() ) );
146  }
147  out_pipes << nb_pipes << EOL;
148  for( const auto& pipe : pipes ) {
149  out_pipes << pipe.v0 << SPACE << pipe.v1 << EOL;
150  }
151  for( const auto& vertices : edges ) {
152  for( auto v0 : range( vertices.size() - 1 ) ) {
153  for( auto v1 : range( v0 + 1, vertices.size() ) ) {
154  out_pipes << vertices[v0] << SPACE << vertices[v1]
155  << EOL;
156  }
157  }
158  }
159 
160  out_xyz
161  << "Node geometry, not used by GPRS but useful to reconstruct a pipe-network"
162  << EOL;
163  for( auto c : range( mesh.cells.nb() ) ) {
164  out_xyz << mesh.cells.barycenter( c ) << EOL;
165  out_vol << mesh.cells.volume( c ) << EOL;
166  }
167  for( auto p : range( polygons.nb() ) ) {
168  out_xyz << polygons.center( p ) << EOL;
169  out_vol << polygons.area( p ) << EOL;
170  }
171 
172  out_pipes << std::flush;
173  out_vol << std::flush;
174  out_xyz << std::flush;
175  }
176  index_t binomial_coef( index_t n ) const
177  {
178  switch( n ) {
179  case 1:
180  return 0;
181  case 2:
182  return 1;
183  case 3:
184  return 3;
185  case 4:
186  return 6;
187  case 5:
188  return 10;
189  case 6:
190  return 15;
191  case 7:
192  return 21;
193  case 8:
194  return 28;
195  case 9:
196  return 36;
197  case 10:
198  return 45;
199  default:
201  return 0;
202 
203  }
204  }
205  };
206 
207 }
const char SPACE
Definition: io.h:46
vecn< 3 > vec3
Definition: types.h:76
void ringmesh_unused(const T &)
Definition: common.h:105
const char EOL
Definition: io.h:45
#define ringmesh_assert_not_reached