MOAB: Mesh Oriented datABase  (version 5.2.1)
ArrayMesh.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 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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines