MOAB: Mesh Oriented datABase
(version 5.2.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) kraftche@cae.wisc.edu 00024 00025 ***************************************************************** */ 00026 00027 /** \file ArrayMesh.cpp 00028 * \brief 00029 * \author Jason Kraftcheck 00030 */ 00031 00032 #include "Mesquite.hpp" 00033 #include "ArrayMesh.hpp" 00034 #include "TopologyInfo.hpp" 00035 #include "MsqError.hpp" 00036 #include "MsqVertex.hpp" 00037 00038 #include <iostream> 00039 00040 namespace MBMesquite 00041 { 00042 00043 class IndexIterator : public EntityIterator 00044 { 00045 public: 00046 IndexIterator( size_t pStart, size_t pEnd ) : mStart( pStart ), mEnd( pEnd ), mCurrent( pStart ) {} 00047 virtual ~IndexIterator() {} 00048 virtual void restart() 00049 { 00050 mCurrent = mStart; 00051 } 00052 virtual Mesh::EntityHandle operator*() const 00053 { 00054 return (Mesh::EntityHandle)mCurrent; 00055 } 00056 virtual void operator++() 00057 { 00058 ++mCurrent; 00059 } 00060 virtual bool is_at_end() const 00061 { 00062 return mEnd - mCurrent <= 1; 00063 } 00064 00065 private: 00066 size_t mStart, mEnd, mCurrent; 00067 }; 00068 00069 ArrayMesh::ArrayMesh() 00070 : mDimension( 0 ), vertexCount( 0 ), coordArray( 0 ), fixedFlags( 0 ), slavedFlags( 0 ), vertexByteArray( 0 ), 00071 elementCount( 0 ), connArray( 0 ), connOffsets( 0 ), allocConnOffsets( 0 ), elementType( MIXED ), 00072 elementTypes( 0 ), nodesPerElement( 0 ), oneBasedArrays( false ), vertexAdjacencyList( 0 ), 00073 vertexAdjacencyOffsets( 0 ), tagList( 0 ) 00074 { 00075 } 00076 00077 ArrayMesh::ArrayMesh( int coords_per_vertex, unsigned long num_vertices, double* interleaved_vertex_coords, 00078 const int* vertex_fixed_flags, unsigned long num_elements, EntityTopology element_type, 00079 const unsigned long* element_connectivity_array, bool one_based_conn_indices, 00080 unsigned nodes_per_element, const int* vertex_slaved_flags ) 00081 : mDimension( coords_per_vertex ), vertexCount( num_vertices ), coordArray( interleaved_vertex_coords ), 00082 fixedFlags( vertex_fixed_flags ), slavedFlags( vertex_slaved_flags ), 00083 vertexByteArray( new unsigned char[num_vertices + one_based_conn_indices] ), elementCount( num_elements ), 00084 connArray( element_connectivity_array ), connOffsets( 0 ), allocConnOffsets( 0 ), elementType( element_type ), 00085 elementTypes( 0 ), nodesPerElement( nodes_per_element ), oneBasedArrays( one_based_conn_indices ), 00086 vertexAdjacencyList( 0 ), vertexAdjacencyOffsets( 0 ), tagList( 0 ) 00087 { 00088 if( oneBasedArrays ) 00089 { 00090 coordArray -= mDimension; 00091 --fixedFlags; 00092 } 00093 00094 if( nodesPerElement < 2 ) nodesPerElement = TopologyInfo::corners( element_type ); 00095 00096 assert( valid() ); 00097 memset( vertexByteArray, 0, num_vertices + one_based_conn_indices ); 00098 } 00099 00100 ArrayMesh::ArrayMesh( int coords_per_vertex, unsigned long num_vertices, double* interleaved_vertex_coords, 00101 const int* vertex_fixed_flags, unsigned long num_elements, const EntityTopology* element_types, 00102 const unsigned long* element_connectivity_array, 00103 const unsigned long* element_connectivity_offsets, bool one_based_conn_indices, 00104 const int* vertex_slaved_flags ) 00105 : mDimension( coords_per_vertex ), vertexCount( num_vertices ), coordArray( interleaved_vertex_coords ), 00106 fixedFlags( vertex_fixed_flags ), slavedFlags( vertex_slaved_flags ), 00107 vertexByteArray( new unsigned char[num_vertices + one_based_conn_indices] ), elementCount( num_elements ), 00108 connArray( element_connectivity_array ), connOffsets( element_connectivity_offsets ), allocConnOffsets( 0 ), 00109 elementType( MIXED ), elementTypes( element_types ), nodesPerElement( 0 ), 00110 oneBasedArrays( one_based_conn_indices ), vertexAdjacencyList( 0 ), vertexAdjacencyOffsets( 0 ), tagList( 0 ) 00111 { 00112 if( oneBasedArrays ) 00113 { 00114 coordArray -= mDimension; 00115 --fixedFlags; 00116 if( element_connectivity_offsets ) --connArray; 00117 } 00118 00119 if( !element_connectivity_offsets ) 00120 { 00121 connOffsets = allocConnOffsets = new unsigned long[num_elements + 1]; 00122 allocConnOffsets[0] = 0; 00123 for( unsigned long i = 1; i <= num_elements; ++i ) 00124 allocConnOffsets[i] = allocConnOffsets[i - 1] + TopologyInfo::corners( elementTypes[i - 1] ); 00125 } 00126 00127 assert( valid() ); 00128 memset( vertexByteArray, 0, num_vertices + one_based_conn_indices ); 00129 } 00130 00131 bool ArrayMesh::valid() const 00132 { 00133 unsigned long off = oneBasedArrays ? 1 : 0; 00134 for( unsigned long i = off; i < vertexCount + off; ++i ) 00135 { 00136 if( fixedFlags[i] != 0 && fixedFlags[i] != 1 ) 00137 { 00138 std::cerr << "Invalid vertex fixed flag at index " << i << std::endl; 00139 return false; 00140 } 00141 } 00142 00143 for( unsigned long i = 0; i < elementCount * nodesPerElement; ++i ) 00144 { 00145 unsigned long j = connArray[i] - oneBasedArrays; 00146 if( j >= vertexCount ) 00147 { 00148 std::cerr << "Invalid connectivity index at index " << j << "(element " << j / elementCount << " node " 00149 << j % elementCount << ')' << std::endl; 00150 return false; 00151 } 00152 } 00153 00154 return true; 00155 } 00156 00157 void ArrayMesh::clear_mesh() 00158 { 00159 delete[] vertexByteArray; 00160 delete[] vertexAdjacencyList; 00161 delete[] vertexAdjacencyOffsets; 00162 delete[] allocConnOffsets; 00163 while( tagList ) 00164 { 00165 Tag* dead = tagList; 00166 tagList = tagList->next; 00167 delete[] dead->name; 00168 delete[] dead->defaultValue; 00169 if( dead->owned ) 00170 { 00171 delete[] dead->vtxWritePtr; 00172 delete[] dead->eleWritePtr; 00173 } 00174 delete dead; 00175 } 00176 mDimension = 0; 00177 vertexCount = 0; 00178 coordArray = 0; 00179 connOffsets = 0; 00180 allocConnOffsets = 0; 00181 fixedFlags = 0; 00182 vertexByteArray = 0; 00183 elementCount = 0; 00184 elementType = MIXED; 00185 elementTypes = 0; 00186 nodesPerElement = 0; 00187 oneBasedArrays = false; 00188 vertexAdjacencyList = 0; 00189 vertexAdjacencyOffsets = 0; 00190 } 00191 00192 void ArrayMesh::set_mesh( int coords_per_vertex, unsigned long num_vertices, double* interleaved_vertex_coords, 00193 const int* vertex_fixed_flags, unsigned long num_elements, EntityTopology element_type, 00194 const unsigned long* element_connectivity_array, bool one_based_conn_indices, 00195 unsigned nodes_per_element, const int* vertex_slaved_flags ) 00196 { 00197 clear_mesh(); 00198 mDimension = coords_per_vertex; 00199 vertexCount = num_vertices; 00200 coordArray = interleaved_vertex_coords; 00201 fixedFlags = vertex_fixed_flags; 00202 slavedFlags = vertex_slaved_flags; 00203 elementCount = num_elements; 00204 connArray = element_connectivity_array; 00205 elementType = element_type; 00206 oneBasedArrays = one_based_conn_indices; 00207 00208 if( oneBasedArrays ) 00209 { 00210 coordArray -= mDimension; 00211 --fixedFlags; 00212 } 00213 00214 if( nodes_per_element < 2 ) 00215 nodesPerElement = TopologyInfo::corners( element_type ); 00216 else 00217 nodesPerElement = nodes_per_element; 00218 00219 vertexByteArray = new unsigned char[num_vertices + one_based_conn_indices]; 00220 assert( valid() ); 00221 memset( vertexByteArray, 0, num_vertices + one_based_conn_indices ); 00222 } 00223 00224 ArrayMesh::~ArrayMesh() 00225 { 00226 clear_mesh(); 00227 } 00228 00229 inline const unsigned long* ArrayMesh::elem_verts( size_t e, int& n ) const 00230 { 00231 assert( e < elementCount ); 00232 if( connOffsets ) 00233 { 00234 n = connOffsets[e + 1] - connOffsets[e]; 00235 return connArray + connOffsets[e]; 00236 } 00237 else 00238 { 00239 n = nodesPerElement; 00240 return connArray + nodesPerElement * e; 00241 } 00242 } 00243 00244 int ArrayMesh::get_geometric_dimension( MsqError& ) 00245 { 00246 return mDimension; 00247 } 00248 00249 void ArrayMesh::get_all_elements( std::vector< ElementHandle >& elements, MsqError& ) 00250 { 00251 elements.resize( elementCount ); 00252 for( unsigned long i = 0; i < elementCount; ++i ) 00253 elements[i] = (Mesh::ElementHandle)i; 00254 } 00255 00256 void ArrayMesh::get_all_vertices( std::vector< VertexHandle >& vertices, MsqError& ) 00257 { 00258 vertices.resize( vertexCount ); 00259 for( unsigned long i = 0; i < vertexCount; ++i ) 00260 vertices[i] = ( Mesh::VertexHandle )( i + oneBasedArrays ); 00261 } 00262 00263 VertexIterator* ArrayMesh::vertex_iterator( MsqError& ) 00264 { 00265 return new IndexIterator( oneBasedArrays, vertexCount + oneBasedArrays ); 00266 } 00267 00268 ElementIterator* ArrayMesh::element_iterator( MsqError& ) 00269 { 00270 return new IndexIterator( 0, elementCount ); 00271 } 00272 00273 void ArrayMesh::vertices_get_fixed_flag( const VertexHandle vert_array[], std::vector< bool >& fixed_flag_array, 00274 size_t num_vtx, MsqError& ) 00275 { 00276 fixed_flag_array.resize( num_vtx ); 00277 const size_t* indices = (const size_t*)vert_array; 00278 for( size_t i = 0; i < num_vtx; ++i ) 00279 { 00280 assert( indices[i] < vertexCount ); 00281 fixed_flag_array[i] = !!fixedFlags[indices[i]]; 00282 } 00283 } 00284 00285 void ArrayMesh::vertices_get_slaved_flag( const VertexHandle* vert_array, std::vector< bool >& slaved_flags, 00286 size_t num_vtx, MsqError& err ) 00287 { 00288 if( !slavedFlags ) 00289 { 00290 MSQ_SETERR( err ) 00291 ( "No data provided to ArrayMesh for Settings::SLAVE_FLAG", MsqError::INVALID_STATE ); 00292 return; 00293 } 00294 00295 slaved_flags.resize( num_vtx ); 00296 const size_t* indices = (const size_t*)vert_array; 00297 for( size_t i = 0; i < num_vtx; ++i ) 00298 { 00299 assert( indices[i] < vertexCount ); 00300 slaved_flags[i] = !!slavedFlags[indices[i]]; 00301 } 00302 } 00303 00304 void ArrayMesh::vertices_get_coordinates( const VertexHandle vert_array[], MsqVertex* coordinates, size_t num_vtx, 00305 MsqError& err ) 00306 { 00307 const size_t* indices = (const size_t*)vert_array; 00308 if( mDimension == 3 ) 00309 for( size_t i = 0; i < num_vtx; ++i ) 00310 { 00311 assert( indices[i] < vertexCount + oneBasedArrays ); 00312 coordinates[i].set( coordArray + 3 * indices[i] ); 00313 } 00314 else if( mDimension == 2 ) 00315 for( size_t i = 0; i < num_vtx; ++i ) 00316 { 00317 assert( indices[i] < vertexCount + oneBasedArrays ); 00318 coordinates[i].set( coordArray[2 * indices[i]], coordArray[2 * indices[i] + 1], 0.0 ); 00319 } 00320 else 00321 MSQ_SETERR( err )( MsqError::INVALID_STATE ); 00322 } 00323 00324 void ArrayMesh::vertex_set_coordinates( VertexHandle vert, const Vector3D& coordinates, MsqError& err ) 00325 { 00326 size_t i = (size_t)vert; 00327 assert( i < vertexCount + oneBasedArrays ); 00328 if( mDimension == 3 ) 00329 coordinates.get_coordinates( coordArray + 3 * i ); 00330 else if( mDimension == 2 ) 00331 { 00332 coordArray[2 * i] = coordinates[0]; 00333 coordArray[2 * i + 1] = coordinates[1]; 00334 } 00335 else 00336 MSQ_SETERR( err )( MsqError::INVALID_STATE ); 00337 } 00338 00339 void ArrayMesh::vertex_set_byte( VertexHandle vertex, unsigned char byte, MsqError& ) 00340 { 00341 assert( (size_t)vertex < vertexCount + oneBasedArrays ); 00342 vertexByteArray[(size_t)vertex] = byte; 00343 } 00344 00345 void ArrayMesh::vertices_set_byte( const VertexHandle* vert_array, const unsigned char* byte_array, size_t array_size, 00346 MsqError& ) 00347 { 00348 const size_t* indices = (const size_t*)vert_array; 00349 for( size_t i = 0; i < array_size; ++i ) 00350 { 00351 assert( indices[i] < vertexCount + oneBasedArrays ); 00352 vertexByteArray[indices[i]] = byte_array[i]; 00353 } 00354 } 00355 00356 void ArrayMesh::vertex_get_byte( VertexHandle vertex, unsigned char* byte, MsqError& ) 00357 { 00358 assert( (size_t)vertex < vertexCount + oneBasedArrays ); 00359 *byte = vertexByteArray[(size_t)vertex]; 00360 } 00361 00362 void ArrayMesh::vertices_get_byte( const VertexHandle* vert_array, unsigned char* byte_array, size_t array_size, 00363 MsqError& ) 00364 { 00365 const size_t* indices = (const size_t*)vert_array; 00366 for( size_t i = 0; i < array_size; ++i ) 00367 { 00368 assert( indices[i] < vertexCount + oneBasedArrays ); 00369 byte_array[i] = vertexByteArray[indices[i]]; 00370 } 00371 } 00372 00373 void ArrayMesh::vertices_get_attached_elements( const VertexHandle* vertex_array, size_t num_vertex, 00374 std::vector< ElementHandle >& elements, std::vector< size_t >& offsets, 00375 MsqError& ) 00376 { 00377 const size_t* indices = (const size_t*)vertex_array; 00378 if( !vertexAdjacencyList ) build_vertex_adjacency_list(); 00379 00380 elements.clear(); 00381 offsets.resize( num_vertex + 1 ); 00382 for( size_t i = 0; i < num_vertex; ++i ) 00383 { 00384 offsets[i] = elements.size(); 00385 assert( indices[i] < vertexCount + oneBasedArrays ); 00386 for( size_t j = vertexAdjacencyOffsets[indices[i]]; j < vertexAdjacencyOffsets[indices[i] + 1]; ++j ) 00387 elements.push_back( (ElementHandle)vertexAdjacencyList[j] ); 00388 } 00389 offsets[num_vertex] = elements.size(); 00390 } 00391 00392 void ArrayMesh::elements_get_attached_vertices( const ElementHandle* elem_handles, size_t num_elems, 00393 std::vector< VertexHandle >& vert_handles, 00394 std::vector< size_t >& offsets, MsqError& ) 00395 { 00396 const size_t* indices = (const size_t*)elem_handles; 00397 offsets.resize( num_elems + 1 ); 00398 vert_handles.clear(); 00399 for( size_t i = 0; i < num_elems; ++i ) 00400 { 00401 assert( indices[i] < elementCount ); 00402 int count; 00403 const unsigned long* conn = elem_verts( indices[i], count ); 00404 size_t prev_size = vert_handles.size(); 00405 offsets[i] = prev_size; 00406 vert_handles.resize( prev_size + count ); 00407 std::copy( conn, conn + count, (size_t*)( &vert_handles[prev_size] ) ); 00408 } 00409 offsets[num_elems] = vert_handles.size(); 00410 } 00411 00412 void ArrayMesh::elements_get_topologies( const ElementHandle* handles, EntityTopology* element_topologies, 00413 size_t num_elements, MsqError& ) 00414 { 00415 const size_t* indices = (const size_t*)handles; 00416 if( elementType == MIXED ) 00417 for( size_t i = 0; i < num_elements; ++i ) 00418 { 00419 assert( indices[i] < elementCount ); 00420 element_topologies[i] = elementTypes[indices[i]]; 00421 } 00422 else 00423 for( size_t i = 0; i < num_elements; ++i ) 00424 { 00425 assert( indices[i] < elementCount ); 00426 element_topologies[i] = elementType; 00427 } 00428 } 00429 00430 void ArrayMesh::release_entity_handles( const EntityHandle*, size_t, MsqError& err ) 00431 { 00432 MSQ_SETERR( err )( MsqError::NOT_IMPLEMENTED ); 00433 } 00434 00435 void ArrayMesh::release() {} 00436 00437 void ArrayMesh::build_vertex_adjacency_list() 00438 { 00439 delete[] vertexAdjacencyList; 00440 delete[] vertexAdjacencyOffsets; 00441 vertexAdjacencyOffsets = new unsigned long[vertexCount + oneBasedArrays + 1]; 00442 00443 // for each vertex, store the number of elements the previous 00444 // vertex occurs in. 00445 memset( vertexAdjacencyOffsets, 0, sizeof( unsigned long ) * ( vertexCount + oneBasedArrays + 1 ) ); 00446 for( size_t i = 0; i < elementCount; ++i ) 00447 { 00448 int n; 00449 const unsigned long* conn = elem_verts( i, n ); 00450 for( int j = 0; j < n; ++j ) 00451 ++vertexAdjacencyOffsets[conn[j] + 1]; 00452 } 00453 00454 // convert vertexAdjacencyOffsets from a shifted list of counts 00455 // to a list of offsts 00456 for( size_t i = 1; i <= vertexCount + oneBasedArrays; ++i ) 00457 vertexAdjacencyOffsets[i] += vertexAdjacencyOffsets[i - 1]; 00458 00459 // allocate space and populate with reverse connectivity 00460 vertexAdjacencyList = new unsigned long[vertexAdjacencyOffsets[vertexCount + oneBasedArrays]]; 00461 for( size_t i = 0; i < elementCount; ++i ) 00462 { 00463 int n; 00464 const unsigned long* conn = elem_verts( i, n ); 00465 for( int j = 0; j < n; ++j ) 00466 vertexAdjacencyList[vertexAdjacencyOffsets[conn[j]]++] = i; 00467 } 00468 00469 for( size_t i = vertexCount + oneBasedArrays; i > 0; --i ) 00470 vertexAdjacencyOffsets[i] = vertexAdjacencyOffsets[i - 1]; 00471 vertexAdjacencyOffsets[0] = 0; 00472 } 00473 00474 unsigned ArrayMesh::bytes( TagType type ) 00475 { 00476 switch( type ) 00477 { 00478 case BYTE: 00479 case BOOL: 00480 return 1; 00481 case INT: 00482 return sizeof( int ); 00483 case DOUBLE: 00484 return sizeof( double ); 00485 case HANDLE: 00486 return sizeof( EntityHandle ); 00487 } 00488 return 0; 00489 } 00490 00491 void ArrayMesh::fill( unsigned char* buffer, const unsigned char* value, size_t size, size_t count ) 00492 { 00493 if( !value ) 00494 { 00495 memset( buffer, 0, size * count ); 00496 return; 00497 } 00498 00499 unsigned char* const end = buffer + size * count; 00500 for( unsigned char* iter = buffer; iter != end; iter += size ) 00501 memcpy( iter, value, size ); 00502 } 00503 00504 ArrayMesh::Tag* ArrayMesh::allocate_tag( const char* name, bool owned, TagType type, unsigned size, 00505 const void* vertex_ro_data, void* vertex_rw_data, const void* element_ro_data, 00506 void* element_rw_data, const void* default_value, MsqError& err ) 00507 { 00508 // check if name is already in use 00509 for( Tag* iter = tagList; iter; iter = iter->next ) 00510 { 00511 if( !strcmp( iter->name, name ) ) 00512 { 00513 MSQ_SETERR( err )( MsqError::TAG_ALREADY_EXISTS ); 00514 return 0; 00515 } 00516 } 00517 00518 // allocate object 00519 Tag* result = new Tag; 00520 00521 // initialize members 00522 result->type = type; 00523 result->size = size * bytes( type ); 00524 result->owned = owned; 00525 result->name = new char[strlen( name ) + 1]; 00526 strcpy( result->name, name ); 00527 00528 result->vtxWritePtr = reinterpret_cast< unsigned char* >( vertex_rw_data ); 00529 if( vertex_rw_data ) 00530 result->vtxReadPtr = reinterpret_cast< unsigned char* >( vertex_rw_data ); 00531 else 00532 result->vtxReadPtr = reinterpret_cast< const unsigned char* >( vertex_ro_data ); 00533 00534 result->eleWritePtr = reinterpret_cast< unsigned char* >( element_rw_data ); 00535 if( element_rw_data ) 00536 result->eleReadPtr = reinterpret_cast< unsigned char* >( element_rw_data ); 00537 else 00538 result->eleReadPtr = reinterpret_cast< const unsigned char* >( element_ro_data ); 00539 00540 if( default_value ) 00541 { 00542 result->defaultValue = new unsigned char[result->size]; 00543 memcpy( result->defaultValue, default_value, result->size ); 00544 } 00545 else 00546 { 00547 result->defaultValue = 0; 00548 } 00549 00550 // prepend to tag list 00551 result->next = tagList; 00552 tagList = result; 00553 00554 return result; 00555 } 00556 00557 TagHandle ArrayMesh::add_read_only_tag_data( const char* tag_name, TagType data_type, int vals_per_entity, 00558 const void* vertex_data, const void* element_data, 00559 const void* default_value, MsqError& err ) 00560 { 00561 Tag* tag = allocate_tag( tag_name, false, data_type, vals_per_entity, vertex_data, 0, element_data, 0, 00562 default_value, err ); 00563 MSQ_ERRZERO( err ); 00564 return reinterpret_cast< TagHandle >( tag ); 00565 } 00566 00567 TagHandle ArrayMesh::add_writable_tag_data( const char* tag_name, TagType data_type, int vals_per_entity, 00568 void* vertex_data, void* element_data, const void* default_value, 00569 MsqError& err ) 00570 { 00571 Tag* tag = allocate_tag( tag_name, false, data_type, vals_per_entity, 0, vertex_data, 0, element_data, 00572 default_value, err ); 00573 MSQ_ERRZERO( err ); 00574 return reinterpret_cast< TagHandle >( tag ); 00575 } 00576 00577 TagHandle ArrayMesh::tag_create( const std::string& tag_name, TagType data_type, unsigned size, 00578 const void* default_value, MsqError& err ) 00579 { 00580 Tag* tag = allocate_tag( tag_name.c_str(), true, data_type, size, 0, 0, 0, 0, default_value, err ); 00581 MSQ_ERRZERO( err ); 00582 return reinterpret_cast< TagHandle >( tag ); 00583 } 00584 00585 void ArrayMesh::tag_delete( TagHandle handle, MsqError& err ) 00586 { 00587 Tag* ptr = reinterpret_cast< Tag* >( handle ); 00588 // find previous tag pointer in list 00589 if( !tagList ) 00590 { 00591 MSQ_SETERR( err )( "Invalid tag handle", MsqError::TAG_NOT_FOUND ); 00592 return; 00593 } 00594 Tag* prev = 0; 00595 for( prev = tagList; prev && prev->next != ptr; prev = prev->next ) 00596 ; 00597 if( !prev && tagList != ptr ) 00598 { 00599 MSQ_SETERR( err )( "Invalid tag handle", MsqError::TAG_NOT_FOUND ); 00600 return; 00601 } 00602 delete[] ptr->name; 00603 delete[] ptr->defaultValue; 00604 if( ptr->owned ) 00605 { 00606 delete[] ptr->vtxWritePtr; 00607 delete[] ptr->eleWritePtr; 00608 } 00609 if( prev ) 00610 prev->next = ptr->next; 00611 else 00612 tagList = ptr->next; 00613 delete ptr; 00614 } 00615 00616 TagHandle ArrayMesh::tag_get( const std::string& name, MsqError& err ) 00617 { 00618 for( Tag* iter = tagList; iter; iter = iter->next ) 00619 if( name == iter->name ) return reinterpret_cast< TagHandle >( iter ); 00620 MSQ_SETERR( err )( MsqError::TAG_NOT_FOUND ); 00621 return 0; 00622 } 00623 00624 void ArrayMesh::tag_properties( TagHandle handle, std::string& name, TagType& type, unsigned& size, MsqError& ) 00625 { 00626 const Tag* ptr = reinterpret_cast< const Tag* >( handle ); 00627 name = ptr->name; 00628 type = ptr->type; 00629 size = ptr->size / bytes( ptr->type ); 00630 } 00631 00632 void ArrayMesh::tag_set_element_data( TagHandle handle, size_t count, const ElementHandle* entities, const void* data, 00633 MsqError& err ) 00634 { 00635 Tag* tag = reinterpret_cast< Tag* >( handle ); 00636 if( !tag->eleWritePtr ) 00637 { 00638 if( !tag->owned ) 00639 { 00640 MSQ_SETERR( err ) 00641 ( "Attempt to set non-writeable (application owned) tag data", MsqError::TAG_ALREADY_EXISTS ); 00642 return; 00643 } 00644 else 00645 { 00646 assert( !tag->eleReadPtr ); 00647 tag->eleReadPtr = tag->eleWritePtr = new unsigned char[elementCount * tag->size]; 00648 fill( tag->eleWritePtr, tag->defaultValue, tag->size, elementCount ); 00649 } 00650 } 00651 const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 00652 // as we're working with user-supplied arrays, make sure we're not 00653 // memcpying overlapping regions 00654 assert( ptr + tag->size * elementCount <= tag->eleWritePtr || tag->eleWritePtr + tag->size * elementCount <= ptr ); 00655 for( size_t i = 0; i < count; ++i ) 00656 { 00657 size_t idx = reinterpret_cast< size_t >( entities[i] ); 00658 memcpy( tag->eleWritePtr + idx * tag->size, ptr + i * tag->size, tag->size ); 00659 } 00660 } 00661 00662 void ArrayMesh::tag_set_vertex_data( TagHandle handle, size_t count, const VertexHandle* entities, const void* data, 00663 MsqError& err ) 00664 { 00665 Tag* tag = reinterpret_cast< Tag* >( handle ); 00666 if( !tag->vtxWritePtr ) 00667 { 00668 if( !tag->owned ) 00669 { 00670 MSQ_SETERR( err ) 00671 ( "Attempt to set non-writeable (application owned) tag data", MsqError::TAG_ALREADY_EXISTS ); 00672 return; 00673 } 00674 else 00675 { 00676 assert( !tag->vtxReadPtr ); 00677 tag->vtxReadPtr = tag->vtxWritePtr = new unsigned char[vertexCount * tag->size]; 00678 fill( tag->vtxWritePtr, tag->defaultValue, tag->size, vertexCount ); 00679 } 00680 } 00681 const unsigned char* ptr = reinterpret_cast< const unsigned char* >( data ); 00682 // as we're working with user-supplied arrays, make sure we're not 00683 // memcpying overlapping regions 00684 assert( ptr + tag->size * vertexCount <= tag->vtxWritePtr || tag->vtxWritePtr + tag->size * vertexCount <= ptr ); 00685 for( size_t i = 0; i < count; ++i ) 00686 { 00687 size_t idx = reinterpret_cast< size_t >( entities[i] ) - oneBasedArrays; 00688 memcpy( tag->vtxWritePtr + idx * tag->size, ptr + i * tag->size, tag->size ); 00689 } 00690 } 00691 00692 void ArrayMesh::tag_get_element_data( TagHandle handle, size_t count, const ElementHandle* entities, void* data, 00693 MsqError& err ) 00694 { 00695 unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 00696 const Tag* tag = reinterpret_cast< const Tag* >( handle ); 00697 if( tag->eleReadPtr ) 00698 { 00699 for( size_t i = 0; i < count; ++i ) 00700 { 00701 size_t idx = reinterpret_cast< size_t >( entities[i] ); 00702 memcpy( ptr + i * tag->size, tag->eleReadPtr + idx * tag->size, tag->size ); 00703 } 00704 } 00705 else if( tag->defaultValue ) 00706 { 00707 fill( ptr, tag->defaultValue, tag->size, count ); 00708 } 00709 else 00710 { 00711 MSQ_SETERR( err )( MsqError::TAG_NOT_FOUND ); 00712 } 00713 } 00714 00715 void ArrayMesh::tag_get_vertex_data( TagHandle handle, size_t count, const VertexHandle* entities, void* data, 00716 MsqError& err ) 00717 { 00718 unsigned char* ptr = reinterpret_cast< unsigned char* >( data ); 00719 const Tag* tag = reinterpret_cast< const Tag* >( handle ); 00720 if( tag->vtxReadPtr ) 00721 { 00722 for( size_t i = 0; i < count; ++i ) 00723 { 00724 size_t idx = reinterpret_cast< size_t >( entities[i] ) - oneBasedArrays; 00725 memcpy( ptr + i * tag->size, tag->vtxReadPtr + idx * tag->size, tag->size ); 00726 } 00727 } 00728 else if( tag->defaultValue ) 00729 { 00730 fill( ptr, tag->defaultValue, tag->size, count ); 00731 } 00732 else 00733 { 00734 MSQ_SETERR( err )( MsqError::TAG_NOT_FOUND ); 00735 } 00736 } 00737 00738 } // namespace MBMesquite