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