MOAB: Mesh Oriented datABase  (version 5.3.1)
MsqIMesh.cpp
Go to the documentation of this file.
00001 /* *****************************************************************
00002     MESQUITE -- The Mesh Quality Improvement Toolkit
00003 
00004     Copyright 2007 Sandia National Laboratories.  Developed at the
00005     University of Wisconsin--Madison under SNL contract number
00006     624796.  The U.S. Government and the University of Wisconsin
00007     retain certain rights to 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     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Lesser General Public License for more details.
00018 
00019     You should have received a copy of the GNU Lesser General Public License
00020     (lgpl.txt) along with this library; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 
00023     (2007) kraftche@cae.wisc.edu
00024 
00025   ***************************************************************** */
00026 
00027 /** \file MsqIMesh.cpp
00028  *  \brief
00029  *  \author Jason Kraftcheck
00030  */
00031 
00032 #include "MsqIMesh.hpp"
00033 #include "MsqError.hpp"
00034 #include "MeshInterface.hpp"
00035 #include "MsqDebug.hpp"
00036 #include "MsqVertex.hpp"
00037 #include <cassert>
00038 #include "MsqIBase.hpp"
00039 #include <algorithm>
00040 
00041 #ifdef IMESH_MAJOR_VERSION
00042 #define IMESH_VERSION_ATLEAST( MAJOR, MINOR ) \
00043     ( 1000 * IMESH_MAJOR_VERSION + IMESH_MINOR_VERSION <= 1000 * ( MAJOR ) + ( MINOR ) )
00044 #else
00045 #define IMESH_VERSION_ATLEAST( MAJOR, MINOR ) 0
00046 #endif
00047 
00048 namespace MBMesquite
00049 {
00050 
00051 /*************************************************************************
00052  *                          Mesh Definition
00053  ************************************************************************/
00054 
00055 MsqIMesh::MsqIMesh( iMesh_Instance mesh, iBase_EntitySetHandle meshset, iBase_EntityType type, MsqError& err,
00056                     const iBase_TagHandle* fixed_tag, const iBase_TagHandle* slaved_tag )
00057     : meshInstance( mesh ), inputSetType( iBase_ALL_TYPES ), inputSet( 0 ), byteTag( 0 ), createdByteTag( false ),
00058       geometricDimension( 0 )
00059 {
00060     init_active_mesh( mesh, err, fixed_tag, slaved_tag );MSQ_ERRRTN( err );
00061     set_active_set( meshset, type, err );MSQ_ERRRTN( err );
00062 }
00063 
00064 MsqIMesh::MsqIMesh( iMesh_Instance mesh, iBase_EntityType type, MsqError& err, const iBase_TagHandle* fixed_tag,
00065                     const iBase_TagHandle* slaved_tag )
00066     : meshInstance( mesh ), inputSetType( iBase_ALL_TYPES ), inputSet( 0 ), byteTag( 0 ), createdByteTag( false ),
00067       geometricDimension( 0 )
00068 {
00069     init_active_mesh( mesh, err, fixed_tag, slaved_tag );MSQ_ERRRTN( err );
00070 
00071     int ierr;
00072     iBase_EntitySetHandle root_set;
00073     iMesh_getRootSet( mesh, &root_set, &ierr );
00074     if( ierr != iBase_SUCCESS )
00075     {
00076         MSQ_SETERR( err )( "Invalid iMesh instance.", MsqError::INVALID_STATE );
00077         return;
00078     }
00079     set_active_set( root_set, type, err );MSQ_ERRRTN( err );
00080 }
00081 
00082 MsqIMesh::~MsqIMesh()
00083 {
00084     int ierr;
00085     if( createdByteTag ) iMesh_destroyTag( meshInstance, byteTag, true, &ierr );
00086 }
00087 
00088 iMesh_Instance MsqIMesh::get_imesh_instance() const
00089 {
00090     return meshInstance;
00091 }
00092 
00093 iBase_EntitySetHandle MsqIMesh::get_entity_set() const
00094 {
00095     return inputSet;
00096 }
00097 
00098 iBase_TagValueType MsqIMesh::check_valid_flag_tag( iBase_TagHandle tag, const char* which_flag, MsqError& err )
00099 {
00100     int ierr, size, type;
00101     const int MAX_NAME_LEN = 127;
00102     char name[MAX_NAME_LEN + 1];
00103 
00104     std::fill( name, name + sizeof( name ), '\0' );
00105     iMesh_getTagName( meshInstance, tag, name, &ierr, MAX_NAME_LEN );
00106     name[MAX_NAME_LEN - 1] = '\0';  // make sure strings are null-terminated
00107     if( iBase_SUCCESS != ierr )
00108     {
00109         MSQ_SETERR( err )
00110         ( MsqError::INVALID_ARG, "Invalid tag handle for vertex %s flag", which_flag );
00111         return iBase_ENTITY_HANDLE;
00112     }
00113     iMesh_getTagSizeBytes( meshInstance, tag, &size, &ierr );
00114     if( iBase_SUCCESS != ierr || size != sizeof( int ) )
00115     {
00116         MSQ_SETERR( err )( MsqError::INVALID_STATE, "Tag \"%s\" exists with invalid size", name );
00117         return iBase_ENTITY_HANDLE;
00118     }
00119 
00120     iMesh_getTagType( meshInstance, tag, &type, &ierr );
00121     if( iBase_SUCCESS != ierr || ( type != iBase_INTEGER && type != iBase_BYTES ) )
00122     {
00123         MSQ_SETERR( err )( MsqError::INVALID_STATE, "Tag \"%s\" exists with invalid type", name );
00124         return iBase_ENTITY_HANDLE;
00125     }
00126     return static_cast< iBase_TagValueType >( type );
00127 }
00128 
00129 void MsqIMesh::init_active_mesh( iMesh_Instance /*mesh*/, MsqError& err, const iBase_TagHandle* fixed_tag,
00130                                  const iBase_TagHandle* slaved_tag )
00131 {
00132     int ierr;
00133 
00134     // Initialize topology map
00135 
00136     const size_t mapsize = sizeof( topologyMap ) / sizeof( MBMesquite::EntityTopology );
00137     if( mapsize < iMesh_ALL_TOPOLOGIES )
00138     {
00139         MSQ_SETERR( err )
00140         ( "MsqIMesh needs to be updated for new iMesh element topologies.", MsqError::INTERNAL_ERROR );
00141     }
00142 
00143     for( size_t i = 0; i <= iMesh_ALL_TOPOLOGIES; ++i )
00144         topologyMap[i] = MBMesquite::MIXED;
00145 
00146     topologyMap[iMesh_TRIANGLE]      = MBMesquite::TRIANGLE;
00147     topologyMap[iMesh_QUADRILATERAL] = MBMesquite::QUADRILATERAL;
00148     topologyMap[iMesh_TETRAHEDRON]   = MBMesquite::TETRAHEDRON;
00149     topologyMap[iMesh_HEXAHEDRON]    = MBMesquite::HEXAHEDRON;
00150     topologyMap[iMesh_PRISM]         = MBMesquite::PRISM;
00151     topologyMap[iMesh_PYRAMID]       = MBMesquite::PYRAMID;
00152 
00153     // Check that fixed tag is valid
00154     haveFixedTag = false;
00155     if( fixed_tag )
00156     {
00157         fixedTagType = check_valid_flag_tag( *fixed_tag, "fixed", err );MSQ_ERRRTN( err );
00158         haveFixedTag = true;
00159         fixedTag     = *fixed_tag;
00160     }
00161 
00162     // Check that slaved tag is valid
00163     haveSlavedTag = false;
00164     if( slaved_tag )
00165     {
00166         slavedTagType = check_valid_flag_tag( *slaved_tag, "slaved", err );MSQ_ERRRTN( err );
00167         haveSlavedTag = true;
00168         slavedTag     = *slaved_tag;
00169     }
00170 
00171     // Get/create tag for vertex byte
00172     iMesh_getTagHandle( meshInstance, VERTEX_BYTE_TAG_NAME, &byteTag, &ierr, strlen( VERTEX_BYTE_TAG_NAME ) );
00173     if( iBase_SUCCESS != ierr )
00174     {
00175         iMesh_createTag( meshInstance, VERTEX_BYTE_TAG_NAME, 1, iBase_INTEGER, &byteTag, &ierr,
00176                          strlen( VERTEX_BYTE_TAG_NAME ) );
00177         if( iBase_SUCCESS != ierr )
00178         {
00179             MSQ_SETERR( err )
00180             ( MsqError::INVALID_STATE, "Tag \"%s\" could not be created", VERTEX_BYTE_TAG_NAME );
00181             return;
00182         }
00183         createdByteTag = true;
00184     }
00185     else
00186     {
00187         int size, type;
00188         iMesh_getTagSizeBytes( meshInstance, byteTag, &size, &ierr );
00189         if( iBase_SUCCESS != ierr || size != sizeof( int ) )
00190         {
00191             MSQ_SETERR( err )
00192             ( MsqError::INVALID_STATE, "Tag \"%s\" exists with invalid size", VERTEX_BYTE_TAG_NAME );
00193             return;
00194         }
00195         iMesh_getTagType( meshInstance, byteTag, &type, &ierr );
00196         if( iBase_SUCCESS != ierr || type != iBase_INTEGER )
00197         {
00198             MSQ_SETERR( err )
00199             ( MsqError::INVALID_STATE, "Tag \"%s\" exists with invalid type", VERTEX_BYTE_TAG_NAME );
00200             return;
00201         }
00202     }
00203     iMesh_getGeometricDimension( meshInstance, &geometricDimension, &ierr );
00204     if( iBase_SUCCESS != ierr )
00205     {
00206         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00207         return;
00208     }
00209 }
00210 
00211 void MsqIMesh::set_fixed_tag( iBase_TagHandle tag, MsqError& err )
00212 {
00213     iBase_TagValueType t = check_valid_flag_tag( tag, "fixed", err );MSQ_ERRRTN( err );
00214     fixedTag     = tag;
00215     fixedTagType = t;
00216     haveFixedTag = true;
00217 }
00218 
00219 void MsqIMesh::clear_fixed_tag()
00220 {
00221     haveFixedTag = false;
00222 }
00223 
00224 const iBase_TagHandle* MsqIMesh::get_fixed_tag() const
00225 {
00226     return haveFixedTag ? &fixedTag : 0;
00227 }
00228 
00229 void MsqIMesh::set_slaved_tag( iBase_TagHandle tag, MsqError& err )
00230 {
00231     iBase_TagValueType t = check_valid_flag_tag( tag, "slaved", err );MSQ_ERRRTN( err );
00232     slavedTag     = tag;
00233     slavedTagType = t;
00234     haveSlavedTag = true;
00235 }
00236 
00237 void MsqIMesh::clear_slaved_tag()
00238 {
00239     haveSlavedTag = false;
00240 }
00241 
00242 const iBase_TagHandle* MsqIMesh::get_slaved_tag() const
00243 {
00244     return haveSlavedTag ? &slavedTag : 0;
00245 }
00246 
00247 void MsqIMesh::set_active_set( iBase_EntitySetHandle elem_set, iBase_EntityType type_in, MsqError& err )
00248 {
00249     inputSetType = type_in;
00250     inputSet     = elem_set;
00251 
00252     // clear vertex byte
00253     std::vector< VertexHandle > verts;
00254     get_all_vertices( verts, err );MSQ_ERRRTN( err );
00255     if( !verts.empty() )
00256     {
00257         std::vector< unsigned char > zeros( verts.size(), 0 );
00258         vertices_set_byte( arrptr( verts ), arrptr( zeros ), verts.size(), err );MSQ_CHKERR( err );
00259     }
00260 }
00261 
00262 // Returns whether this mesh lies in a 2D or 3D coordinate system.
00263 int MsqIMesh::get_geometric_dimension( MBMesquite::MsqError& /*err*/ )
00264 {
00265     return geometricDimension;
00266 }
00267 
00268 //************ Vertex Properties ********************
00269 
00270 void MsqIMesh::get_flag_data( iBase_TagHandle tag, bool have_tag, iBase_TagValueType type,
00271                               const VertexHandle vert_array[], std::vector< bool >& flag_array, size_t num_vtx,
00272                               MsqError& err )
00273 {
00274     if( !num_vtx ) return;
00275 
00276     if( !have_tag )
00277     {
00278         flag_array.clear();
00279         flag_array.resize( num_vtx, false );
00280         return;
00281     }
00282 
00283     flag_array.resize( num_vtx );
00284 
00285     assert( sizeof( VertexHandle ) == sizeof( iBase_EntityHandle ) );
00286     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( vert_array );
00287 
00288     int ierr, alloc = num_vtx, size = 0;
00289     assert( (size_t)alloc == num_vtx );  // size_t can hold larger values than int if 64-bit
00290 
00291     if( type == iBase_INTEGER )
00292     {
00293         std::vector< int > values( num_vtx );
00294         int* ptr = arrptr( values );
00295         iMesh_getIntArrData( meshInstance, arr, num_vtx, tag, &ptr, &alloc, &size, &ierr );
00296         for( int i = 0; i < size; ++i )
00297             flag_array[i] = !!values[i];
00298     }
00299     else if( type == iBase_BYTES )
00300     {
00301         std::vector< char > values( num_vtx );
00302         void* ptr = arrptr( values );
00303         iMesh_getArrData( meshInstance, arr, num_vtx, tag, &ptr, &alloc, &size, &ierr );
00304         for( int i = 0; i < size; ++i )
00305             flag_array[i] = !!values[i];
00306     }
00307     else
00308     {
00309         MSQ_SETERR( err )( "Invalid tag type for vertex flag data", MsqError::INVALID_STATE );
00310         return;
00311     }
00312 
00313     // check if query for tag data failed
00314     if( iBase_SUCCESS != ierr )
00315     {
00316         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00317         return;
00318     }
00319 
00320     // make sure we got back the requested number of values
00321     assert( static_cast< size_t >( size ) == num_vtx );
00322 }
00323 
00324 // Returns true or false, indicating whether the vertex
00325 // is allowed to be repositioned.  True indicates that the vertex
00326 // is fixed and cannot be moved.  Note that this is a read-only
00327 // property; this flag can't be modified by users of the
00328 // MBMesquite::Mesh interface.
00329 void MsqIMesh::vertices_get_fixed_flag( const VertexHandle vert_array[], std::vector< bool >& bool_array,
00330                                         size_t num_vtx, MsqError& err )
00331 {
00332     get_flag_data( fixedTag, haveFixedTag, fixedTagType, vert_array, bool_array, num_vtx, err );
00333 }
00334 
00335 void MsqIMesh::vertices_get_slaved_flag( const VertexHandle vert_array[], std::vector< bool >& bool_array,
00336                                          size_t num_vtx, MsqError& err )
00337 {
00338     get_flag_data( slavedTag, haveSlavedTag, slavedTagType, vert_array, bool_array, num_vtx, err );
00339 }
00340 
00341 // Get vertex coordinates
00342 void MsqIMesh::vertices_get_coordinates( const MBMesquite::Mesh::VertexHandle vert_array[], MsqVertex* coordinates,
00343                                          size_t num_vtx, MsqError& err )
00344 {
00345     if( !num_vtx ) return;
00346 
00347     std::vector< double > dbl_store( 3 * num_vtx );
00348     double* dbl_array = arrptr( dbl_store );
00349 
00350     int ierr, junk = 3 * num_vtx, junk2;
00351     assert( sizeof( VertexHandle ) == sizeof( iBase_EntityHandle ) );
00352     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( vert_array );
00353     iMesh_getVtxArrCoords( meshInstance, arr, num_vtx, iBase_INTERLEAVED, &dbl_array, &junk, &junk2, &ierr );
00354     if( iBase_SUCCESS != ierr )
00355     {
00356         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00357         return;
00358     }
00359 
00360     if( geometricDimension == 2 )
00361     {
00362         double* iter = dbl_array;
00363         for( size_t i = 0; i < num_vtx; ++i )
00364         {
00365             coordinates[i].x( *iter );
00366             ++iter;
00367             coordinates[i].y( *iter );
00368             ++iter;
00369             coordinates[i].z( 0 );
00370         }
00371     }
00372     else
00373     {
00374         double* iter = dbl_array;
00375         for( size_t i = 0; i < num_vtx; ++i )
00376         {
00377             coordinates[i].set( iter );
00378             iter += 3;
00379         }
00380     }
00381 }
00382 
00383 void MsqIMesh::vertex_set_coordinates( MBMesquite::Mesh::VertexHandle vertex, const Vector3D& coords, MsqError& err )
00384 {
00385     int ierr;
00386     iBase_EntityHandle bh = static_cast< iBase_EntityHandle >( vertex );
00387     iMesh_setVtxCoord( meshInstance, bh, coords[0], coords[1], coords[2], &ierr );
00388     if( iBase_SUCCESS != ierr ) MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00389 }
00390 
00391 // Each vertex has a byte-sized flag that can be used to store
00392 // flags.  This byte's value is neither set nor used by the mesh
00393 // implementation.  It is intended to be used by Mesquite algorithms.
00394 // Until a vertex's byte has been explicitly set, its value is 0.
00395 void MsqIMesh::vertex_set_byte( MBMesquite::Mesh::VertexHandle vertex, unsigned char byte, MsqError& err )
00396 {
00397     int ierr, value = byte;
00398     iBase_EntityHandle bh = static_cast< iBase_EntityHandle >( vertex );
00399     iMesh_setIntData( meshInstance, bh, byteTag, value, &ierr );
00400     if( iBase_SUCCESS != ierr ) MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00401 }
00402 
00403 void MsqIMesh::vertices_set_byte( const VertexHandle* vert_array, const unsigned char* byte_array, size_t array_size,
00404                                   MsqError& err )
00405 {
00406     if( !array_size ) return;
00407 
00408     std::vector< int > data( array_size );
00409     std::copy( byte_array, byte_array + array_size, data.begin() );
00410     int ierr;
00411     assert( sizeof( VertexHandle ) == sizeof( iBase_EntityHandle ) );
00412     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( vert_array );
00413     iMesh_setIntArrData( meshInstance, arr, array_size, byteTag, arrptr( data ), array_size, &ierr );
00414     if( iBase_SUCCESS != ierr ) MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00415 }
00416 
00417 // Retrieve the byte value for the specified vertex or vertices.
00418 // The byte value is 0 if it has not yet been set via one of the
00419 // *_set_byte() functions.
00420 void MsqIMesh::vertex_get_byte( MBMesquite::Mesh::VertexHandle vertex, unsigned char* byte, MsqError& err )
00421 {
00422     int ierr, value;
00423     iBase_EntityHandle bh = static_cast< iBase_EntityHandle >( vertex );
00424     iMesh_getIntData( meshInstance, bh, byteTag, &value, &ierr );
00425     if( iBase_SUCCESS != ierr ) MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00426     *byte = value;
00427 }
00428 
00429 void MsqIMesh::vertices_get_byte( const VertexHandle* vert_array, unsigned char* byte_array, size_t array_size,
00430                                   MsqError& err )
00431 {
00432     if( !array_size ) return;
00433 
00434     std::vector< int > data( array_size );
00435     int ierr;
00436     int* ptr  = arrptr( data );
00437     int junk1 = data.size(), junk2;
00438     assert( sizeof( VertexHandle ) == sizeof( iBase_EntityHandle ) );
00439     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( vert_array );
00440     iMesh_getIntArrData( meshInstance, arr, array_size, byteTag, &ptr, &junk1, &junk2, &ierr );
00441     if( iBase_SUCCESS != ierr ) MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00442     std::copy( data.begin(), data.end(), byte_array );
00443 }
00444 
00445 //**************** Topology *****************
00446 
00447 void MsqIMesh::get_adjacent_entities( const iBase_EntityHandle* source, size_t num_source, iBase_EntityType target_type,
00448                                       std::vector< EntityHandle >& target, std::vector< size_t >& offsets,
00449                                       MsqError& err )
00450 {
00451     if( num_source == 0 )
00452     {
00453         target.clear();
00454         offsets.clear();
00455         offsets.reserve( 1 );
00456         offsets.push_back( 0 );
00457         return;
00458     }
00459 
00460     int ierr, num_adj = 0, num_offset;
00461 
00462     assert( sizeof( size_t ) >= sizeof( int ) );
00463     offsets.resize( num_source + 1 );
00464     int* ptr2;
00465     bool expand = false;
00466     if( sizeof( size_t ) > sizeof( int ) )
00467     {
00468         ptr2   = (int*)malloc( sizeof( int ) * ( num_source + 1 ) );
00469         expand = true;
00470     }
00471     else
00472     {
00473         // sizeof(int) == sizeof(size_t)
00474         ptr2 = (int*)arrptr( offsets );
00475     }
00476 
00477     assert( sizeof( iBase_EntityHandle ) == sizeof( EntityHandle ) );
00478     bool have_adj = false;
00479     // If passed vector has allocated storage, try to use existing space
00480     if( target.capacity() >= num_source )
00481     {
00482         target.resize( target.capacity() );
00483         int junk1 = target.capacity(), junk3 = offsets.size();
00484         iBase_EntityHandle* ptr = reinterpret_cast< iBase_EntityHandle* >( arrptr( target ) );
00485         iMesh_getEntArrAdj( meshInstance, source, num_source, target_type, &ptr, &junk1, &num_adj, &ptr2, &junk3,
00486                             &num_offset, &ierr );
00487         if( iBase_SUCCESS == ierr )
00488         {
00489             have_adj = true;
00490             target.resize( num_adj );
00491         }
00492     }
00493 
00494     // If implementation passed back a size, try that
00495     if( !have_adj && num_adj && (unsigned)num_adj > target.capacity() )
00496     {
00497         target.resize( num_adj );
00498         int junk1 = target.capacity(), junk3 = offsets.size();
00499         iBase_EntityHandle* ptr = reinterpret_cast< iBase_EntityHandle* >( arrptr( target ) );
00500         iMesh_getEntArrAdj( meshInstance, source, num_source, target_type, &ptr, &junk1, &num_adj, &ptr2, &junk3,
00501                             &num_offset, &ierr );
00502         if( iBase_SUCCESS == ierr ) have_adj = true;
00503     }
00504 
00505     // Try with empty sidl array, and copy into elements vector
00506     if( !have_adj )
00507     {
00508         iBase_EntityHandle* mArray = 0;
00509         int junk1 = 0, junk3 = offsets.size();
00510         iMesh_getEntArrAdj( meshInstance, source, num_source, target_type, &mArray, &junk1, &num_adj, &ptr2, &junk3,
00511                             &num_offset, &ierr );
00512         if( iBase_SUCCESS != ierr )
00513         {
00514             MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00515             return;
00516         }
00517 
00518         target.resize( num_adj );
00519         std::copy( mArray, mArray + num_adj, reinterpret_cast< iBase_EntityHandle* >( arrptr( target ) ) );
00520         free( mArray );
00521     }
00522 
00523     if( expand )
00524     {
00525         for( size_t i = num_offset; i > 0; --i )
00526             offsets[i - 1] = static_cast< size_t >( ptr2[i - 1] );
00527         free( ptr2 );
00528     }
00529 
00530     // iMesh implementations seem to be inconsistent with regard to
00531     // placing the last value on this list.
00532     if( offsets.size() - num_offset == 1 ) offsets[num_offset++] = num_adj;
00533     assert( (unsigned)num_offset == offsets.size() );
00534 }
00535 
00536 void MsqIMesh::vertices_get_attached_elements( const VertexHandle* vertices, size_t num_vertex,
00537                                                std::vector< ElementHandle >& elements, std::vector< size_t >& offsets,
00538                                                MsqError& err )
00539 {
00540     int ierr, cont;
00541     assert( sizeof( EntityHandle ) == sizeof( iBase_EntityHandle ) );
00542     const iBase_EntityHandle* verts = reinterpret_cast< const iBase_EntityHandle* >( vertices );
00543     get_adjacent_entities( verts, num_vertex, inputSetType, elements, offsets, err );MSQ_ERRRTN( err );
00544 
00545     iBase_EntitySetHandle root_set;
00546     iMesh_getRootSet( meshInstance, &root_set, &ierr );
00547     if( iBase_SUCCESS != ierr )
00548     {
00549         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00550         return;
00551     }
00552 
00553     // Remove all elements not in inputSet
00554     if( root_set != inputSet )
00555     {
00556         std::vector< size_t >::iterator offset_iter = offsets.begin();
00557         size_t read_idx, write_idx;
00558         for( read_idx = write_idx = 0; read_idx < elements.size(); ++read_idx )
00559         {
00560             if( *offset_iter == read_idx )
00561             {
00562                 *offset_iter = write_idx;
00563                 ++offset_iter;
00564             }
00565 
00566             iBase_EntityHandle bh = static_cast< iBase_EntityHandle >( elements[read_idx] );
00567             iMesh_isEntContained( meshInstance, inputSet, bh, &cont, &ierr );
00568             if( iBase_SUCCESS != ierr )
00569             {
00570                 MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00571                 return;
00572             }
00573 
00574             if( cont ) elements[write_idx++] = elements[read_idx];
00575         }
00576         *offset_iter = write_idx;
00577         elements.resize( write_idx );
00578     }
00579 }
00580 
00581 //**************** Element Topology *****************
00582 
00583 /** Get connectivity
00584  *\param elements - Array of length num_elems containing elements
00585  *                  handles of elements for which connectivity is to
00586  *                  be queried.
00587  *\param vertices - Array of vertex handles in connectivity list.
00588  *\param offsets  - Indices into \ref vertex_handles, one per element
00589  */
00590 void MsqIMesh::elements_get_attached_vertices( const ElementHandle* elements, size_t num_elems,
00591                                                std::vector< VertexHandle >& vertices, std::vector< size_t >& offsets,
00592                                                MBMesquite::MsqError& err )
00593 {
00594     assert( sizeof( iBase_EntityHandle ) == sizeof( EntityHandle ) );
00595     const iBase_EntityHandle* elems = reinterpret_cast< const iBase_EntityHandle* >( elements );
00596     get_adjacent_entities( elems, num_elems, iBase_VERTEX, vertices, offsets, err );MSQ_CHKERR( err );
00597 }
00598 
00599 void MsqIMesh::get_all_elements( std::vector< ElementHandle >& elements, MsqError& err )
00600 {
00601     int ierr, count_in, count_out;
00602 
00603     if( inputSetType == iBase_ALL_TYPES )
00604     {
00605         int num_vol, num_face;
00606 
00607         iMesh_getNumOfType( meshInstance, inputSet, iBase_FACE, &num_face, &ierr );
00608         if( iBase_SUCCESS != ierr )
00609         {
00610             MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00611             return;
00612         }
00613         iMesh_getNumOfType( meshInstance, inputSet, iBase_REGION, &num_vol, &ierr );
00614         if( iBase_SUCCESS != ierr )
00615         {
00616             MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00617             return;
00618         }
00619         elements.resize( num_face + num_vol );
00620         if( elements.empty() ) return;
00621 
00622         iBase_EntityHandle* ptr = reinterpret_cast< iBase_EntityHandle* >( arrptr( elements ) );
00623         if( num_face )
00624         {
00625             count_in = num_face + num_vol;
00626             iMesh_getEntities( meshInstance, inputSet, iBase_FACE, iMesh_ALL_TOPOLOGIES, &ptr, &count_in, &count_out,
00627                                &ierr );
00628             if( iBase_SUCCESS != ierr )
00629             {
00630                 MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00631                 return;
00632             }
00633             assert( count_out == num_face );
00634         }
00635 
00636         if( num_vol )
00637         {
00638             ptr += num_face;
00639             count_in = num_vol;
00640             iMesh_getEntities( meshInstance, inputSet, iBase_REGION, iMesh_ALL_TOPOLOGIES, &ptr, &count_in, &count_out,
00641                                &ierr );
00642             if( iBase_SUCCESS != ierr )
00643             {
00644                 MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00645                 return;
00646             }
00647             assert( count_out == num_vol );
00648         }
00649     }
00650     else
00651     {
00652         int count;
00653         iMesh_getNumOfType( meshInstance, inputSet, inputSetType, &count, &ierr );
00654         if( iBase_SUCCESS != ierr )
00655         {
00656             MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00657             return;
00658         }
00659 
00660         if( !count ) return;
00661         elements.resize( count );
00662 
00663         iBase_EntityHandle* ptr = reinterpret_cast< iBase_EntityHandle* >( arrptr( elements ) );
00664         count_in                = count;
00665         iMesh_getEntities( meshInstance, inputSet, inputSetType, iMesh_ALL_TOPOLOGIES, &ptr, &count_in, &count_out,
00666                            &ierr );
00667         if( iBase_SUCCESS != ierr )
00668         {
00669             MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00670             return;
00671         }
00672         assert( count_out == count );
00673     }
00674 }
00675 
00676 void MsqIMesh::get_all_vertices( std::vector< VertexHandle >& vertices, MsqError& err )
00677 {
00678     std::vector< ElementHandle > elems;
00679     get_all_elements( elems, err );MSQ_CHKERR( err );
00680     if( elems.empty() ) return;
00681 
00682     std::vector< size_t > offsets;
00683     elements_get_attached_vertices( arrptr( elems ), elems.size(), vertices, offsets, err );MSQ_CHKERR( err );
00684 
00685     std::sort( vertices.begin(), vertices.end() );
00686     vertices.erase( std::unique( vertices.begin(), vertices.end() ), vertices.end() );
00687 }
00688 
00689 // Returns the topologies of the given entities.  The "entity_topologies"
00690 // array must be at least "num_elements" in size.
00691 void MsqIMesh::elements_get_topologies( const ElementHandle* element_handle_array, EntityTopology* element_topologies,
00692                                         size_t num_elements, MsqError& err )
00693 {
00694     if( !num_elements ) return;
00695 
00696     // don't copy unless we have to
00697     std::vector< int > topo_store;
00698     int* topo_array;
00699     if( sizeof( EntityTopology ) == sizeof( int ) )
00700         topo_array = (int*)element_topologies;
00701     else
00702     {
00703         topo_store.resize( num_elements );
00704         topo_array = arrptr( topo_store );
00705     }
00706 
00707     int ierr, junk1 = num_elements, junk2;
00708     assert( sizeof( ElementHandle ) == sizeof( iBase_EntityHandle ) );
00709     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( element_handle_array );
00710     iMesh_getEntArrTopo( meshInstance, arr, num_elements, &topo_array, &junk1, &junk2, &ierr );
00711     if( iBase_SUCCESS != ierr )
00712     {
00713         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00714         return;
00715     }
00716 
00717     for( size_t i = 0; i < num_elements; ++i )
00718         element_topologies[i] = topologyMap[topo_array[i]];
00719 }
00720 
00721 //**************** Memory Management ****************
00722 // Tells the mesh that the client is finished with a given
00723 // entity handle.
00724 void MsqIMesh::release_entity_handles( const MBMesquite::Mesh::EntityHandle* /*handle_array*/, size_t /*num_handles*/,
00725                                        MsqError& /*err*/ )
00726 {
00727     // Do nothing
00728 }
00729 
00730 // Instead of deleting a Mesh when you think you are done,
00731 // call release().  In simple cases, the implementation could
00732 // just call the destructor.  More sophisticated implementations
00733 // may want to keep the Mesh object to live longer than Mesquite
00734 // is using it.
00735 void MsqIMesh::release() {}
00736 
00737 //**************** Tags ****************
00738 TagHandle MsqIMesh::tag_create( const std::string& name, TagType type, unsigned length, const void*, MsqError& err )
00739 {
00740     int itaps_type;
00741     switch( type )
00742     {
00743         case MBMesquite::Mesh::BYTE:
00744             itaps_type = iBase_BYTES;
00745             break;
00746         case MBMesquite::Mesh::INT:
00747             itaps_type = iBase_INTEGER;
00748             break;
00749         case MBMesquite::Mesh::DOUBLE:
00750             itaps_type = iBase_DOUBLE;
00751             break;
00752         case MBMesquite::Mesh::HANDLE:
00753             itaps_type = iBase_ENTITY_HANDLE;
00754             break;
00755         default:
00756             MSQ_SETERR( err )( "Invalid tag type", MsqError::INVALID_ARG );
00757             return 0;
00758     }
00759 
00760     int ierr;
00761     iBase_TagHandle result;
00762     iMesh_createTag( meshInstance, name.c_str(), length, itaps_type, &result, &ierr, name.size() );
00763     if( iBase_SUCCESS != ierr )
00764     {
00765         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00766         return 0;
00767     }
00768 
00769     return static_cast< TagHandle >( result );
00770 }
00771 
00772 void MsqIMesh::tag_delete( TagHandle handle, MsqError& err )
00773 {
00774     int ierr;
00775     iMesh_destroyTag( meshInstance, static_cast< iBase_TagHandle >( handle ), true, &ierr );
00776     if( iBase_SUCCESS != ierr )
00777     {
00778         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00779         return;
00780     }
00781 }
00782 
00783 TagHandle MsqIMesh::tag_get( const std::string& name, MsqError& err )
00784 {
00785     iBase_TagHandle handle = 0;
00786     int ierr;
00787     iMesh_getTagHandle( meshInstance, name.c_str(), &handle, &ierr, name.length() );
00788     if( iBase_TAG_NOT_FOUND == ierr )
00789     {
00790         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::TAG_NOT_FOUND );
00791         return 0;
00792     }
00793     else if( iBase_SUCCESS != ierr )
00794     {
00795         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00796         return 0;
00797     }
00798     return static_cast< TagHandle >( handle );
00799 }
00800 
00801 void MsqIMesh::tag_properties( TagHandle handle, std::string& name_out, TagType& type_out, unsigned& length_out,
00802                                MsqError& err )
00803 {
00804     char buffer[256];
00805     int ierr1, ierr2, ierr3, itype;
00806 
00807     iBase_TagHandle th = static_cast< iBase_TagHandle >( handle );
00808     iMesh_getTagName( meshInstance, th, buffer, &ierr1, sizeof( buffer ) );
00809     iMesh_getTagSizeValues( meshInstance, th, (int*)&length_out, &ierr2 );
00810     iMesh_getTagType( meshInstance, th, &itype, &ierr3 );
00811 
00812     int ierr = iBase_SUCCESS;
00813     if( ierr1 != iBase_SUCCESS )
00814         ierr = ierr1;
00815     else if( ierr2 != iBase_SUCCESS )
00816         ierr = ierr2;
00817     else if( ierr3 != iBase_SUCCESS )
00818         ierr = ierr3;
00819     if( iBase_SUCCESS != ierr )
00820     {
00821         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00822         return;
00823     }
00824 
00825     buffer[255] = '\0';
00826     name_out    = buffer;
00827     switch( itype )
00828     {
00829         case iBase_BYTES:
00830             type_out = MBMesquite::Mesh::BYTE;
00831             break;
00832         case iBase_INTEGER:
00833             type_out = MBMesquite::Mesh::INT;
00834             break;
00835         case iBase_DOUBLE:
00836             type_out = MBMesquite::Mesh::DOUBLE;
00837             break;
00838         case iBase_ENTITY_HANDLE:
00839             type_out = MBMesquite::Mesh::HANDLE;
00840             break;
00841         default:
00842             MSQ_SETERR( err )( "Unsupported iMesh tag type", MsqError::NOT_IMPLEMENTED );
00843             return;
00844     }
00845 }
00846 
00847 void MsqIMesh::tag_set_element_data( TagHandle tag, size_t num_elems, const ElementHandle* array, const void* data,
00848                                      MsqError& err )
00849 {
00850     tag_set_data( tag, num_elems, array, data, err );
00851 }
00852 
00853 void MsqIMesh::tag_set_vertex_data( TagHandle tag, size_t num_elems, const VertexHandle* array, const void* data,
00854                                     MsqError& err )
00855 {
00856     tag_set_data( tag, num_elems, array, data, err );
00857 }
00858 
00859 void MsqIMesh::tag_set_data( TagHandle tag, size_t num_elems, const EntityHandle* array, const void* data,
00860                              MsqError& err )
00861 {
00862     int ierr, size;
00863     iMesh_getTagSizeBytes( meshInstance, static_cast< iBase_TagHandle >( tag ), &size, &ierr );
00864     if( iBase_SUCCESS != ierr )
00865     {
00866         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00867         return;
00868     }
00869     assert( sizeof( EntityHandle ) == sizeof( iBase_EntityHandle ) );
00870     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( array );
00871     iMesh_setArrData( meshInstance, arr, num_elems, static_cast< iBase_TagHandle >( tag ),
00872                       static_cast< const char* >( data ), size * num_elems, &ierr );
00873     if( iBase_SUCCESS != ierr )
00874     {
00875         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00876         return;
00877     }
00878 }
00879 
00880 void MsqIMesh::tag_get_element_data( TagHandle tag, size_t num_elems, const ElementHandle* array, void* data,
00881                                      MsqError& err )
00882 {
00883     tag_get_data( tag, num_elems, array, data, err );
00884 }
00885 
00886 void MsqIMesh::tag_get_vertex_data( TagHandle tag, size_t num_elems, const VertexHandle* array, void* data,
00887                                     MsqError& err )
00888 {
00889     tag_get_data( tag, num_elems, array, data, err );
00890 }
00891 
00892 void MsqIMesh::tag_get_data( TagHandle tag, size_t num_elems, const EntityHandle* array, void* data, MsqError& err )
00893 {
00894     int ierr, size;
00895     iMesh_getTagSizeBytes( meshInstance, static_cast< iBase_TagHandle >( tag ), &size, &ierr );
00896     if( iBase_SUCCESS != ierr )
00897     {
00898         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00899         return;
00900     }
00901 #if IMESH_VERSION_ATLEAST( 1, 1 )
00902     void* ptr = data;
00903 #else
00904     char* ptr = static_cast< char* >( data );
00905 #endif
00906     int junk1 = size * num_elems, junk2;
00907     assert( sizeof( EntityHandle ) == sizeof( iBase_EntityHandle ) );
00908     const iBase_EntityHandle* arr = reinterpret_cast< const iBase_EntityHandle* >( array );
00909     iMesh_getArrData( meshInstance, arr, num_elems, static_cast< iBase_TagHandle >( tag ), &ptr, &junk1, &junk2,
00910                       &ierr );
00911     if( iBase_SUCCESS != ierr )
00912     {
00913         MSQ_SETERR( err )( process_itaps_error( ierr ), MsqError::INTERNAL_ERROR );
00914         return;
00915     }
00916 }
00917 
00918 }  // namespace MBMesquite
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines