MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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) [email protected] 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