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