41 index_t nb_polygons(
const GeoModel3D& geomodel )
44 for(
const auto& surface : surface_range < 3 > ( geomodel ) ) {
45 result += surface.nb_mesh_elements();
58 void save_region( index_t count,
const Region3D& region, std::ostream& out )
60 out <<
"REGION " << count <<
" " << region.name() <<
" " <<
EOL;
63 for(
auto i : range( region.nb_boundaries() ) ) {
65 if( region.side( i ) ) {
70 out << region.boundary( i ).index() + 1;
82 const GeoModel3D& geomodel,
85 const SurfaceSide surface_region_sides = geomodel.voi_surfaces();
87 out <<
"REGION " << count <<
" Universe " 91 for(
auto i : range( surface_region_sides.surfaces_.size() ) ) {
93 if( surface_region_sides.sides_[ i ] ) {
98 out << surface_region_sides.surfaces_[ i ] + 1;
119 const GeoModelGeologicalEntity3D& layer,
122 out <<
"LAYER " << layer.name() <<
" " <<
EOL;
125 for(
auto i : range( layer.nb_children() ) ) {
126 out <<
" " << layer.child_gmme( i ).index() + offset + 1;
140 void save_coordinate_system( std::ostream& out )
142 out <<
"GOCAD_ORIGINAL_COORDINATE_SYSTEM" << EOL <<
"NAME Default" 143 << EOL <<
"AXIS_NAME \"X\" \"Y\" \"Z\"" << EOL
144 <<
"AXIS_UNIT \"m\" \"m\" \"m\"" << EOL <<
"ZPOSITIVE Elevation" 145 << EOL <<
"END_ORIGINAL_COORDINATE_SYSTEM" <<
EOL;
156 bool check_gocad_validity(
const GeoModel3D& geomodel )
158 auto nb_interfaces = geomodel.nb_geological_entities(
159 Interface3D::type_name_static() );
160 if( nb_interfaces == 0 ) {
161 Logger::err(
"",
" The GeoModel ", geomodel.name(),
162 " has no Interface" );
165 for(
auto& cur_interface : geomodel.geol_entities(
166 Interface3D::type_name_static() ) ) {
167 if( !cur_interface.has_geological_feature() ) {
168 Logger::err(
"", cur_interface.gmge(),
" has no geological feature" );
172 for(
const auto& surface : surface_range < 3 > ( geomodel ) ) {
173 if( !surface.has_parent() ) {
174 Logger::err(
"", surface.gmme(),
175 " does not belong to any Interface of the geomodel" );
178 if( !surface.is_simplicial() ) {
179 Logger::err(
"", surface.gmme(),
" is not triangulated " );
187 bool has_surface_edge(
188 const Surface3D& surface,
192 for(
auto i : range( surface.nb_mesh_elements() ) ) {
193 for(
auto j : range( surface.nb_mesh_element_vertices( i ) ) ) {
194 auto v0 = surface.mesh_element_vertex_index(
196 auto v1 = surface.mesh_element_vertex_index(
197 surface.mesh().next_polygon_vertex(
199 if( ( v0 == v0_in && v1 == v1_in )
200 || ( v0 == v1_in && v1 == v0_in ) ) {
213 void save_gocad_model3d(
const GeoModel3D& geomodel, std::ostream& out )
215 if( !check_gocad_validity( geomodel ) ) {
216 throw RINGMeshException(
"I/O",
" The GeoModel ", geomodel.name(),
217 " cannot be saved in .ml format" );
222 out <<
"GOCAD Model3d 1" << EOL <<
"HEADER {" << EOL <<
"name: " 223 << geomodel.name() << EOL <<
"}" <<
EOL;
225 save_coordinate_system( out );
228 for(
auto& tsurf : geomodel.geol_entities(
229 Interface3D::type_name_static() ) ) {
230 out <<
"TSURF " << tsurf.name() <<
EOL;
236 for(
const auto& surface : geomodel.surfaces() ) {
237 const gmge_id& parent_interface = surface.parent_gmge(
238 Interface3D::type_name_static() );
239 if( !parent_interface.is_defined() ) {
240 throw RINGMeshException(
"I/O",
"Failed to save GeoModel",
241 " in .ml Gocad format because Surface ", surface.index(),
242 " has no Interface parent)" );
244 const auto& cur_geol_feature =
245 geomodel.geological_entity( parent_interface ).geological_feature();
247 out <<
"TFACE " << count <<
" ";
248 out << GeoModelGeologicalEntity3D::geol_name( cur_geol_feature );
249 out <<
" " << surface.parent( Interface3D::type_name_static() ).name()
255 << surface.mesh_element_vertex( { 0, 0 } )
258 << surface.mesh_element_vertex( { 0, 1 } )
261 << surface.mesh_element_vertex( { 0, 2 } )
267 auto offset_layer = count;
268 save_universe( count, geomodel, out );
271 for(
const auto& region : geomodel.regions() ) {
272 save_region( count, region, out );
276 if( geomodel.entity_type_manager().geological_entity_manager.is_valid_type(
277 Layer3D::type_name_static() ) ) {
278 for(
auto& layer : geomodel.geol_entities( Layer3D::type_name_static() ) ) {
279 save_layer( offset_layer, layer, out );
285 const auto& geomodel_vertices = geomodel.mesh.vertices;
287 for(
auto& tsurf : geomodel.geol_entities( Interface3D::type_name_static() ) ) {
289 out <<
"GOCAD TSurf 1" << EOL <<
"HEADER {" << EOL <<
"name:" 290 << tsurf.name() << EOL <<
"name_in_model_list:" << tsurf.name()
291 << EOL <<
"}" <<
EOL;
292 save_coordinate_system( out );
294 out <<
"GEOLOGICAL_FEATURE " << tsurf.name() << EOL
295 <<
"GEOLOGICAL_TYPE ";
296 out << GeoModelGeologicalEntity < 3
297 > ::geol_name( tsurf.geological_feature() );
299 out <<
"PROPERTY_CLASS_HEADER Z {" << EOL <<
"is_z:on" << EOL
302 index_t vertex_count { 1 };
304 auto offset = vertex_count;
308 std::set< index_t > corners;
309 std::set< std::pair< index_t, index_t > > lineindices;
310 for(
auto j : range( tsurf.nb_children() ) ) {
311 offset = vertex_count;
312 const auto& surface =
313 dynamic_cast< const Surface3D&
>( tsurf.child( j ) );
315 out <<
"TFACE" <<
EOL;
316 for(
auto k : range( surface.nb_vertices() ) ) {
317 out <<
"VRTX " << vertex_count <<
" " << surface.vertex( k )
321 for(
auto k : range( surface.nb_mesh_elements() ) ) {
323 << surface.mesh_element_vertex_index(
324 { k, 0 } ) + offset <<
" " 325 << surface.mesh_element_vertex_index(
326 { k, 1 } ) + offset <<
" " 327 << surface.mesh_element_vertex_index(
328 { k, 2 } ) + offset << EOL;
330 for(
auto k : range( surface.nb_boundaries() ) ) {
331 const auto& line = surface.boundary( k );
332 auto v0_model_id = geomodel_vertices.geomodel_vertex_id(
334 auto v1_model_id = geomodel_vertices.geomodel_vertex_id(
337 auto v0_surface_ids =
338 geomodel_vertices.mesh_entity_vertex_id( surface.gmme(),
340 auto v1_surface_ids =
341 geomodel_vertices.mesh_entity_vertex_id( surface.gmme(),
344 if( !surface.has_inside_border() ) {
345 auto v0 = v0_surface_ids[0];
346 auto v1 = v1_surface_ids[0];
351 std::pair< index_t, index_t >( v0, v1 ) );
352 corners.insert( v0 );
357 bool to_break =
false;
358 for(
auto v0 : v0_surface_ids ) {
359 for(
auto v1 : v1_surface_ids ) {
360 if( has_surface_edge( surface, v0, v1 ) ) {
362 std::pair< index_t, index_t >( v0 + offset,
366 if( !line.is_inside_border( surface )
370 }
else if( count == 2 ) {
376 corners.insert( v0 + offset );
383 const auto& c1_id = line.boundary_gmme( 1 );
385 geomodel_vertices.mesh_entity_vertex_id( surface.gmme(),
386 geomodel_vertices.geomodel_vertex_id( c1_id ) );
387 corners.insert( gme_vertices.front() + offset );
391 for(
auto it( corners.begin() ); it != corners.end(); ++it ) {
392 out <<
"BSTONE " << *it <<
EOL;
394 for(
auto it( lineindices.begin() ); it != lineindices.end(); ++it ) {
395 out <<
"BORDER " << vertex_count <<
" " << it->first <<
" " 396 << it->second <<
EOL;
403 class MLIOHandler final:
public GeoModelIOHandler< 3 > {
408 void load(
const std::string& filename, GeoModel3D& geomodel )
final 410 std::ifstream input( filename.c_str() );
412 throw RINGMeshException(
"I/O",
"Failed to open file ", filename );
414 GeoModelBuilderML builder( geomodel, filename );
415 builder.build_geomodel();
418 void save(
const GeoModel< 3 >& geomodel,
const std::string& filename )
final 420 std::ofstream out( filename.c_str() );
421 save_gocad_model3d( geomodel, out );