MOAB: Mesh Oriented datABase  (version 5.3.0)
ReadCGM.cpp
Go to the documentation of this file.
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                 {
00616                     std::cerr << "         further instances of this warning will be suppressed..." << std::endl;
00617                 }
00618             }
00619         }
00620         // Create interior points
00621         std::vector< EntityHandle > verts, edges;
00622         verts.push_back( vertex_map[start_vtx] );
00623         for( size_t i = 1; i < points.size() - 1; ++i )
00624         {
00625             double coords[] = { points[i].x(), points[i].y(), points[i].z() };
00626             EntityHandle h;
00627             // Create vertex entity
00628             rval = mdbImpl->create_vertex( coords, h );
00629             if( MB_SUCCESS != rval ) return MB_FAILURE;
00630             verts.push_back( h );
00631         }
00632         verts.push_back( vertex_map[end_vtx] );
00633 
00634         // Create edges
00635         for( size_t i = 0; i < verts.size() - 1; ++i )
00636         {
00637             EntityHandle h;
00638             rval = mdbImpl->create_element( MBEDGE, &verts[i], 2, h );
00639             if( MB_SUCCESS != rval ) return MB_FAILURE;
00640             edges.push_back( h );
00641         }
00642 
00643         // If closed, remove duplicate
00644         if( verts.front() == verts.back() ) verts.pop_back();
00645         // Add entities to the curve meshset from entitymap
00646         rval = mdbImpl->add_entities( ci->second, &verts[0], verts.size() );
00647         if( MB_SUCCESS != rval ) return MB_FAILURE;
00648         rval = mdbImpl->add_entities( ci->second, &edges[0], edges.size() );
00649         if( MB_SUCCESS != rval ) return MB_FAILURE;
00650     }
00651 
00652     if( !verbose_warn && curve_warnings < 0 )
00653     {
00654         std::cerr << "Suppressed " << -curve_warnings << " 'vertices not at ends of curve' warnings." << std::endl;
00655         std::cerr << "To see all warnings, use reader param VERBOSE_CGM_WARNINGS." << std::endl;
00656     }
00657 
00658     return MB_SUCCESS;
00659 }
00660 
00661 ErrorCode ReadCGM::create_surface_facets( std::map< RefEntity*, EntityHandle >& surface_map,
00662                                           std::map< RefEntity*, EntityHandle >& vertex_map, int norm_tol,
00663                                           double facet_tol, double length_tol )
00664 {
00665     ErrorCode rval;
00666     std::map< RefEntity*, EntityHandle >::iterator ci;
00667     CubitStatus s;
00668 #if( ( CGM_MAJOR_VERSION == 14 && CGM_MINOR_VERSION > 2 ) || CGM_MAJOR_VERSION >= 15 )
00669     DLIList< TopologyEntity* > me_list;
00670 #else
00671     DLIList< ModelEntity* > me_list;
00672 #endif
00673 
00674     GMem data;
00675     // Create geometry for all surfaces
00676     for( ci = surface_map.begin(); ci != surface_map.end(); ++ci )
00677     {
00678         RefFace* face = dynamic_cast< RefFace* >( ci->first );
00679 
00680         data.clean_out();
00681         s = face->get_graphics( data, norm_tol, facet_tol, length_tol );
00682 
00683         if( CUBIT_SUCCESS != s ) return MB_FAILURE;
00684 
00685         // Declare array of all vertex handles
00686         std::vector< EntityHandle > verts( data.pointListCount, 0 );
00687 
00688         // Get list of geometric vertices in surface
00689         me_list.clean_out();
00690         ModelQueryEngine::instance()->query_model( *face, DagType::ref_vertex_type(), me_list );
00691 
00692         // For each geometric vertex, find a single coincident point in facets
00693         // Otherwise, print a warning
00694         for( int i = me_list.size(); i--; )
00695         {
00696             // Assign geometric vertex
00697             RefVertex* vtx  = dynamic_cast< RefVertex* >( me_list.get_and_step() );
00698             CubitVector pos = vtx->coordinates();
00699 
00700             for( int j = 0; j < data.pointListCount; ++j )
00701             {
00702                 // Assign facet vertex
00703                 CubitVector vpos( data.point_list()[j].x, data.point_list()[j].y, data.point_list()[j].z );
00704                 // Check to see if they are considered coincident
00705                 if( ( pos - vpos ).length_squared() < GEOMETRY_RESABS * GEOMETRY_RESABS )
00706                 {
00707                     // If this facet vertex has already been found coincident, print warning
00708                     if( verts[j] ) std::cerr << "Warning: Coincident vertices in surface " << face->id() << std::endl;
00709                     // If a coincidence is found, keep track of it in the verts vector
00710                     verts[j] = vertex_map[vtx];
00711                     break;
00712                 }
00713             }
00714         }
00715 
00716         // Now create vertices for the remaining points in the facetting
00717         for( int i = 0; i < data.pointListCount; ++i )
00718         {
00719             if( verts[i] )  // If a geometric vertex
00720                 continue;
00721             double coords[] = { data.point_list()[i].x, data.point_list()[i].y, data.point_list()[i].z };
00722             // Return vertex handle to verts to fill in all remaining facet
00723             // vertices
00724             rval = mdbImpl->create_vertex( coords, verts[i] );
00725             if( MB_SUCCESS != rval ) return rval;
00726         }
00727 
00728         // record the failures for information
00729         if( data.fListCount == 0 )
00730         {
00731             failed_surface_count++;
00732             failed_surfaces.push_back( face->id() );
00733         }
00734 
00735         // Now create facets
00736         Range facets;
00737         std::vector< EntityHandle > corners;
00738         for( int i = 0; i < data.fListCount; i += data.facet_list()[i] + 1 )
00739         {
00740             // Get number of facet verts
00741             int* facet = data.facet_list() + i;
00742             corners.resize( *facet );
00743             for( int j = 1; j <= *facet; ++j )
00744             {
00745                 if( facet[j] >= (int)verts.size() )
00746                 {
00747                     std::cerr << "ERROR: Invalid facet data for surface " << face->id() << std::endl;
00748                     return MB_FAILURE;
00749                 }
00750                 corners[j - 1] = verts[facet[j]];
00751             }
00752             EntityType type;
00753             if( *facet == 3 )
00754                 type = MBTRI;
00755             else
00756             {
00757                 std::cerr << "Warning: non-triangle facet in surface " << face->id() << std::endl;
00758                 std::cerr << "  entity has " << *facet << " edges" << std::endl;
00759                 if( *facet == 4 )
00760                     type = MBQUAD;
00761                 else
00762                     type = MBPOLYGON;
00763             }
00764 
00765             // if (surf->bridge_sense() == CUBIT_REVERSED)
00766             // std::reverse(corners.begin(), corners.end());
00767 
00768             EntityHandle h;
00769             rval = mdbImpl->create_element( type, &corners[0], corners.size(), h );
00770             if( MB_SUCCESS != rval ) return MB_FAILURE;
00771 
00772             facets.insert( h );
00773         }
00774 
00775         // Add vertices and facets to surface set
00776         rval = mdbImpl->add_entities( ci->second, &verts[0], verts.size() );
00777         if( MB_SUCCESS != rval ) return MB_FAILURE;
00778         rval = mdbImpl->add_entities( ci->second, facets );
00779         if( MB_SUCCESS != rval ) return MB_FAILURE;
00780     }
00781 
00782     return MB_SUCCESS;
00783 }
00784 
00785 // Copy geometry into mesh database
00786 ErrorCode ReadCGM::load_file( const char* cgm_file_name, const EntityHandle* file_set, const FileOptions& opts,
00787                               const ReaderIface::SubsetList* subset_list, const Tag* /*file_id_tag*/ )
00788 {
00789     // Blocks_to_load and num_blocks are ignored.
00790     ErrorCode rval;
00791 
00792     if( subset_list ) { MB_SET_ERR( MB_UNSUPPORTED_OPERATION, "Reading subset of files not supported for CGM data" ); }
00793 
00794     int norm_tol;
00795     double faceting_tol;
00796     double len_tol;
00797     bool act_att          = true;
00798     bool verbose_warnings = false;
00799     bool fatal_on_curves  = false;
00800 
00801     rval = set_options( opts, norm_tol, faceting_tol, len_tol, act_att, verbose_warnings, fatal_on_curves );
00802     if( MB_SUCCESS != rval ) return rval;
00803 
00804     // Always tag with the faceting_tol and geometry absolute resolution
00805     // If file_set is defined, use that, otherwise (file_set == NULL) tag the interface
00806     EntityHandle set = file_set ? *file_set : 0;
00807     rval             = mdbImpl->tag_set_data( faceting_tol_tag, &set, 1, &faceting_tol );
00808     if( MB_SUCCESS != rval ) return rval;
00809 
00810     rval = mdbImpl->tag_set_data( geometry_resabs_tag, &set, 1, &GEOMETRY_RESABS );
00811     if( MB_SUCCESS != rval ) return rval;
00812 
00813     // Initialize CGM
00814     InitCGMA::initialize_cgma();
00815 
00816     // Determine CGM settings and amount of output
00817     set_cgm_attributes( act_att, verbose_warnings );
00818 
00819     CubitStatus s;
00820 
00821     // Get CGM file type
00822     const char* file_type = 0;
00823     file_type             = get_geom_file_type( cgm_file_name );
00824     if( !file_type || !strcmp( file_type, "CUBIT" ) ) return MB_FAILURE;
00825 
00826     s = CubitCompat_import_solid_model( cgm_file_name, file_type );
00827     if( CUBIT_SUCCESS != s )
00828     {
00829         MB_SET_ERR( MB_FAILURE, cgm_file_name << ": Failed to read file of type \"" << file_type << "\"" );
00830     }
00831 
00832     // Create entity sets for all geometric entities
00833     std::map< RefEntity*, EntityHandle > entmap[5];  // One for each dim, and one for groups
00834 
00835     rval = create_entity_sets( entmap );
00836     if( rval != MB_SUCCESS ) return rval;
00837 
00838     // Create topology for all geometric entities
00839     rval = create_topology( entmap );
00840     if( rval != MB_SUCCESS ) return rval;
00841 
00842     // Store CoFace senses
00843     rval = store_surface_senses( entmap[2], entmap[3] );
00844     if( rval != MB_SUCCESS ) return rval;
00845 
00846     // Store CoEdge senses
00847     rval = store_curve_senses( entmap[1], entmap[2] );
00848     if( rval != MB_SUCCESS ) return rval;
00849 
00850     // Get group information and store it in the mesh
00851     rval = store_groups( entmap );
00852     if( rval != MB_SUCCESS ) return rval;
00853 
00854     // Done with volumes and groups
00855     entmap[3].clear();
00856     entmap[4].clear();
00857 
00858     // Create geometry for all vertices and replace
00859     rval = create_vertices( entmap[0] );
00860     if( rval != MB_SUCCESS ) return rval;
00861 
00862     // Create facets for all curves
00863     rval = create_curve_facets( entmap[1], entmap[0], norm_tol, faceting_tol, verbose_warnings, fatal_on_curves );
00864     if( rval != MB_SUCCESS ) return rval;
00865 
00866     // Create facets for surfaces
00867     rval = create_surface_facets( entmap[2], entmap[0], norm_tol, faceting_tol, len_tol );
00868     if( rval != MB_SUCCESS ) return rval;
00869 
00870     // print the fail information
00871     dump_fail_counts();
00872 
00873     return MB_SUCCESS;
00874 }
00875 
00876 // return the number of curves that failed to facet
00877 int ReadCGM::get_failed_curve_count()
00878 {
00879     return failed_curve_count;
00880 }
00881 
00882 // return the number of surfaces that failed to facet
00883 int ReadCGM::get_failed_surface_count()
00884 {
00885     return failed_surface_count;
00886 }
00887 
00888 void ReadCGM::dump_fail_counts()
00889 {
00890     std::cout << "***** Faceting Summary Information *****" << std::endl;
00891     std::cout << "----- Curve Fail Information -----" << std::endl;
00892     std::cout << "There were " << failed_curve_count << " curves that could not be faceted." << std::endl;
00893 
00894     if( failed_curve_count > 0 )
00895     {
00896         std::cout << "The curves were ";
00897         for( int i = 0; i < failed_curve_count; i++ )
00898         {
00899             std::cout << failed_curves[i] << " ";
00900             if( ( i % 10 == 0 ) & ( i > 0 ) ) std::cout << std::endl;
00901         }
00902     }
00903     std::cout << std::endl;
00904     std::cout << "----- Facet Fail Information -----" << std::endl;
00905     std::cout << "There were " << failed_surface_count << " surfaces that could not be faceted." << std::endl;
00906     if( failed_surface_count > 0 )
00907     {
00908         std::cout << "The surfaces were ";
00909         for( int i = 0; i < failed_surface_count; i++ )
00910         {
00911             std::cout << failed_surfaces[i] << " ";
00912             if( ( i % 10 == 0 ) & ( i > 0 ) ) std::cout << std::endl;
00913         }
00914     }
00915     std::cout << std::endl;
00916     std::cout << "***** End of Faceting Summary Information *****" << std::endl;
00917     return;
00918 }
00919 
00920 const char* ReadCGM::get_geom_file_type( const char* name )
00921 {
00922     FILE* file;
00923     const char* result = 0;
00924 
00925     file = fopen( name, "r" );
00926     if( file )
00927     {
00928         result = get_geom_fptr_type( file );
00929         fclose( file );
00930     }
00931 
00932     return result;
00933 }
00934 
00935 const char* ReadCGM::get_geom_fptr_type( FILE* file )
00936 {
00937     static const char* CUBIT_NAME = GF_CUBIT_FILE_TYPE;
00938     static const char* STEP_NAME  = GF_STEP_FILE_TYPE;
00939     static const char* IGES_NAME  = GF_IGES_FILE_TYPE;
00940     static const char* BREP_NAME  = GF_OCC_BREP_FILE_TYPE;
00941     static const char* FACET_NAME = GF_FACET_FILE_TYPE;
00942 
00943     if( is_cubit_file( file ) )
00944         return CUBIT_NAME;
00945     else if( is_step_file( file ) )
00946         return STEP_NAME;
00947     else if( is_iges_file( file ) )
00948         return IGES_NAME;
00949     else if( is_occ_brep_file( file ) )
00950         return BREP_NAME;
00951     else if( is_facet_file( file ) )
00952         return FACET_NAME;
00953     else
00954         return NULL;
00955 }
00956 
00957 int ReadCGM::is_cubit_file( FILE* file )
00958 {
00959     unsigned char buffer[4];
00960     return !fseek( file, 0, SEEK_SET ) && fread( buffer, 4, 1, file ) && !memcmp( buffer, "CUBE", 4 );
00961 }
00962 
00963 int ReadCGM::is_step_file( FILE* file )
00964 {
00965     unsigned char buffer[9];
00966     return !fseek( file, 0, SEEK_SET ) && fread( buffer, 9, 1, file ) && !memcmp( buffer, "ISO-10303", 9 );
00967 }
00968 
00969 int ReadCGM::is_iges_file( FILE* file )
00970 {
00971     unsigned char buffer[10];
00972     return !fseek( file, 72, SEEK_SET ) && fread( buffer, 10, 1, file ) && !memcmp( buffer, "S      1", 8 );
00973 }
00974 
00975 int ReadCGM::is_occ_brep_file( FILE* file )
00976 {
00977     unsigned char buffer[6];
00978     return !fseek( file, 0, SEEK_SET ) && fread( buffer, 6, 1, file ) && !memcmp( buffer, "DBRep_", 6 );
00979 }
00980 int ReadCGM::is_facet_file( FILE* file )
00981 {
00982     unsigned char buffer[10];
00983     return !fseek( file, 0, SEEK_SET ) && fread( buffer, 10, 1, file ) && !memcmp( buffer, "MESH_BASED", 10 );
00984 }
00985 
00986 void ReadCGM::tokenize( const std::string& str, std::vector< std::string >& tokens, const char* delimiters )
00987 {
00988     std::string::size_type last = str.find_first_not_of( delimiters, 0 );
00989     std::string::size_type pos  = str.find_first_of( delimiters, last );
00990     while( std::string::npos != pos && std::string::npos != last )
00991     {
00992         tokens.push_back( str.substr( last, pos - last ) );
00993         last = str.find_first_not_of( delimiters, pos );
00994         pos  = str.find_first_of( delimiters, last );
00995         if( std::string::npos == pos ) pos = str.size();
00996     }
00997 }
00998 
00999 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines