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