![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /**
00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003 * storing and accessing finite element mesh data.
00004 *
00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract
00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007 * retains certain rights in this software.
00008 *
00009 * This library is free software; you can redistribute it and/or
00010 * modify it under the terms of the GNU Lesser General Public
00011 * License as published by the Free Software Foundation; either
00012 * version 2.1 of the License, or (at your option) any later version.
00013 *
00014 */
00015 #ifdef WIN32
00016 #pragma warning( disable : 4786 )
00017 #endif
00018
00019 #include "CGMConfig.h"
00020 #include "GeometryQueryTool.hpp"
00021 #include "ModelQueryEngine.hpp"
00022 #include "RefEntityName.hpp"
00023 #include "GMem.hpp"
00024
00025 #include "RefGroup.hpp"
00026 #include "RefVolume.hpp"
00027 #include "RefFace.hpp"
00028 #include "RefEdge.hpp"
00029 #include "RefVertex.hpp"
00030
00031 #include "SenseEntity.hpp"
00032 #include "Surface.hpp"
00033 #include "Curve.hpp"
00034 #include "Body.hpp"
00035 #include "InitCGMA.hpp"
00036
00037 #include "moab/Core.hpp"
00038 #include "moab/Interface.hpp"
00039 #include "moab/Range.hpp"
00040 #include "MBTagConventions.hpp"
00041 #include "moab/FileOptions.hpp"
00042
00043 #include "moab/GeomTopoTool.hpp"
00044
00045 #include "CubitCompat.hpp"
00046
00047 #include
00048 #include
00049 #include
00050 #include
00051
00052 #include "ReadCGM.hpp"
00053 #include "moab/ReadUtilIface.hpp"
00054
00055 namespace moab
00056 {
00057
00058 #define GF_CUBIT_FILE_TYPE "CUBIT"
00059 #define GF_STEP_FILE_TYPE "STEP"
00060 #define GF_IGES_FILE_TYPE "IGES"
00061 #define GF_OCC_BREP_FILE_TYPE "OCC"
00062 #define GF_FACET_FILE_TYPE "FACET"
00063
00064 ReaderIface* ReadCGM::factory( Interface* iface )
00065 {
00066 return new ReadCGM( iface );
00067 }
00068
00069 ReadCGM::ReadCGM( Interface* impl )
00070 : geom_tag( 0 ), id_tag( 0 ), name_tag( 0 ), category_tag( 0 ), faceting_tol_tag( 0 ), geometry_resabs_tag( 0 )
00071 {
00072 assert( NULL != impl );
00073 mdbImpl = impl;
00074 myGeomTool = new GeomTopoTool( impl );
00075 impl->query_interface( readUtilIface );
00076 assert( NULL != readUtilIface );
00077
00078 // initialise counters
00079 failed_curve_count = 0;
00080 failed_surface_count = 0;
00081
00082 ErrorCode rval;
00083
00084 // get some tag handles
00085 int negone = -1, zero = 0 /*, negonearr[] = {-1, -1, -1, -1}*/;
00086 rval = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, MB_TAG_SPARSE | MB_TAG_CREAT,
00087 &negone );
00088 assert( !rval );
00089 id_tag = mdbImpl->globalId_tag();
00090
00091 rval =
00092 mdbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );
00093 assert( !rval );
00094
00095 rval = mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE, category_tag,
00096 MB_TAG_SPARSE | MB_TAG_CREAT );
00097 assert( !rval );
00098 rval = mdbImpl->tag_get_handle( "FACETING_TOL", 1, MB_TYPE_DOUBLE, faceting_tol_tag, MB_TAG_SPARSE | MB_TAG_CREAT );
00099 assert( !rval );
00100 rval = mdbImpl->tag_get_handle( "GEOMETRY_RESABS", 1, MB_TYPE_DOUBLE, geometry_resabs_tag,
00101 MB_TAG_SPARSE | MB_TAG_CREAT );
00102 assert( !rval );
00103 #ifdef NDEBUG
00104 if( !rval )
00105 {
00106 }; // Line to avoid compiler warning about variable set but not used
00107 #endif
00108 }
00109
00110 ReadCGM::~ReadCGM()
00111 {
00112 mdbImpl->release_interface( readUtilIface );
00113 delete myGeomTool;
00114 }
00115
00116 ErrorCode ReadCGM::read_tag_values( const char* /* file_name */,
00117 const char* /* tag_name */,
00118 const FileOptions& /* opts */,
00119 std::vector< int >& /* tag_values_out */,
00120 const SubsetList* /* subset_list */ )
00121 {
00122 return MB_NOT_IMPLEMENTED;
00123 }
00124
00125 // Sets options passed into ReadCGM::load_file
00126 ErrorCode ReadCGM::set_options( const FileOptions& opts,
00127 int& norm_tol,
00128 double& faceting_tol,
00129 double& len_tol,
00130 bool& act_att,
00131 bool& verbose_warnings,
00132 bool& fatal_on_curves )
00133 {
00134 ErrorCode rval;
00135
00136 // Default Values
00137 int DEFAULT_NORM = 5;
00138 double DEFAULT_FACET_TOL = 0.001;
00139 double DEFAULT_LEN_TOL = 0.0;
00140 act_att = true;
00141
00142 // Check for the options.
00143 if( MB_SUCCESS != opts.get_int_option( "FACET_NORMAL_TOLERANCE", norm_tol ) ) norm_tol = DEFAULT_NORM;
00144
00145 if( MB_SUCCESS != opts.get_real_option( "FACET_DISTANCE_TOLERANCE", faceting_tol ) )
00146 faceting_tol = DEFAULT_FACET_TOL;
00147
00148 if( MB_SUCCESS != opts.get_real_option( "MAX_FACET_EDGE_LENGTH", len_tol ) ) len_tol = DEFAULT_LEN_TOL;
00149
00150 if( MB_SUCCESS == opts.get_null_option( "VERBOSE_CGM_WARNINGS" ) ) verbose_warnings = true;
00151
00152 if( MB_SUCCESS == opts.get_null_option( "FATAL_ON_CURVES" ) ) fatal_on_curves = true;
00153
00154 const char* name = "CGM_ATTRIBS";
00155 const char* value = "no";
00156 rval = opts.match_option( name, value );
00157 if( MB_SUCCESS == rval ) act_att = false;
00158
00159 return MB_SUCCESS;
00160 }
00161
00162 ErrorCode ReadCGM::create_entity_sets( std::map< RefEntity*, EntityHandle > ( &entmap )[5] )
00163 {
00164 ErrorCode rval;
00165 const char geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0", "Group\0" };
00166 const char* const names[] = { "Vertex", "Curve", "Surface", "Volume" };
00167 DLIList< RefEntity* > entlist;
00168
00169 for( int dim = 0; dim < 4; dim++ )
00170 {
00171 entlist.clean_out();
00172 GeometryQueryTool::instance()->ref_entity_list( names[dim], entlist, true );
00173 entlist.reset();
00174
00175 for( int i = entlist.size(); i--; )
00176 {
00177 RefEntity* ent = entlist.get_and_step();
00178 EntityHandle handle;
00179 // Create the new meshset
00180 rval = mdbImpl->create_meshset( dim == 1 ? MESHSET_ORDERED : MESHSET_SET, handle );
00181 if( MB_SUCCESS != rval ) return rval;
00182
00183 // Map the geom reference entity to the corresponding moab meshset
00184 entmap[dim][ent] = handle;
00185
00186 // Create tags for the new meshset
00187 rval = mdbImpl->tag_set_data( geom_tag, &handle, 1, &dim );
00188 if( MB_SUCCESS != rval ) return rval;
00189
00190 int id = ent->id();
00191 rval = mdbImpl->tag_set_data( id_tag, &handle, 1, &id );
00192 if( MB_SUCCESS != rval ) return rval;
00193
00194 rval = mdbImpl->tag_set_data( category_tag, &handle, 1, &geom_categories[dim] );
00195 if( MB_SUCCESS != rval ) return rval;
00196 }
00197 }
00198
00199 return MB_SUCCESS;
00200 }
00201
00202 ErrorCode ReadCGM::create_topology( std::map< RefEntity*, EntityHandle > ( &entitymap )[5] )
00203 {
00204 ErrorCode rval;
00205 DLIList< RefEntity* > entitylist;
00206 std::map< RefEntity*, EntityHandle >::iterator ci;
00207
00208 for( int dim = 1; dim < 4; ++dim )
00209 {
00210 for( ci = entitymap[dim].begin(); ci != entitymap[dim].end(); ++ci )
00211 {
00212 entitylist.clean_out();
00213 ci->first->get_child_ref_entities( entitylist );
00214
00215 entitylist.reset();
00216 for( int i = entitylist.size(); i--; )
00217 {
00218 RefEntity* ent = entitylist.get_and_step();
00219 EntityHandle h = entitymap[dim - 1][ent];
00220 rval = mdbImpl->add_parent_child( ci->second, h );
00221 if( MB_SUCCESS != rval ) return rval;
00222 }
00223 }
00224 }
00225
00226 return MB_SUCCESS;
00227 }
00228
00229 ErrorCode ReadCGM::store_surface_senses( std::map< RefEntity*, EntityHandle >& surface_map,
00230 std::map< RefEntity*, EntityHandle >& volume_map )
00231 {
00232 ErrorCode rval;
00233 std::map< RefEntity*, EntityHandle >::iterator ci;
00234
00235 for( ci = surface_map.begin(); ci != surface_map.end(); ++ci )
00236 {
00237 RefFace* face = (RefFace*)( ci->first );
00238 BasicTopologyEntity *forward = 0, *reverse = 0;
00239 for( SenseEntity* cf = face->get_first_sense_entity_ptr(); cf; cf = cf->next_on_bte() )
00240 {
00241 BasicTopologyEntity* vol = cf->get_parent_basic_topology_entity_ptr();
00242 // Allocate vol to the proper topology entity (forward or reverse)
00243 if( cf->get_sense() == CUBIT_UNKNOWN || cf->get_sense() != face->get_surface_ptr()->bridge_sense() )
00244 {
00245 // Check that each surface has a sense for only one volume
00246 if( reverse )
00247 {
00248 std::cout << "Surface " << face->id() << " has reverse sense "
00249 << "with multiple volume " << reverse->id() << " and "
00250 << "volume " << vol->id() << std::endl;
00251 return MB_FAILURE;
00252 }
00253 reverse = vol;
00254 }
00255 if( cf->get_sense() == CUBIT_UNKNOWN || cf->get_sense() == face->get_surface_ptr()->bridge_sense() )
00256 {
00257 // Check that each surface has a sense for only one volume
00258 if( forward )
00259 {
00260 std::cout << "Surface " << face->id() << " has forward sense "
00261 << "with multiple volume " << forward->id() << " and "
00262 << "volume " << vol->id() << std::endl;
00263 return MB_FAILURE;
00264 }
00265 forward = vol;
00266 }
00267 }
00268
00269 if( forward )
00270 {
00271 rval = myGeomTool->set_sense( ci->second, volume_map[forward], SENSE_FORWARD );
00272 if( MB_SUCCESS != rval ) return rval;
00273 }
00274 if( reverse )
00275 {
00276 rval = myGeomTool->set_sense( ci->second, volume_map[reverse], SENSE_REVERSE );
00277 if( MB_SUCCESS != rval ) return rval;
00278 }
00279 }
00280
00281 return MB_SUCCESS;
00282 }
00283
00284 ErrorCode ReadCGM::store_curve_senses( std::map< RefEntity*, EntityHandle >& curve_map,
00285 std::map< RefEntity*, EntityHandle >& surface_map )
00286 {
00287 ErrorCode rval;
00288 std::vector< EntityHandle > ents;
00289 std::vector< int > senses;
00290 std::map< RefEntity*, EntityHandle >::iterator ci;
00291 for( ci = curve_map.begin(); ci != curve_map.end(); ++ci )
00292 {
00293 RefEdge* edge = (RefEdge*)( ci->first );
00294 ents.clear();
00295 senses.clear();
00296 for( SenseEntity* ce = edge->get_first_sense_entity_ptr(); ce; ce = ce->next_on_bte() )
00297 {
00298 BasicTopologyEntity* fac = ce->get_parent_basic_topology_entity_ptr();
00299 EntityHandle face = surface_map[fac];
00300 if( ce->get_sense() == CUBIT_UNKNOWN || ce->get_sense() != edge->get_curve_ptr()->bridge_sense() )
00301 {
00302 ents.push_back( face );
00303 senses.push_back( SENSE_REVERSE );
00304 }
00305 if( ce->get_sense() == CUBIT_UNKNOWN || ce->get_sense() == edge->get_curve_ptr()->bridge_sense() )
00306 {
00307 ents.push_back( face );
00308 senses.push_back( SENSE_FORWARD );
00309 }
00310 }
00311
00312 rval = myGeomTool->set_senses( ci->second, ents, senses );
00313 if( MB_SUCCESS != rval ) return rval;
00314 }
00315 return MB_SUCCESS;
00316 }
00317
00318 ErrorCode ReadCGM::store_groups( std::map< RefEntity*, EntityHandle > ( &entitymap )[5] )
00319 {
00320 ErrorCode rval;
00321
00322 // Create entity sets for all ref groups
00323 rval = create_group_entsets( entitymap[4] );
00324 if( rval != MB_SUCCESS ) return rval;
00325
00326 // Store group names and entities in the mesh
00327 rval = store_group_content( entitymap );
00328 if( rval != MB_SUCCESS ) return rval;
00329
00330 return MB_SUCCESS;
00331 }
00332
00333 ErrorCode ReadCGM::create_group_entsets( std::map< RefEntity*, EntityHandle >& group_map )
00334 {
00335 ErrorCode rval;
00336 const char geom_categories[][CATEGORY_TAG_SIZE] = { "Vertex\0", "Curve\0", "Surface\0", "Volume\0", "Group\0" };
00337 DLIList< RefEntity* > entitylist;
00338 // Create entity sets for all ref groups
00339 std::vector< Tag > extra_name_tags;
00340 #if CGM_MAJOR_VERSION > 13
00341 DLIList< CubitString > name_list;
00342 #else
00343 DLIList< CubitString* > name_list;
00344 #endif
00345 entitylist.clean_out();
00346 // Get all entity groups from the CGM model
00347 GeometryQueryTool::instance()->ref_entity_list( "group", entitylist );
00348 entitylist.reset();
00349 // Loop over all groups
00350 for( int i = entitylist.size(); i--; )
00351 {
00352 // Take the next group
00353 RefEntity* grp = entitylist.get_and_step();
00354 name_list.clean_out();
00355 // Get the names of all entities in this group from the solid model
00356 #if CGM_MAJOR_VERSION > 13
00357 RefEntityName::instance()->get_refentity_name( grp, name_list );
00358 #else
00359 // True argument is optional, but for large multi-names situation, it should save
00360 // some cpu time
00361 RefEntityName::instance()->get_refentity_name( grp, name_list, true );
00362 #endif
00363 if( name_list.size() == 0 ) continue;
00364 // Set pointer to first name of the group and set the first name to name1
00365 name_list.reset();
00366 #if CGM_MAJOR_VERSION > 13
00367 CubitString name1 = name_list.get();
00368 #else
00369 CubitString name1 = *name_list.get();
00370 #endif
00371 // Create entity handle for the group
00372 EntityHandle h;
00373 rval = mdbImpl->create_meshset( MESHSET_SET, h );
00374 if( MB_SUCCESS != rval ) return rval;
00375 // Set tag data for the group
00376 char namebuf[NAME_TAG_SIZE];
00377 memset( namebuf, '\0', NAME_TAG_SIZE );
00378 strncpy( namebuf, name1.c_str(), NAME_TAG_SIZE - 1 );
00379 if( name1.length() >= (unsigned)NAME_TAG_SIZE )
00380 std::cout << "WARNING: group name '" << name1.c_str() << "' truncated to '" << namebuf << "'" << std::endl;
00381 rval = mdbImpl->tag_set_data( name_tag, &h, 1, namebuf );
00382 if( MB_SUCCESS != rval ) return MB_FAILURE;
00383
00384 int id = grp->id();
00385 rval = mdbImpl->tag_set_data( id_tag, &h, 1, &id );
00386 if( MB_SUCCESS != rval ) return MB_FAILURE;
00387
00388 rval = mdbImpl->tag_set_data( category_tag, &h, 1, &geom_categories[4] );
00389 if( MB_SUCCESS != rval ) return MB_FAILURE;
00390 // Check for extra group names
00391 if( name_list.size() > 1 )
00392 {
00393 for( int j = extra_name_tags.size(); j < name_list.size(); ++j )
00394 {
00395 sprintf( namebuf, "EXTRA_%s%d", NAME_TAG_NAME, j );
00396 Tag t;
00397 rval =
00398 mdbImpl->tag_get_handle( namebuf, NAME_TAG_SIZE, MB_TYPE_OPAQUE, t, MB_TAG_SPARSE | MB_TAG_CREAT );
00399 assert( !rval );
00400 extra_name_tags.push_back( t );
00401 }
00402 // Add extra group names to the group handle
00403 for( int j = 0; j < name_list.size(); ++j )
00404 {
00405 #if CGM_MAJOR_VERSION > 13
00406 name1 = name_list.get_and_step();
00407 #else
00408 name1 = *name_list.get_and_step();
00409 #endif
00410 memset( namebuf, '\0', NAME_TAG_SIZE );
00411 strncpy( namebuf, name1.c_str(), NAME_TAG_SIZE - 1 );
00412 if( name1.length() >= (unsigned)NAME_TAG_SIZE )
00413 std::cout << "WARNING: group name '" << name1.c_str() << "' truncated to '" << namebuf << "'"
00414 << std::endl;
00415 rval = mdbImpl->tag_set_data( extra_name_tags[j], &h, 1, namebuf );
00416 if( MB_SUCCESS != rval ) return MB_FAILURE;
00417 }
00418 }
00419 // Add the group handle
00420 group_map[grp] = h;
00421 }
00422
00423 return MB_SUCCESS;
00424 }
00425
00426 ErrorCode ReadCGM::store_group_content( std::map< RefEntity*, EntityHandle > ( &entitymap )[5] )
00427 {
00428 ErrorCode rval;
00429 DLIList< RefEntity* > entlist;
00430 std::map< RefEntity*, EntityHandle >::iterator ci;
00431 // Store contents for each group
00432 entlist.reset();
00433 for( ci = entitymap[4].begin(); ci != entitymap[4].end(); ++ci )
00434 {
00435 RefGroup* grp = (RefGroup*)( ci->first );
00436 entlist.clean_out();
00437 grp->get_child_ref_entities( entlist );
00438
00439 Range entities;
00440 while( entlist.size() )
00441 {
00442 RefEntity* ent = entlist.pop();
00443 int dim = ent->dimension();
00444
00445 if( dim < 0 )
00446 {
00447 Body* body;
00448 if( entitymap[4].find( ent ) != entitymap[4].end() )
00449 {
00450 // Child is another group; examine its contents
00451 entities.insert( entitymap[4][ent] );
00452 }
00453 else if( ( body = dynamic_cast< Body* >( ent ) ) != NULL )
00454 {
00455 // Child is a CGM Body, which presumably comprises some volumes--
00456 // extract volumes as if they belonged to group.
00457 DLIList< RefVolume* > vols;
00458 body->ref_volumes( vols );
00459 for( int vi = vols.size(); vi--; )
00460 {
00461 RefVolume* vol = vols.get_and_step();
00462 if( entitymap[3].find( vol ) != entitymap[3].end() )
00463 {
00464 entities.insert( entitymap[3][vol] );
00465 }
00466 else
00467 {
00468 std::cerr << "Warning: CGM Body has orphan RefVolume" << std::endl;
00469 }
00470 }
00471 }
00472 else
00473 {
00474 // Otherwise, warn user.
00475 std::cerr << "Warning: A dim<0 entity is being ignored by ReadCGM." << std::endl;
00476 }
00477 }
00478 else if( dim < 4 )
00479 {
00480 if( entitymap[dim].find( ent ) != entitymap[dim].end() ) entities.insert( entitymap[dim][ent] );
00481 }
00482 }
00483
00484 if( !entities.empty() )
00485 {
00486 rval = mdbImpl->add_entities( ci->second, entities );
00487 if( MB_SUCCESS != rval ) return MB_FAILURE;
00488 }
00489 }
00490
00491 return MB_SUCCESS;
00492 }
00493
00494 void ReadCGM::set_cgm_attributes( bool const act_attributes, bool const verbose )
00495 {
00496 if( act_attributes )
00497 {
00498 CGMApp::instance()->attrib_manager()->set_all_auto_read_flags( act_attributes );
00499 CGMApp::instance()->attrib_manager()->set_all_auto_actuate_flags( act_attributes );
00500 }
00501
00502 if( !verbose )
00503 {
00504 CGMApp::instance()->attrib_manager()->silent_flag( true );
00505 }
00506 }
00507
00508 ErrorCode ReadCGM::create_vertices( std::map< RefEntity*, EntityHandle >& vertex_map )
00509 {
00510 ErrorCode rval;
00511 std::map< RefEntity*, EntityHandle >::iterator ci;
00512 for( ci = vertex_map.begin(); ci != vertex_map.end(); ++ci )
00513 {
00514 CubitVector pos = dynamic_cast< RefVertex* >( ci->first )->coordinates();
00515 double coords[3] = { pos.x(), pos.y(), pos.z() };
00516 EntityHandle vh;
00517 rval = mdbImpl->create_vertex( coords, vh );
00518 if( MB_SUCCESS != rval ) return MB_FAILURE;
00519
00520 // Add the vertex to its tagged meshset
00521 rval = mdbImpl->add_entities( ci->second, &vh, 1 );
00522 if( MB_SUCCESS != rval ) return MB_FAILURE;
00523
00524 // Replace the meshset handle with the vertex handle
00525 // This makes adding the vertex to higher dim sets easier
00526 ci->second = vh;
00527 }
00528
00529 return MB_SUCCESS;
00530 }
00531
00532 ErrorCode ReadCGM::create_curve_facets( std::map< RefEntity*, EntityHandle >& curve_map,
00533 std::map< RefEntity*, EntityHandle >& vertex_map,
00534 #if CGM_MAJOR_VERSION > 12
00535 int norm_tol,
00536 #else
00537 int /* norm_tol */,
00538 #endif
00539 double faceting_tol,
00540 bool verbose_warn,
00541 bool fatal_on_curves )
00542 {
00543 ErrorCode rval;
00544 CubitStatus s;
00545 // Maximum allowable curve-endpoint proximity warnings
00546 // If this integer becomes negative, then abs(curve_warnings) is the
00547 // number of warnings that were suppressed.
00548 int curve_warnings = 0;
00549
00550 // Map iterator
00551 std::map< RefEntity*, EntityHandle >::iterator ci;
00552
00553 // Create geometry for all curves
00554 GMem data;
00555 for( ci = curve_map.begin(); ci != curve_map.end(); ++ci )
00556 {
00557 // Get the start and end points of the curve in the form of a reference edge
00558 RefEdge* edge = dynamic_cast< RefEdge* >( ci->first );
00559 // Get the edge's curve information
00560 Curve* curve = edge->get_curve_ptr();
00561 // Clean out previous curve information
00562 data.clean_out();
00563 // Facet curve according to parameters and CGM version
00564 #if CGM_MAJOR_VERSION > 12
00565 s = edge->get_graphics( data, norm_tol, faceting_tol );
00566 #else
00567 s = edge->get_graphics( data, faceting_tol );
00568 #endif
00569
00570 if( s != CUBIT_SUCCESS )
00571 {
00572 // if we fatal on curves
00573 if( fatal_on_curves )
00574 {
00575 std::cout << "Failed to facet the curve " << edge->id() << std::endl;
00576 return MB_FAILURE;
00577 }
00578 // otherwise record them
00579 else
00580 {
00581 failed_curve_count++;
00582 failed_curves.push_back( edge->id() );
00583 }
00584 continue;
00585 }
00586
00587 std::vector< CubitVector > points;
00588 for( int i = 0; i < data.pointListCount; ++i )
00589 // Add Cubit vertext points to a list
00590 points.push_back( CubitVector( data.point_list()[i].x, data.point_list()[i].y, data.point_list()[i].z ) );
00591
00592 // Need to reverse data?
00593 if( curve->bridge_sense() == CUBIT_REVERSED ) std::reverse( points.begin(), points.end() );
00594
00595 // Check for closed curve
00596 RefVertex *start_vtx, *end_vtx;
00597 start_vtx = edge->start_vertex();
00598 end_vtx = edge->end_vertex();
00599
00600 // Special case for point curve
00601 if( points.size() < 2 )
00602 {
00603 if( start_vtx != end_vtx || curve->measure() > GEOMETRY_RESABS )
00604 {
00605 std::cerr << "Warning: No facetting for curve " << edge->id() << std::endl;
00606 continue;
00607 }
00608 EntityHandle h = vertex_map[start_vtx];
00609 rval = mdbImpl->add_entities( ci->second, &h, 1 );
00610 if( MB_SUCCESS != rval ) return MB_FAILURE;
00611 continue;
00612 }
00613 // Check to see if the first and last interior vertices are considered to be
00614 // coincident by CUBIT
00615 const bool closed = ( points.front() - points.back() ).length() < GEOMETRY_RESABS;
00616 if( closed != ( start_vtx == end_vtx ) )
00617 {
00618 std::cerr << "Warning: topology and geometry inconsistant for possibly closed curve " << edge->id()
00619 << std::endl;
00620 }
00621
00622 // Check proximity of vertices to end coordinates
00623 if( ( start_vtx->coordinates() - points.front() ).length() > GEOMETRY_RESABS ||
00624 ( end_vtx->coordinates() - points.back() ).length() > GEOMETRY_RESABS )
00625 {
00626
00627 curve_warnings--;
00628 if( curve_warnings >= 0 || verbose_warn )
00629 {
00630 std::cerr << "Warning: vertices not at ends of curve " << edge->id() << std::endl;
00631 if( curve_warnings == 0 && !verbose_warn )
00632 {
00633 std::cerr << " further instances of this warning will be suppressed..." << std::endl;
00634 }
00635 }
00636 }
00637 // Create interior points
00638 std::vector< EntityHandle > verts, edges;
00639 verts.push_back( vertex_map[start_vtx] );
00640 for( size_t i = 1; i < points.size() - 1; ++i )
00641 {
00642 double coords[] = { points[i].x(), points[i].y(), points[i].z() };
00643 EntityHandle h;
00644 // Create vertex entity
00645 rval = mdbImpl->create_vertex( coords, h );
00646 if( MB_SUCCESS != rval ) return MB_FAILURE;
00647 verts.push_back( h );
00648 }
00649 verts.push_back( vertex_map[end_vtx] );
00650
00651 // Create edges
00652 for( size_t i = 0; i < verts.size() - 1; ++i )
00653 {
00654 EntityHandle h;
00655 rval = mdbImpl->create_element( MBEDGE, &verts[i], 2, h );
00656 if( MB_SUCCESS != rval ) return MB_FAILURE;
00657 edges.push_back( h );
00658 }
00659
00660 // If closed, remove duplicate
00661 if( verts.front() == verts.back() ) verts.pop_back();
00662 // Add entities to the curve meshset from entitymap
00663 rval = mdbImpl->add_entities( ci->second, &verts[0], verts.size() );
00664 if( MB_SUCCESS != rval ) return MB_FAILURE;
00665 rval = mdbImpl->add_entities( ci->second, &edges[0], edges.size() );
00666 if( MB_SUCCESS != rval ) return MB_FAILURE;
00667 }
00668
00669 if( !verbose_warn && curve_warnings < 0 )
00670 {
00671 std::cerr << "Suppressed " << -curve_warnings << " 'vertices not at ends of curve' warnings." << std::endl;
00672 std::cerr << "To see all warnings, use reader param VERBOSE_CGM_WARNINGS." << std::endl;
00673 }
00674
00675 return MB_SUCCESS;
00676 }
00677
00678 ErrorCode ReadCGM::create_surface_facets( std::map< RefEntity*, EntityHandle >& surface_map,
00679 std::map< RefEntity*, EntityHandle >& vertex_map,
00680 int norm_tol,
00681 double facet_tol,
00682 double length_tol )
00683 {
00684 ErrorCode rval;
00685 std::map< RefEntity*, EntityHandle >::iterator ci;
00686 CubitStatus s;
00687 #if( ( CGM_MAJOR_VERSION == 14 && CGM_MINOR_VERSION > 2 ) || CGM_MAJOR_VERSION >= 15 )
00688 DLIList< TopologyEntity* > me_list;
00689 #else
00690 DLIList< ModelEntity* > me_list;
00691 #endif
00692
00693 GMem data;
00694 // Create geometry for all surfaces
00695 for( ci = surface_map.begin(); ci != surface_map.end(); ++ci )
00696 {
00697 RefFace* face = dynamic_cast< RefFace* >( ci->first );
00698
00699 data.clean_out();
00700 s = face->get_graphics( data, norm_tol, facet_tol, length_tol );
00701
00702 if( CUBIT_SUCCESS != s ) return MB_FAILURE;
00703
00704 // Declare array of all vertex handles
00705 std::vector< EntityHandle > verts( data.pointListCount, 0 );
00706
00707 // Get list of geometric vertices in surface
00708 me_list.clean_out();
00709 ModelQueryEngine::instance()->query_model( *face, DagType::ref_vertex_type(), me_list );
00710
00711 // For each geometric vertex, find a single coincident point in facets
00712 // Otherwise, print a warning
00713 for( int i = me_list.size(); i--; )
00714 {
00715 // Assign geometric vertex
00716 RefVertex* vtx = dynamic_cast< RefVertex* >( me_list.get_and_step() );
00717 CubitVector pos = vtx->coordinates();
00718
00719 for( int j = 0; j < data.pointListCount; ++j )
00720 {
00721 // Assign facet vertex
00722 CubitVector vpos( data.point_list()[j].x, data.point_list()[j].y, data.point_list()[j].z );
00723 // Check to see if they are considered coincident
00724 if( ( pos - vpos ).length_squared() < GEOMETRY_RESABS * GEOMETRY_RESABS )
00725 {
00726 // If this facet vertex has already been found coincident, print warning
00727 if( verts[j] ) std::cerr << "Warning: Coincident vertices in surface " << face->id() << std::endl;
00728 // If a coincidence is found, keep track of it in the verts vector
00729 verts[j] = vertex_map[vtx];
00730 break;
00731 }
00732 }
00733 }
00734
00735 // Now create vertices for the remaining points in the facetting
00736 for( int i = 0; i < data.pointListCount; ++i )
00737 {
00738 if( verts[i] ) // If a geometric vertex
00739 continue;
00740 double coords[] = { data.point_list()[i].x, data.point_list()[i].y, data.point_list()[i].z };
00741 // Return vertex handle to verts to fill in all remaining facet
00742 // vertices
00743 rval = mdbImpl->create_vertex( coords, verts[i] );
00744 if( MB_SUCCESS != rval ) return rval;
00745 }
00746
00747 // record the failures for information
00748 if( data.fListCount == 0 )
00749 {
00750 failed_surface_count++;
00751 failed_surfaces.push_back( face->id() );
00752 }
00753
00754 // Now create facets
00755 Range facets;
00756 std::vector< EntityHandle > corners;
00757 for( int i = 0; i < data.fListCount; i += data.facet_list()[i] + 1 )
00758 {
00759 // Get number of facet verts
00760 int* facet = data.facet_list() + i;
00761 corners.resize( *facet );
00762 for( int j = 1; j <= *facet; ++j )
00763 {
00764 if( facet[j] >= (int)verts.size() )
00765 {
00766 std::cerr << "ERROR: Invalid facet data for surface " << face->id() << std::endl;
00767 return MB_FAILURE;
00768 }
00769 corners[j - 1] = verts[facet[j]];
00770 }
00771 EntityType type;
00772 if( *facet == 3 )
00773 type = MBTRI;
00774 else
00775 {
00776 std::cerr << "Warning: non-triangle facet in surface " << face->id() << std::endl;
00777 std::cerr << " entity has " << *facet << " edges" << std::endl;
00778 if( *facet == 4 )
00779 type = MBQUAD;
00780 else
00781 type = MBPOLYGON;
00782 }
00783
00784 // if (surf->bridge_sense() == CUBIT_REVERSED)
00785 // std::reverse(corners.begin(), corners.end());
00786
00787 EntityHandle h;
00788 rval = mdbImpl->create_element( type, &corners[0], corners.size(), h );
00789 if( MB_SUCCESS != rval ) return MB_FAILURE;
00790
00791 facets.insert( h );
00792 }
00793
00794 // Add vertices and facets to surface set
00795 rval = mdbImpl->add_entities( ci->second, &verts[0], verts.size() );
00796 if( MB_SUCCESS != rval ) return MB_FAILURE;
00797 rval = mdbImpl->add_entities( ci->second, facets );
00798 if( MB_SUCCESS != rval ) return MB_FAILURE;
00799 }
00800
00801 return MB_SUCCESS;
00802 }
00803
00804 // Copy geometry into mesh database
00805 ErrorCode ReadCGM::load_file( const char* cgm_file_name,
00806 const EntityHandle* file_set,
00807 const FileOptions& opts,
00808 const ReaderIface::SubsetList* subset_list,
00809 const Tag* /*file_id_tag*/ )
00810 {
00811 // Blocks_to_load and num_blocks are ignored.
00812 ErrorCode rval;
00813
00814 if( subset_list )
00815 {
00816 MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for CGM data" );
00817 }
00818
00819 int norm_tol;
00820 double faceting_tol;
00821 double len_tol;
00822 bool act_att = true;
00823 bool verbose_warnings = false;
00824 bool fatal_on_curves = false;
00825
00826 rval = set_options( opts, norm_tol, faceting_tol, len_tol, act_att, verbose_warnings, fatal_on_curves );
00827 if( MB_SUCCESS != rval ) return rval;
00828
00829 // Always tag with the faceting_tol and geometry absolute resolution
00830 // If file_set is defined, use that, otherwise (file_set == NULL) tag the interface
00831 EntityHandle set = file_set ? *file_set : 0;
00832 rval = mdbImpl->tag_set_data( faceting_tol_tag, &set, 1, &faceting_tol );
00833 if( MB_SUCCESS != rval ) return rval;
00834
00835 rval = mdbImpl->tag_set_data( geometry_resabs_tag, &set, 1, &GEOMETRY_RESABS );
00836 if( MB_SUCCESS != rval ) return rval;
00837
00838 // Initialize CGM
00839 InitCGMA::initialize_cgma();
00840
00841 // Determine CGM settings and amount of output
00842 set_cgm_attributes( act_att, verbose_warnings );
00843
00844 CubitStatus s;
00845
00846 // Get CGM file type
00847 const char* file_type = 0;
00848 file_type = get_geom_file_type( cgm_file_name );
00849 if( !file_type || !strcmp( file_type, "CUBIT" ) ) return MB_FAILURE;
00850
00851 s = CubitCompat_import_solid_model( cgm_file_name, file_type );
00852 if( CUBIT_SUCCESS != s )
00853 {
00854 MB_SET_ERR( MB_FAILURE, cgm_file_name << ": Failed to read file of type \"" << file_type << "\"" );
00855 }
00856
00857 // Create entity sets for all geometric entities
00858 std::map< RefEntity*, EntityHandle > entmap[5]; // One for each dim, and one for groups
00859
00860 rval = create_entity_sets( entmap );
00861 if( rval != MB_SUCCESS ) return rval;
00862
00863 // Create topology for all geometric entities
00864 rval = create_topology( entmap );
00865 if( rval != MB_SUCCESS ) return rval;
00866
00867 // Store CoFace senses
00868 rval = store_surface_senses( entmap[2], entmap[3] );
00869 if( rval != MB_SUCCESS ) return rval;
00870
00871 // Store CoEdge senses
00872 rval = store_curve_senses( entmap[1], entmap[2] );
00873 if( rval != MB_SUCCESS ) return rval;
00874
00875 // Get group information and store it in the mesh
00876 rval = store_groups( entmap );
00877 if( rval != MB_SUCCESS ) return rval;
00878
00879 // Done with volumes and groups
00880 entmap[3].clear();
00881 entmap[4].clear();
00882
00883 // Create geometry for all vertices and replace
00884 rval = create_vertices( entmap[0] );
00885 if( rval != MB_SUCCESS ) return rval;
00886
00887 // Create facets for all curves
00888 rval = create_curve_facets( entmap[1], entmap[0], norm_tol, faceting_tol, verbose_warnings, fatal_on_curves );
00889 if( rval != MB_SUCCESS ) return rval;
00890
00891 // Create facets for surfaces
00892 rval = create_surface_facets( entmap[2], entmap[0], norm_tol, faceting_tol, len_tol );
00893 if( rval != MB_SUCCESS ) return rval;
00894
00895 // print the fail information
00896 dump_fail_counts();
00897
00898 return MB_SUCCESS;
00899 }
00900
00901 // return the number of curves that failed to facet
00902 int ReadCGM::get_failed_curve_count()
00903 {
00904 return failed_curve_count;
00905 }
00906
00907 // return the number of surfaces that failed to facet
00908 int ReadCGM::get_failed_surface_count()
00909 {
00910 return failed_surface_count;
00911 }
00912
00913 void ReadCGM::dump_fail_counts()
00914 {
00915 std::cout << "***** Faceting Summary Information *****" << std::endl;
00916 std::cout << "----- Curve Fail Information -----" << std::endl;
00917 std::cout << "There were " << failed_curve_count << " curves that could not be faceted." << std::endl;
00918
00919 if( failed_curve_count > 0 )
00920 {
00921 std::cout << "The curves were ";
00922 for( int i = 0; i < failed_curve_count; i++ )
00923 {
00924 std::cout << failed_curves[i] << " ";
00925 if( ( i % 10 == 0 ) & ( i > 0 ) ) std::cout << std::endl;
00926 }
00927 }
00928 std::cout << std::endl;
00929 std::cout << "----- Facet Fail Information -----" << std::endl;
00930 std::cout << "There were " << failed_surface_count << " surfaces that could not be faceted." << std::endl;
00931 if( failed_surface_count > 0 )
00932 {
00933 std::cout << "The surfaces were ";
00934 for( int i = 0; i < failed_surface_count; i++ )
00935 {
00936 std::cout << failed_surfaces[i] << " ";
00937 if( ( i % 10 == 0 ) & ( i > 0 ) ) std::cout << std::endl;
00938 }
00939 }
00940 std::cout << std::endl;
00941 std::cout << "***** End of Faceting Summary Information *****" << std::endl;
00942 return;
00943 }
00944
00945 const char* ReadCGM::get_geom_file_type( const char* name )
00946 {
00947 FILE* file;
00948 const char* result = 0;
00949
00950 file = fopen( name, "r" );
00951 if( file )
00952 {
00953 result = get_geom_fptr_type( file );
00954 fclose( file );
00955 }
00956
00957 return result;
00958 }
00959
00960 const char* ReadCGM::get_geom_fptr_type( FILE* file )
00961 {
00962 static const char* CUBIT_NAME = GF_CUBIT_FILE_TYPE;
00963 static const char* STEP_NAME = GF_STEP_FILE_TYPE;
00964 static const char* IGES_NAME = GF_IGES_FILE_TYPE;
00965 static const char* BREP_NAME = GF_OCC_BREP_FILE_TYPE;
00966 static const char* FACET_NAME = GF_FACET_FILE_TYPE;
00967
00968 if( is_cubit_file( file ) )
00969 return CUBIT_NAME;
00970 else if( is_step_file( file ) )
00971 return STEP_NAME;
00972 else if( is_iges_file( file ) )
00973 return IGES_NAME;
00974 else if( is_occ_brep_file( file ) )
00975 return BREP_NAME;
00976 else if( is_facet_file( file ) )
00977 return FACET_NAME;
00978 else
00979 return NULL;
00980 }
00981
00982 int ReadCGM::is_cubit_file( FILE* file )
00983 {
00984 unsigned char buffer[4];
00985 return !fseek( file, 0, SEEK_SET ) && fread( buffer, 4, 1, file ) && !memcmp( buffer, "CUBE", 4 );
00986 }
00987
00988 int ReadCGM::is_step_file( FILE* file )
00989 {
00990 unsigned char buffer[9];
00991 return !fseek( file, 0, SEEK_SET ) && fread( buffer, 9, 1, file ) && !memcmp( buffer, "ISO-10303", 9 );
00992 }
00993
00994 int ReadCGM::is_iges_file( FILE* file )
00995 {
00996 unsigned char buffer[10];
00997 return !fseek( file, 72, SEEK_SET ) && fread( buffer, 10, 1, file ) && !memcmp( buffer, "S 1", 8 );
00998 }
00999
01000 int ReadCGM::is_occ_brep_file( FILE* file )
01001 {
01002 unsigned char buffer[6];
01003 return !fseek( file, 0, SEEK_SET ) && fread( buffer, 6, 1, file ) && !memcmp( buffer, "DBRep_", 6 );
01004 }
01005 int ReadCGM::is_facet_file( FILE* file )
01006 {
01007 unsigned char buffer[10];
01008 return !fseek( file, 0, SEEK_SET ) && fread( buffer, 10, 1, file ) && !memcmp( buffer, "MESH_BASED", 10 );
01009 }
01010
01011 void ReadCGM::tokenize( const std::string& str, std::vector< std::string >& tokens, const char* delimiters )
01012 {
01013 std::string::size_type last = str.find_first_not_of( delimiters, 0 );
01014 std::string::size_type pos = str.find_first_of( delimiters, last );
01015 while( std::string::npos != pos && std::string::npos != last )
01016 {
01017 tokens.push_back( str.substr( last, pos - last ) );
01018 last = str.find_first_not_of( delimiters, pos );
01019 pos = str.find_first_of( delimiters, last );
01020 if( std::string::npos == pos ) pos = str.size();
01021 }
01022 }
01023
01024 } // namespace moab