MOAB: Mesh Oriented datABase  (version 5.4.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 )
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines