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