diff --git a/README.md b/README.md index a59c7a5..bf0ca7f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -

Adaptive Multigrid Solvers (Version 10.03)

+

Adaptive Multigrid Solvers (Version 10.04)

-links -executables -usage -changes +links +executables +usage +changes

@@ -27,10 +27,11 @@ This code-base was born from the Poisson Surface Reconstruction code. It has evo [Kazhdan and Hoppe, 2013]
Executables: -Win64
+Win64
Source Code: -ZIP GitHub
+ZIP GitHub
Older Versions: +V10.03, V10.02, V10.01, V10.00, @@ -782,6 +783,11 @@ Similarly, to reduce compilation times, support for specific degrees can be remo
  • Cleaned up memory leaks and fixed a bug causing ImageStitching and EDTInHeat to SEGFAULT on Linux. +Version 10.04: +
      +
    1. Replaced the ply I/O code with an object-oriented implementation. +
    + diff --git a/Src/AdaptiveTreeVisualization.cpp b/Src/AdaptiveTreeVisualization.cpp index 895af5f..d042a85 100644 --- a/Src/AdaptiveTreeVisualization.cpp +++ b/Src/AdaptiveTreeVisualization.cpp @@ -147,7 +147,8 @@ void _Execute( const FEMTree< Dim , Real >* tree , FILE* fp ) if( Verbose.set ) printf( "Got iso-surface: %.2f(s)\n" , Time()-t ); if( Verbose.set ) printf( "Vertices / Polygons: %d / %d\n" , (int)( mesh.outOfCorePointCount()+mesh.inCorePoints.size() ) , (int)mesh.polygonCount() ); - PlyWritePolygons< Vertex , Real , Dim >( OutMesh.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NULL , 0 , XForm< Real , Dim+1 >::Identity() ); + std::vector< std::string > comments; + PlyWritePolygons< Vertex , Real , Dim >( OutMesh.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , comments , XForm< Real , Dim+1 >::Identity() ); } } @@ -229,7 +230,7 @@ int main( int argc , char* argv[] ) int dimension; ReadFEMTreeParameter( fp , realType , dimension ); { - unsigned int dim; + unsigned int dim = dimension; unsigned int* sigs = ReadDenseNodeDataSignatures( fp , dim ); if( dimension!=dim ) fprintf( stderr , "[ERROR] Octree and node data dimensions don't math: %d != %d\n" , dimension , dim ) , exit( 0 ); for( unsigned int d=1 ; d::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); else messageWriter( "%9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); } - void dumpOutput2( std::vector< char* >& comments , const char* header ) const + void dumpOutput2( std::vector< std::string >& comments , const char* header ) const { FEMTree< Dim , Real >::MemoryUsage(); if( header ) messageWriter( comments , "%s %9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , header , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); @@ -208,7 +208,7 @@ int _Execute( int argc , char* argv[] ) { static const unsigned int Degree = FEMSignature< FEMSig >::Degree; typedef typename FEMTree< Dim , Real >::template InterpolationInfo< Real , 0 > InterpolationInfo; - std::vector< char* > comments; + std::vector< std::string > comments; messageWriter( comments , "*****************************************\n" ); messageWriter( comments , "*****************************************\n" ); messageWriter( comments , "** Running EDT in Heat (Version %s) **\n" , VERSION ); @@ -271,7 +271,8 @@ int _Execute( int argc , char* argv[] ) int file_type; std::vector< PlyVertex< float , Dim > > _vertices; std::vector< std::vector< int > > _polygons; - PlyReadPolygons( In.value , _vertices , _polygons , PlyVertex< float , Dim >::PlyReadProperties() , PlyVertex< float , Dim >::PlyReadNum , file_type ); + std::vector< std::string > comments; + PlyReadPolygons( In.value , _vertices , _polygons , PlyVertex< float , Dim >::PlyReadProperties() , PlyVertex< float , Dim >::PlyReadNum , file_type , comments ); vertices.resize( _vertices.size() ); for( int i=0 ; i - static unsigned int MCIndex( const Real values[ ElementNum< 0 >() ] , Real iso ); + static unsigned int MCIndex( const Real values[ Cube::ElementNum< 0 >() ] , Real iso ); // Extracts the marching-cubes sub-index for the associated element template< unsigned int K > @@ -586,7 +586,7 @@ namespace HyperCube } template< unsigned int D > template< typename Real > - unsigned int Cube< D >::MCIndex( const Real values[ ElementNum< 0 >() ] , Real iso ) + unsigned int Cube< D >::MCIndex( const Real values[ Cube< D >::ElementNum< 0 >() ] , Real iso ) { unsigned int mcIdx = 0; for( unsigned int c=0 ; c() ; c++ ) if( values[c] #include +#include struct MessageWriter { char* outputFile; @@ -151,6 +152,33 @@ struct MessageWriter va_end( args ); if( str[strlen(str)-1]=='\n' ) str[strlen(str)-1] = 0; } + void operator() ( std::vector< std::string >& messages , const char* format , ... ) + { + if( outputFile ) + { + FILE* fp = fopen( outputFile , "a" ); + va_list args; + va_start( args , format ); + vfprintf( fp , format , args ); + fclose( fp ); + va_end( args ); + } + if( echoSTDOUT ) + { + va_list args; + va_start( args , format ); + vprintf( format , args ); + va_end( args ); + } + // [WARNING] We are not checking the string is small enough to fit in 1024 characters + char message[1024]; + va_list args; + va_start( args , format ); + vsprintf( message , format , args ); + va_end( args ); + if( message[strlen(message)-1]=='\n' ) message[strlen(message)-1] = 0; + messages.push_back( std::string( message ) ); + } }; ////////////////// diff --git a/Src/Ply.h b/Src/Ply.h index 58a82b5..3030431 100644 --- a/Src/Ply.h +++ b/Src/Ply.h @@ -55,7 +55,7 @@ typedef struct PlyFace } PlyFace; static PlyProperty face_props[] = { - { _strdup( "vertex_indices" ) , PLY_INT , PLY_INT , offsetof( PlyFace , vertices ) , 1 , PLY_UCHAR, PLY_UCHAR , offsetof(PlyFace,nr_vertices) }, + PlyProperty( "vertex_indices" , PLY_INT , PLY_INT , offsetof( PlyFace , vertices ) , 1 , PLY_UCHAR, PLY_UCHAR , offsetof( PlyFace , nr_vertices ) ) , }; @@ -117,55 +117,55 @@ protected: template<> const PlyProperty PlyVertex< float , 2 , float >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< double , 2 , float >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< float , 2 , double >::_PlyProperties[] = { - { "x" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< double , 2 , double >::_PlyProperties[] = { - { "x" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< float , 3 , float >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< double , 3 , float >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< float , 3 , double >::_PlyProperties[] = { - { "x" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "z" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_DOUBLE , PLY_FLOAT , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PlyVertex< double , 3 , double >::_PlyProperties[] = { - { "x" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "y" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "z" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_DOUBLE , PLY_DOUBLE , int( offsetof( PlyVertex , point.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; /////////////////////// @@ -256,90 +256,22 @@ void PlyVertexWithData< Real , Dim , Data , RealOnDisk >::_SetWriteProperties( v } template< class Vertex , class Real , int Dim > -int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point< float , Dim >& translate , float scale , char** comments=NULL , int commentNum=0 , XForm< Real , Dim+1 > xForm=XForm< Real , Dim+1 >::Identity() ); +int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point< float , Dim >& translate , float scale , const std::vector< std::string >& comments , XForm< Real , Dim+1 > xForm=XForm< Real , Dim+1 >::Identity() ); template< class Vertex , class Real , int Dim > -int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , char** comments=NULL , int commentNum=0 , XForm< Real , Dim+1 > xForm=XForm< Real , Dim+1 >::Identity() ); +int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const std::vector< std::string >& comments , XForm< Real , Dim+1 > xForm=XForm< Real , Dim+1 >::Identity() ); inline bool PlyReadHeader( char* fileName , const PlyProperty* properties , int propertyNum , bool* readFlags , int& file_type ) { - int nr_elems; - char **elist; + std::vector< std::string > elist; float version; - PlyFile* ply; - char* elem_name; - int num_elems; - int nr_props; - PlyProperty** plist; - ply = ply_open_for_reading( fileName , &nr_elems , &elist , &file_type , &version ); + PlyFile *ply = PlyFile::Read( fileName , elist , file_type , version ); if( !ply ) return false; - for( int i=0 ; ielems[i]->name ); - free( ply->elems[i]->store_prop ); - for( int j=0 ; jelems[i]->nprops ; j++ ) - { - free( ply->elems[i]->props[j]->name ); - free( ply->elems[i]->props[j] ); - } - free( ply->elems[i]->props ); - } - for( int i=0 ; ielems[i] ); - free( ply->elems ); - for( int i=0 ; inum_comments ; i++ ) free( ply->comments[i] ); - free( ply->comments ); - for( int i=0 ; inum_obj_info ; i++ ) free( ply->obj_info[i] ); - free( ply->obj_info ); - ply_free_other_elements( ply->other_elems ); - - for( int i=0 ; iget_property( elist[i].c_str() , &properties[j] )!=0; - for( int j=0 ; jname ); - free( plist[j] ); - } - free( plist ); - } // for each type of element - - for( int i=0 ; ielems[i]->name ); - free( ply->elems[i]->store_prop ); - for( int j=0 ; jelems[i]->nprops ; j++ ) - { - free( ply->elems[i]->props[j]->name ); - free( ply->elems[i]->props[j] ); - } - if( ply->elems[i]->props && ply->elems[i]->nprops ) free(ply->elems[i]->props); - } - for( int i=0 ; ielems[i]); - free( ply->elems) ; - for( int i=0 ; inum_comments ; i++ ) free( ply->comments[i] ); - free( ply->comments ); - for( int i=0 ; inum_obj_info ; i++ ) free( ply->obj_info[i] ); - free( ply->obj_info ); - ply_free_other_elements(ply->other_elems); - - - for( int i=0 ; i +template< class Vertex > int PlyReadPolygons( const char* fileName, - std::vector& vertices,std::vector >& polygons, - const PlyProperty* properties,int propertyNum, - int& file_type, - char*** comments=NULL,int* commentNum=NULL , bool* readFlags=NULL ); + std::vector< Vertex >& vertices , std::vector >& polygons , + const PlyProperty* properties , int propertyNum , + int& file_type , + std::vector< std::string > &comments , bool* readFlags=NULL ); template -int PlyWritePolygons( const char* fileName, - const std::vector& vertices,const std::vector >& polygons , - const PlyProperty* properties,int propertyNum, - int file_type, - char** comments=NULL,const int& commentNum=0); +int PlyWritePolygons( const char* fileName , + const std::vector< Vertex > &vertices , const std::vector< std::vector< int > > &polygons , + const PlyProperty* properties , int propertyNum , + int file_type , + const std::vector< std::string > &comments ); -template -int PlyWritePolygons( const char* fileName, - const std::vector& vertices , const std::vector< std::vector< int > >& polygons, - const PlyProperty* properties,int propertyNum, - int file_type, - char** comments,const int& commentNum) +template< class Vertex > +int PlyWritePolygons( const char* fileName , + const std::vector< Vertex > &vertices , const std::vector< std::vector< int > > &polygons , + const PlyProperty *properties , int propertyNum , + int file_type , + const std::vector< std::string > &comments ) { int nr_vertices=int(vertices.size()); int nr_faces=int(polygons.size()); float version; - const char *elem_names[] = { "vertex" , "face" }; - PlyFile *ply = ply_open_for_writing( fileName , 2 , elem_names , file_type , &version ); + std::vector< std::string > elem_names = { std::string( "vertex" ) , std::string( "face" ) }; + PlyFile *ply = PlyFile::Write( fileName , elem_names , file_type , version ); if (!ply){return 0;} // // describe vertex and face properties // - ply_element_count(ply, "vertex", nr_vertices); - for(int i=0;ielement_count( "vertex", nr_vertices ); + for( int i=0 ; idescribe_property( "vertex" , &properties[i] ); + ply->element_count( "face" , nr_faces ); + ply->describe_property( "face" , &face_props[0] ); - ply_header_complete(ply); + // Write in the comments + for( int i=0 ; iput_comment( comments[i] ); + ply->header_complete(); // write vertices - ply_put_element_setup(ply, "vertex"); - for (int i=0; i < int(vertices.size()); i++) - ply_put_element(ply, (void *) &vertices[i]); + ply->put_element_setup( elem_names[0] ); + for( int i=0 ; i<(int)vertices.size() ; i++ ) ply->put_element( (void *)&vertices[i] ); // write faces PlyFace ply_face; @@ -405,165 +331,91 @@ int PlyWritePolygons( const char* fileName, ply_face.nr_vertices = 3; ply_face.vertices = new int[3]; - ply_put_element_setup(ply, "face"); - for (int i=0; i < nr_faces; i++) + ply->put_element_setup( elem_names[1] ); + for( int i=0 ; imaxFaceVerts) + if( (int)polygons[i].size()>maxFaceVerts ) { delete[] ply_face.vertices; - maxFaceVerts=int(polygons[i].size()); - ply_face.vertices=new int[maxFaceVerts]; + maxFaceVerts = (int)polygons[i].size(); + ply_face.vertices=new int[ maxFaceVerts ]; } - ply_face.nr_vertices=int(polygons[i].size()); - for(int j=0;jput_element( (void *)&ply_face ); } delete[] ply_face.vertices; - if( ply->nelems ) - { - for( int i=0 ; inelems ; i++ ) - { - free( ply->elems[i]->name ); - if( ply->elems[i]->store_prop ) free( ply->elems[i]->store_prop ); - for( int j=0 ; jelems[i]->nprops ; j++ ) - { - free( ply->elems[i]->props[j]->name ); - free( ply->elems[i]->props[j] ); - } - free( ply->elems[i]->props ); - free( ply->elems[i] ); - } - free( ply->elems ); - } - if( ply->num_comments ) - { - for( int i=0 ; inum_comments ; i++ ) free( ply->comments[i] ); - free( ply->comments ); - } - ply_close(ply); + delete ply; + return 1; } -template -int PlyReadPolygons( const char* fileName, - std::vector& vertices , std::vector >& polygons , - const PlyProperty* properties , int propertyNum , - int& file_type , - char*** comments , int* commentNum , bool* readFlags ) +template< class Vertex > +int PlyReadPolygons( const char *fileName , + std::vector< Vertex > &vertices , std::vector< std::vector< int > > &polygons , + const PlyProperty *properties , int propertyNum , + int &file_type , + std::vector< std::string > &comments , bool *readFlags ) { - int nr_elems; - char **elist; + std::vector< std::string > elist; float version; - int i,j,k; - PlyFile* ply; - char* elem_name; - int num_elems; - int nr_props; - PlyProperty** plist; - PlyFace ply_face; - ply = ply_open_for_reading( fileName , &nr_elems , &elist , &file_type , &version ); + PlyFile *ply = PlyFile::Read( fileName , elist , file_type , version ); if(!ply) return 0; - if( comments ) - { - (*comments)=new char*[*commentNum+ply->num_comments]; - for( int i=0 ; inum_comments ; i++ ) (*comments)[i] = _strdup(ply->comments[i]); - *commentNum = ply->num_comments; - } + comments.reserve( comments.size() + ply->comments.size() ); + for( int i=0 ; icomments.size() ; i++ ) comments.push_back( ply->comments[i] ); - for (i=0; i < nr_elems; i++) { - elem_name = elist[i]; - plist = ply_get_element_description(ply, elem_name, &num_elems, &nr_props); - if(!plist) + for( int i=0 ; i plist = ply->get_element_description( elem_name , num_elems ); + if( !plist.size() ) { - for(i=0;ielems[i]->name); - free(ply->elems[i]->store_prop); - for(j=0;jelems[i]->nprops;j++){ - free(ply->elems[i]->props[j]->name); - free(ply->elems[i]->props[j]); - } - free(ply->elems[i]->props); - } - for(i=0;ielems[i]);} - free(ply->elems); - for(i=0;inum_comments;i++) free(ply->comments[i]); - free(ply->comments); - for(i=0;inum_obj_info;i++) free(ply->obj_info[i]); - free(ply->obj_info); - ply_free_other_elements (ply->other_elems); - - for(i=0;iget_property( elem_name , &properties[i] ); if( readFlags ) readFlags[i] = (hasProperty!=0); } - vertices.resize(num_elems); - for (j=0; j < num_elems; j++) ply_get_element (ply, (void *) &vertices[j]); + vertices.resize( num_elems ); + for( int j=0 ; jget_element( (void *)&vertices[j] ); } - else if (equal_strings("face", elem_name)) + else if( elem_name=="face" ) { - ply_get_property (ply, elem_name, &face_props[0]); - polygons.resize(num_elems); - for (j=0; j < num_elems; j++) + ply->get_property( elem_name , &face_props[0] ); + polygons.resize( num_elems ); + for( int j=0 ; jget_element( (void *)&ply_face ); + polygons[j].resize( ply_face.nr_vertices ); + for( int k=0 ; kget_other_element( elem_name , num_elems ); - for(j=0;jname); - free(plist[j]); - } - free(plist); + for( int j=0 ; jelems[i]->name); - free(ply->elems[i]->store_prop); - for(j=0;jelems[i]->nprops;j++){ - free(ply->elems[i]->props[j]->name); - free(ply->elems[i]->props[j]); - } - if(ply->elems[i]->props && ply->elems[i]->nprops){free(ply->elems[i]->props);} - } - for(i=0;ielems[i]);} - free(ply->elems); - for(i=0;inum_comments;i++){free(ply->comments[i]);} - free(ply->comments); - for(i=0;inum_obj_info;i++){free(ply->obj_info[i]);} - free(ply->obj_info); - ply_free_other_elements (ply->other_elems); - - - for(i=0;i -int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point< float , Dim >& translate , float scale , char** comments , int commentNum , XForm< Real , Dim+1 > xForm ) +int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point< float , Dim >& translate , float scale , const std::vector< std::string > &comments , XForm< Real , Dim+1 > xForm ) { - int i; int nr_vertices=int(mesh->outOfCorePointCount()+mesh->inCorePoints.size()); int nr_faces=mesh->polygonCount(); float version; - const char *elem_names[] = { "vertex" , "face" }; - PlyFile *ply = ply_open_for_writing( fileName , 2 , elem_names , file_type , &version ); + std::vector< std::string > elem_names = { std::string( "vertex" ) , std::string( "face" ) }; + PlyFile *ply = PlyFile::Write( fileName , elem_names , file_type , version ); if( !ply ) return 0; mesh->resetIterator(); @@ -571,36 +423,34 @@ int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int // // describe vertex and face properties // - ply_element_count( ply , "vertex" , nr_vertices ); - for( int i=0 ; ielement_count( "vertex" , nr_vertices ); + for( int i=0 ; idescribe_property( "vertex" , &Vertex::Properties[i] ); + ply->element_count( "face" , nr_faces ); + ply->describe_property( "face" , &face_props[0] ); - ply_header_complete( ply ); + // Write in the comments + for( int i=0 ; iput_comment( comments[i] ); + ply->header_complete(); // write vertices - ply_put_element_setup( ply , "vertex" ); - for( i=0 ; iinCorePoints.size() ) ; i++ ) + ply->put_element_setup( "vertex" ); + for( int i=0 ; iinCorePoints.size() ) ; i++ ) { Vertex vertex = xForm * ( mesh->inCorePoints[i] * scale + translate ); - ply_put_element(ply, (void *) &vertex); + ply->put_element( (void *)&vertex ); } - for( i=0; ioutOfCorePointCount() ; i++ ) + for( int i=0; ioutOfCorePointCount() ; i++ ) { Vertex vertex; mesh->nextOutOfCorePoint( vertex ); vertex = xForm * ( vertex * scale + translate ); - ply_put_element(ply, (void *) &vertex); + ply->put_element( (void *)&vertex ); } // for, write vertices // write faces std::vector< CoredVertexIndex > polygon; - ply_put_element_setup( ply , "face" ); - for( i=0 ; iput_element_setup( "face" ); + for( int i=0 ; i* mesh , int mesh->nextPolygon( polygon ); ply_face.nr_vertices = int( polygon.size() ); ply_face.vertices = new int[ polygon.size() ]; - for( int i=0 ; iinCorePoints.size() ); - ply_put_element( ply, (void *) &ply_face ); + for( int j=0 ; jinCorePoints.size() ); + ply->put_element( (void *)&ply_face ); delete[] ply_face.vertices; } // for, write faces - - ply_close( ply ); + + delete ply; + return 1; } template< class Vertex , class Real , int Dim > -int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , char** comments , int commentNum , XForm< Real , Dim+1 > xForm ) +int PlyWritePolygons( const char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const std::vector< std::string > &comments , XForm< Real , Dim+1 > xForm ) { - int i; int nr_vertices=int(mesh->outOfCorePointCount()+mesh->inCorePoints.size()); int nr_faces=mesh->polygonCount(); float version; - const char *elem_names[] = { "vertex" , "face" }; - PlyFile *ply = ply_open_for_writing( fileName , 2 , elem_names , file_type , &version ); + std::vector< std::string > elem_names = { std::string( "vertex" ) , std::string( "face" ) }; + PlyFile *ply = PlyFile::Write( fileName , elem_names , file_type , version ); if( !ply ) return 0; mesh->resetIterator(); - + // // describe vertex and face properties // - ply_element_count( ply , "vertex" , nr_vertices ); + ply->element_count( "vertex" , nr_vertices ); typename Vertex::Transform _xForm( xForm ); const PlyProperty* PlyWriteProperties = Vertex::PlyWriteProperties(); - for( int i=0 ; idescribe_property( "vertex" , &PlyWriteProperties[i] ); + ply->element_count( "face" , nr_faces ); + ply->describe_property( "face" , &face_props[0] ); - ply_element_count( ply , "face" , nr_faces ); - ply_describe_property( ply , "face" , &face_props[0] ); - // Write in the comments - for( i=0 ; iput_comment( comments[i] ); + ply->header_complete(); // write vertices - ply_put_element_setup( ply , "vertex" ); - for( i=0 ; iinCorePoints.size() ) ; i++ ) + ply->put_element_setup( "vertex" ); + for( int i=0 ; iinCorePoints.size() ) ; i++ ) { Vertex vertex = _xForm( mesh->inCorePoints[i] ); - ply_put_element(ply, (void *) &vertex); + ply->put_element( (void *)&vertex ); } - for( i=0; ioutOfCorePointCount() ; i++ ) + for( int i=0; ioutOfCorePointCount() ; i++ ) { Vertex vertex; mesh->nextOutOfCorePoint( vertex ); vertex = _xForm( vertex ); - ply_put_element(ply, (void *) &vertex); + ply->put_element( (void *)&vertex ); } // for, write vertices - - // write faces + + // write faces std::vector< CoredVertexIndex > polygon; - ply_put_element_setup( ply , "face" ); - for( i=0 ; iput_element_setup( "face" ); + for( int i=0 ; i* mesh , int mesh->nextPolygon( polygon ); ply_face.nr_vertices = int( polygon.size() ); ply_face.vertices = new int[ polygon.size() ]; - for( int i=0 ; iinCorePoints.size() ); - ply_put_element( ply, (void *) &ply_face ); - delete[] ply_face.vertices; + for( int j=0 ; jinCorePoints.size() ); + ply->put_element( (void *)&ply_face ); + delete[] ply_face.vertices; } // for, write faces - - if( ply->nelems ) - { - for( int i=0 ; inelems ; i++ ) - { - free( ply->elems[i]->name ); - if( ply->elems[i]->store_prop ) free( ply->elems[i]->store_prop ); - for( int j=0 ; jelems[i]->nprops ; j++ ) - { - free( ply->elems[i]->props[j]->name ); - free( ply->elems[i]->props[j] ); - } - free( ply->elems[i]->props ); - free( ply->elems[i] ); - } - free( ply->elems ); - } - if( ply->num_comments ) - { - for( int i=0 ; inum_comments ; i++ ) free( ply->comments[i] ); - free( ply->comments ); - } - ply_close( ply ); + + delete ply; + return 1; } inline int PlyDefaultFileType(void){return PLY_ASCII;} diff --git a/Src/PlyFile.cpp b/Src/PlyFile.cpp index e2a457a..d5bb00f 100644 --- a/Src/PlyFile.cpp +++ b/Src/PlyFile.cpp @@ -38,7 +38,8 @@ WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. #include #include "PlyFile.h" -const char *type_names[] = { +const char *type_names[] = +{ "invalid", "char", "short", @@ -57,10 +58,10 @@ const char *type_names[] = { "uint32", // unsigned integer 4 "float32", // single-precision float 4 "float64", // double-precision float 8 - }; -int ply_type_size[] = { +int ply_type_size[] = +{ 0, 1, 2, @@ -99,55 +100,33 @@ static int types_checked = 0; #define NAMED_PROP 1 -/* returns 1 if strings are equal, 0 if not */ -int equal_strings(const char *, const char *); - -/* find an element in a plyfile's list */ -PlyElement *find_element(PlyFile *, const char *); - -/* find a property in an element's list */ -PlyProperty *find_property(PlyElement *, const char *, int *); - /* write to a file the word describing a PLY file data type */ void write_scalar_type (FILE *, int); /* read a line from a file and break it up into separate words */ -char **get_words(FILE *, int *, char **); -char **old_get_words(FILE *, int *); +std::vector< std::string > get_words( FILE * , char ** ); +std::vector< std::string > old_get_words( FILE * ); + +/* write to a file the word describing a PLY file data type */ +void write_scalar_type (FILE *, int); /* write an item to a file */ void write_binary_item(FILE *, int, int, unsigned int, double, int); void write_ascii_item(FILE *, int, unsigned int, double, int); double old_write_ascii_item(FILE *, char *, int); -/* add information to a PLY file descriptor */ -void add_element(PlyFile *, char **); -void add_property(PlyFile *, char **); -void add_comment(PlyFile *, char *); -void add_obj_info(PlyFile *, char *); - -/* copy a property */ -void copy_property(PlyProperty *, const PlyProperty *); - /* store a value into where a pointer and a type specify */ void store_item(char *, int, int, unsigned int, double); /* return the value of a stored item */ -void get_stored_item( void *, int, int *, unsigned int *, double *); +void get_stored_item( void * , int , int & , unsigned int & , double & ); /* return the value stored in an item, given ptr to it and its type */ double get_item_value(char *, int); /* get binary or ascii item and store it according to ptr and type */ -void get_ascii_item(char *, int, int *, unsigned int *, double *); -void get_binary_item(FILE *, int, int, int *, unsigned int *, double *); - -/* get a bunch of elements from a file */ -void ascii_get_element(PlyFile *, char *); -void binary_get_element(PlyFile *, char *); - -/* memory allocation */ -char *my_alloc(int, int, const char *); +void get_ascii_item( const std::string & , int , int & , unsigned int & , double & ); +void get_binary_item( FILE * , int , int , int & , unsigned int & , double & ); /* byte ordering */ void get_native_binary_type(); @@ -173,53 +152,30 @@ Exit: returns a pointer to a PlyFile, used to refer to this file, or NULL if error ******************************************************************************/ -PlyFile *ply_write( - FILE *fp, - int nelems, - const char **elem_names, - int file_type -) +PlyFile *PlyFile::_Write( FILE *fp , const std::vector< std::string > &elem_names , int file_type ) { - int i; - PlyFile *plyfile; - PlyElement *elem; - /* check for NULL file pointer */ - if (fp == NULL) - return (NULL); + if( fp==NULL ) return NULL; - if (native_binary_type == -1) - get_native_binary_type(); - if (!types_checked) - check_types(); + if( native_binary_type==-1 ) get_native_binary_type(); + if( !types_checked ) check_types(); /* create a record for this object */ - plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); - if (file_type == PLY_BINARY_NATIVE) - plyfile->file_type = native_binary_type; - else - plyfile->file_type = file_type; - plyfile->num_comments = 0; - plyfile->num_obj_info = 0; - plyfile->nelems = nelems; - plyfile->version = 1.0; - plyfile->fp = fp; - plyfile->other_elems = NULL; + PlyFile *plyfile = new PlyFile( fp ); + if( file_type==PLY_BINARY_NATIVE ) plyfile->file_type = native_binary_type; + else plyfile->file_type = file_type; /* tuck aside the names of the elements */ - - plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); - for (i = 0; i < nelems; i++) { - elem = (PlyElement *) myalloc (sizeof (PlyElement)); - plyfile->elems[i] = elem; - elem->name = _strdup (elem_names[i]); - elem->num = 0; - elem->nprops = 0; + plyfile->elems.resize( elem_names.size() ); + for( int i=0 ; ielems[i].name = elem_names[i]; + plyfile->elems[i].num = 0; } /* return pointer to the file descriptor */ - return (plyfile); + return plyfile; } @@ -237,45 +193,24 @@ version - version number of PLY file returns a file identifier, used to refer to this file, or NULL if error ******************************************************************************/ -PlyFile *ply_open_for_writing( - const char *filename, - int nelems, - const char **elem_names, - int file_type, - float *version -) +PlyFile *PlyFile::Write( const std::string &filename , const std::vector< std::string > &elem_names , int file_type , float &version ) { - PlyFile *plyfile; - char *name; - FILE *fp; - /* tack on the extension .ply, if necessary */ - - name = (char *) myalloc (int(sizeof (char) * (strlen (filename)) + 5)); - strcpy (name, filename); - if (strlen (name) < 4 || - strcmp (name + strlen (name) - 4, ".ply") != 0) - strcat (name, ".ply"); + std::string name = filename; + if( name.length()<4 || name.substr( name.length()-4 )!=".ply" ) name += ".ply"; /* open the file for writing */ - - fp = fopen (name, "wb"); - free(name); - if (fp == NULL) { - return (NULL); - } + FILE *fp = fopen( name.c_str() , "wb" ); + if( fp==NULL ) return NULL; /* create the actual PlyFile structure */ - - plyfile = ply_write (fp, nelems, elem_names, file_type); - if (plyfile == NULL) - return (NULL); + PlyFile *plyfile = _Write( fp , elem_names , file_type ); /* say what PLY file version number we're writing */ - *version = plyfile->version; + version = plyfile->version; /* return pointer to the file descriptor */ - return (plyfile); + return plyfile; } @@ -284,46 +219,23 @@ Describe an element, including its properties and how many will be written to the file. Entry: -plyfile - file identifier elem_name - name of element that information is being specified about nelems - number of elements of this type to be written nprops - number of properties contained in the element prop_list - list of properties ******************************************************************************/ -void ply_describe_element( - PlyFile *plyfile, - char *elem_name, - int nelems, - int nprops, - PlyProperty *prop_list -) +void PlyFile::describe_element( const std::string &elem_name , int nelems , int nprops , const PlyProperty *prop_list ) { - int i; - PlyElement *elem; - PlyProperty *prop; - /* look for appropriate element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name); - exit (-1); - } + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) fprintf( stderr , "[ERROR] PlyFile::describe_element: can't find element '%s'\n" , elem_name.c_str() ) , exit (-1); elem->num = nelems; /* copy the list of properties */ - - elem->nprops = nprops; - elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); - elem->store_prop = (char *) myalloc (sizeof (char) * nprops); - - for (i = 0; i < nprops; i++) { - prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - elem->props[i] = prop; - elem->store_prop[i] = NAMED_PROP; - copy_property (prop, &prop_list[i]); - } + elem->props.resize( nprops ); + for( int i=0 ; iprops[i] = PlyStoredProperty( prop_list[i] , NAMED_PROP ); } @@ -331,49 +243,21 @@ void ply_describe_element( Describe a property of an element. Entry: -plyfile - file identifier elem_name - name of element that information is being specified about prop - the new property ******************************************************************************/ -void ply_describe_property( - PlyFile *plyfile, - const char *elem_name, - const PlyProperty *prop -) +void PlyFile::describe_property( const std::string &elem_name , const PlyProperty *prop ) { - PlyElement *elem; - PlyProperty *elem_prop; - /* look for appropriate element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf(stderr, "ply_describe_property: can't find element '%s'\n", - elem_name); + PlyElement *elem = find_element( elem_name ); + if( elem == NULL ) + { + fprintf( stderr , "[WARNING] PlyFile::describe_property: can't find element '%s'\n" , elem_name.c_str() ); return; } - /* create room for new property */ - - if (elem->nprops == 0) { - elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); - elem->store_prop = (char *) myalloc (sizeof (char)); - elem->nprops = 1; - } - else { - elem->nprops++; - elem->props = (PlyProperty **) - realloc (elem->props, sizeof (PlyProperty *) * elem->nprops); - elem->store_prop = (char *) - realloc (elem->store_prop, sizeof (char) * elem->nprops); - } - - /* copy the new property */ - - elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - elem->props[elem->nprops - 1] = elem_prop; - elem->store_prop[elem->nprops - 1] = NAMED_PROP; - copy_property (elem_prop, prop); + elem->props.push_back( PlyStoredProperty( *prop , NAMED_PROP ) ); } @@ -382,53 +266,21 @@ Describe what the "other" properties are that are to be stored, and where they are in an element. ******************************************************************************/ -void ply_describe_other_properties( - PlyFile *plyfile, - PlyOtherProp *other, - int offset -) +void PlyFile::describe_other_properties( const PlyOtherProp &other , int offset ) { - int i; - PlyElement *elem; - PlyProperty *prop; - /* look for appropriate element */ - elem = find_element (plyfile, other->name); - if (elem == NULL) { - fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n", - other->name); + PlyElement *elem = find_element( other.name ); + if( elem==NULL ) + { + fprintf( stderr , "[WARNING] PlyFile::describe_other_properties: can't find element '%s'\n" , other.name.c_str() ); return; } - /* create room for other properties */ - - if (elem->nprops == 0) { - elem->props = (PlyProperty **) - myalloc (sizeof (PlyProperty *) * other->nprops); - elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops); - elem->nprops = 0; - } - else { - int newsize; - newsize = elem->nprops + other->nprops; - elem->props = (PlyProperty **) - realloc (elem->props, sizeof (PlyProperty *) * newsize); - elem->store_prop = (char *) - realloc (elem->store_prop, sizeof (char) * newsize); - } - - /* copy the other properties */ - - for (i = 0; i < other->nprops; i++) { - prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - copy_property (prop, other->props[i]); - elem->props[elem->nprops] = prop; - elem->store_prop[elem->nprops] = OTHER_PROP; - elem->nprops++; - } + elem->props.reserve( elem->props.size() + other.props.size() ); + for( int i=0 ; iprops.push_back( PlyStoredProperty( other.props[i] , OTHER_PROP ) ); /* save other info about other properties */ - elem->other_size = other->size; + elem->other_size = other.size; elem->other_offset = offset; } @@ -437,25 +289,14 @@ void ply_describe_other_properties( State how many of a given element will be written. Entry: -plyfile - file identifier elem_name - name of element that information is being specified about nelems - number of elements of this type to be written ******************************************************************************/ - -void ply_element_count( - PlyFile *plyfile, - const char *elem_name, - int nelems -) +void PlyFile::element_count( const std::string &elem_name , int nelems ) { - PlyElement *elem; - /* look for appropriate element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name); - exit (-1); - } + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) fprintf( stderr , "[ERROR] PlyFile::element_count: can't find element '%s'\n" , elem_name.c_str() ) , exit (-1); elem->num = nelems; } @@ -464,72 +305,50 @@ void ply_element_count( /****************************************************************************** Signal that we've described everything a PLY file's header and that the header should be written to the file. - -Entry: -plyfile - file identifier ******************************************************************************/ -void ply_header_complete(PlyFile *plyfile) +void PlyFile::header_complete( void ) { - int i,j; - FILE *fp = plyfile->fp; - PlyElement *elem; - PlyProperty *prop; - - fprintf (fp, "ply\n"); - - switch (plyfile->file_type) { - case PLY_ASCII: - fprintf (fp, "format ascii 1.0\n"); - break; - case PLY_BINARY_BE: - fprintf (fp, "format binary_big_endian 1.0\n"); - break; - case PLY_BINARY_LE: - fprintf (fp, "format binary_little_endian 1.0\n"); - break; - default: - fprintf (stderr, "ply_header_complete: bad file type = %d\n", - plyfile->file_type); - exit (-1); + fprintf( fp , "ply\n" ); + switch( file_type ) + { + case PLY_ASCII: fprintf( fp , "format ascii 1.0\n" ) ; break; + case PLY_BINARY_BE: fprintf( fp , "format binary_big_endian 1.0\n" ) ; break; + case PLY_BINARY_LE: fprintf( fp , "format binary_little_endian 1.0\n" ) ; break; + default: fprintf( stderr , "[ERROR] PlyFile::header_complete: bad file type = %d\n" , file_type ) , exit (-1); } /* write out the comments */ - - for (i = 0; i < plyfile->num_comments; i++) - fprintf (fp, "comment %s\n", plyfile->comments[i]); + for( int i=0 ; inum_obj_info; i++) - fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); + for( int i=0 ; inelems; i++) { - - elem = plyfile->elems[i]; - fprintf (fp, "element %s %d\n", elem->name, elem->num); - - /* write out each property */ - for (j = 0; j < elem->nprops; j++) { - prop = elem->props[j]; - if (prop->is_list) { - fprintf (fp, "property list "); - write_scalar_type (fp, prop->count_external); - fprintf (fp, " "); - write_scalar_type (fp, prop->external_type); - fprintf (fp, " %s\n", prop->name); + for( int j=0 ; jexternal_type); - fprintf (fp, " %s\n", prop->name); + else + { + fprintf( fp , "property " ); + write_scalar_type( fp , elems[i].props[j].prop.external_type ); + fprintf( fp , " %s\n", elems[i].props[j].prop.name.c_str() ); } } } - fprintf (fp, "end_header\n"); + fprintf( fp , "end_header\n" ); } @@ -538,21 +357,14 @@ Specify which elements are going to be written. This should be called before a call to the routine ply_put_element(). Entry: -plyfile - file identifier elem_name - name of element we're talking about ******************************************************************************/ -void ply_put_element_setup(PlyFile *plyfile, const char *elem_name) +void PlyFile::put_element_setup( const std::string &elem_name ) { - PlyElement *elem; - - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name); - exit (-1); - } - - plyfile->which_elem = elem; + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) fprintf( stderr , "[ERROR] PlyFile::put_element_setup: can't find element '%s'\n" , elem_name.c_str() ) , exit(-1); + which_elem = elem; } @@ -562,16 +374,11 @@ writing the type of element specified in the last call to the routine ply_put_element_setup(). Entry: -plyfile - file identifier elem_ptr - pointer to the element ******************************************************************************/ -void ply_put_element(PlyFile *plyfile, void *elem_ptr) +void PlyFile::put_element( void *elem_ptr ) { - int j,k; - FILE *fp = plyfile->fp; - PlyElement *elem; - PlyProperty *prop; char *elem_data,*item; char **item_ptr; int list_count; @@ -581,92 +388,76 @@ void ply_put_element(PlyFile *plyfile, void *elem_ptr) double double_val; char **other_ptr; - elem = plyfile->which_elem; + PlyElement *elem = which_elem; elem_data = (char *)elem_ptr; other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); /* write out either to an ascii or binary file */ - if (plyfile->file_type == PLY_ASCII) { - - /* write an ascii file */ - + if( file_type==PLY_ASCII ) /* write an ascii file */ + { /* write out each property of the element */ - for (j = 0; j < elem->nprops; j++) { - prop = elem->props[j]; - if (elem->store_prop[j] == OTHER_PROP) - elem_data = *other_ptr; - else - elem_data = (char *)elem_ptr; - if (prop->is_list) { - item = elem_data + prop->count_offset; - get_stored_item ((void *) item, prop->count_internal, - &int_val, &uint_val, &double_val); - write_ascii_item (fp, int_val, uint_val, double_val, - prop->count_external); + for( int j=0 ; jprops.size() ; j++ ) + { + if( elem->props[j].store==OTHER_PROP ) elem_data = *other_ptr; + else elem_data = (char *)elem_ptr; + if( elem->props[j].prop.is_list ) + { + item = elem_data + elem->props[j].prop.count_offset; + get_stored_item( (void *)item , elem->props[j].prop.count_internal , int_val , uint_val , double_val ); + write_ascii_item( fp , int_val , uint_val , double_val , elem->props[j].prop.count_external ); list_count = uint_val; - item_ptr = (char **) (elem_data + prop->offset); + item_ptr = (char **)( elem_data + elem->props[j].prop.offset ); item = item_ptr[0]; - item_size = ply_type_size[prop->internal_type]; - for (k = 0; k < list_count; k++) { - get_stored_item ((void *) item, prop->internal_type, - &int_val, &uint_val, &double_val); - write_ascii_item (fp, int_val, uint_val, double_val, - prop->external_type); + item_size = ply_type_size[ elem->props[j].prop.internal_type ]; + for( int k=0 ; kprops[j].prop.internal_type , int_val , uint_val , double_val ); + write_ascii_item( fp , int_val , uint_val , double_val , elem->props[j].prop.external_type ); item += item_size; } } - else { - item = elem_data + prop->offset; - get_stored_item ((void *) item, prop->internal_type, - &int_val, &uint_val, &double_val); - write_ascii_item (fp, int_val, uint_val, double_val, - prop->external_type); + else + { + item = elem_data + elem->props[j].prop.offset; + get_stored_item( (void *)item , elem->props[j].prop.internal_type , int_val , uint_val , double_val ); + write_ascii_item( fp , int_val , uint_val , double_val , elem->props[j].prop.external_type ); } } - - fprintf (fp, "\n"); + fprintf( fp , "\n" ); } - else { - - /* write a binary file */ - + else /* write a binary file */ + { /* write out each property of the element */ - for (j = 0; j < elem->nprops; j++) { - prop = elem->props[j]; - if (elem->store_prop[j] == OTHER_PROP) - elem_data = *other_ptr; - else - elem_data = (char *)elem_ptr; - if (prop->is_list) { - item = elem_data + prop->count_offset; - item_size = ply_type_size[prop->count_internal]; - get_stored_item ((void *) item, prop->count_internal, - &int_val, &uint_val, &double_val); - write_binary_item (fp, plyfile->file_type, int_val, uint_val, - double_val, prop->count_external); + for( int j=0 ; jprops.size() ; j++ ) + { + if (elem->props[j].store==OTHER_PROP ) elem_data = *other_ptr; + else elem_data = (char *)elem_ptr; + if( elem->props[j].prop.is_list ) + { + item = elem_data + elem->props[j].prop.count_offset; + item_size = ply_type_size[ elem->props[j].prop.count_internal ]; + get_stored_item( (void *)item , elem->props[j].prop.count_internal , int_val , uint_val , double_val ); + write_binary_item( fp , file_type , int_val , uint_val , double_val , elem->props[j].prop.count_external ); list_count = uint_val; - item_ptr = (char **) (elem_data + prop->offset); + item_ptr = (char **)( elem_data + elem->props[j].prop.offset ); item = item_ptr[0]; - item_size = ply_type_size[prop->internal_type]; - for (k = 0; k < list_count; k++) { - get_stored_item ((void *) item, prop->internal_type, - &int_val, &uint_val, &double_val); - write_binary_item (fp, plyfile->file_type, int_val, uint_val, - double_val, prop->external_type); + item_size = ply_type_size[ elem->props[j].prop.internal_type ]; + for( int k=0 ; kprops[j].prop.internal_type , int_val , uint_val , double_val ); + write_binary_item( fp , file_type , int_val , uint_val , double_val , elem->props[j].prop.external_type ); item += item_size; } } - else { - item = elem_data + prop->offset; - item_size = ply_type_size[prop->internal_type]; - get_stored_item ((void *) item, prop->internal_type, - &int_val, &uint_val, &double_val); - write_binary_item (fp, plyfile->file_type, int_val, uint_val, - double_val, prop->external_type); + else + { + item = elem_data + elem->props[j].prop.offset; + item_size = ply_type_size[ elem->props[j].prop.internal_type ]; + get_stored_item( (void *)item , elem->props[j].prop.internal_type , int_val , uint_val , double_val ); + write_binary_item( fp , file_type , int_val , uint_val , double_val , elem->props[j].prop.external_type ); } } - } } @@ -675,23 +466,10 @@ void ply_put_element(PlyFile *plyfile, void *elem_ptr) Specify a comment that will be written in the header. Entry: -plyfile - file identifier comment - the comment to be written ******************************************************************************/ -void ply_put_comment(PlyFile *plyfile, char *comment) -{ - /* (re)allocate space for new comment */ - if (plyfile->num_comments == 0) - plyfile->comments = (char **) myalloc (sizeof (char *)); - else - plyfile->comments = (char **) realloc (plyfile->comments, - sizeof (char *) * (plyfile->num_comments + 1)); - - /* add comment to list */ - plyfile->comments[plyfile->num_comments] = _strdup (comment); - plyfile->num_comments++; -} +void PlyFile::put_comment( const std::string &comment ){ comments.push_back( comment ); } /****************************************************************************** @@ -699,28 +477,10 @@ Specify a piece of object information (arbitrary text) that will be written in the header. Entry: -plyfile - file identifier obj_info - the text information to be written ******************************************************************************/ -void ply_put_obj_info(PlyFile *plyfile, char *obj_info) -{ - /* (re)allocate space for new info */ - if (plyfile->num_obj_info == 0) - plyfile->obj_info = (char **) myalloc (sizeof (char *)); - else - plyfile->obj_info = (char **) realloc (plyfile->obj_info, - sizeof (char *) * (plyfile->num_obj_info + 1)); - - /* add info to list */ - plyfile->obj_info[plyfile->num_obj_info] = _strdup (obj_info); - plyfile->num_obj_info++; -} - - - - - +void PlyFile::put_obj_info( const std::string &obj_info ){ this->obj_info.push_back( obj_info ); } /*************/ @@ -741,105 +501,57 @@ elem_names - list of element names returns a pointer to a PlyFile, used to refer to this file, or NULL if error ******************************************************************************/ -PlyFile *ply_read( FILE *fp , int *nelems , char ***elem_names ) +PlyFile *PlyFile::_Read( FILE *fp , std::vector< std::string > &elem_names ) { - int i,j; - PlyFile *plyfile; - int nwords; - char **words; - char **elist; - PlyElement *elem; char *orig_line; /* check for NULL file pointer */ - if (fp == NULL) - return (NULL); + if( fp==NULL ) return NULL; + + if( native_binary_type==-1 ) get_native_binary_type(); + if( !types_checked ) check_types(); - if (native_binary_type == -1) - get_native_binary_type(); - if (!types_checked) - check_types(); /* create record for this object */ - - plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); - plyfile->nelems = 0; - plyfile->comments = NULL; - plyfile->num_comments = 0; - plyfile->obj_info = NULL; - plyfile->num_obj_info = 0; - plyfile->fp = fp; - plyfile->other_elems = NULL; + std::vector< std::string > words; + PlyFile *plyfile = new PlyFile( fp ); /* read and parse the file's header */ - - words = get_words (plyfile->fp, &nwords, &orig_line); - if (!words || !equal_strings (words[0], "ply")) + words = get_words( plyfile->fp , &orig_line ); + if( !words.size() || words[0]!="ply" ) return NULL; + while( words.size() ) { - if (words) - free(words); - return (NULL); - } - while (words) { /* parse words */ - - if (equal_strings (words[0], "format")) { - if (nwords != 3) { - free(words); - return (NULL); - } - if (equal_strings (words[1], "ascii")) - plyfile->file_type = PLY_ASCII; - else if (equal_strings (words[1], "binary_big_endian")) - plyfile->file_type = PLY_BINARY_BE; - else if (equal_strings (words[1], "binary_little_endian")) - plyfile->file_type = PLY_BINARY_LE; - else { - free(words); - return (NULL); - } - plyfile->version = (float)atof (words[2]); - } - else if (equal_strings (words[0], "element")) - add_element (plyfile, words); - else if (equal_strings (words[0], "property")) - add_property (plyfile, words); - else if (equal_strings (words[0], "comment")) - add_comment (plyfile, orig_line); - else if (equal_strings (words[0], "obj_info")) - add_obj_info (plyfile, orig_line); - else if (equal_strings (words[0], "end_header")) { - free(words); - break; + if( words[0]=="format" ) + { + if( words.size()!=3 ) return NULL; + if ( words[1]=="ascii" ) plyfile->file_type = PLY_ASCII; + else if( words[1]=="binary_big_endian" ) plyfile->file_type = PLY_BINARY_BE; + else if( words[1]=="binary_little_endian" ) plyfile->file_type = PLY_BINARY_LE; + else return NULL; + plyfile->version = (float)atof( words[2].c_str() ); } + else if( words[0]=="element" ) plyfile->add_element ( words ); + else if( words[0]=="property" ) plyfile->add_property( words ); + else if( words[0]=="comment" ) plyfile->add_comment ( orig_line ); + else if( words[0]=="obj_info" ) plyfile->add_obj_info( orig_line ); + else if( words[0]=="end_header" ) break; - /* free up words space */ - free (words); - - words = get_words (plyfile->fp, &nwords, &orig_line); + words = get_words( plyfile->fp , &orig_line ); } /* create tags for each property of each element, to be used */ /* later to say whether or not to store each property for the user */ - - for (i = 0; i < plyfile->nelems; i++) { - elem = plyfile->elems[i]; - elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); - for (j = 0; j < elem->nprops; j++) - elem->store_prop[j] = DONT_STORE_PROP; - elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ + for( int i=0 ; ielems.size() ; i++ ) + { + for( int j=0 ; jelems[i].props.size() ; j++ ) plyfile->elems[i].props[j].store = DONT_STORE_PROP; + plyfile->elems[i].other_offset = NO_OTHER_PROPS; /* no "other" props by default */ } /* set return values about the elements */ - - elist = (char **) myalloc (sizeof (char *) * plyfile->nelems); - for (i = 0; i < plyfile->nelems; i++) - elist[i] = _strdup (plyfile->elems[i]->name); - - *elem_names = elist; - *nelems = plyfile->nelems; + elem_names.resize( plyfile->elems.size() ); + for( int i=0 ; ielems[i].name; /* return a pointer to the file's information */ - - return (plyfile); + return plyfile; } @@ -857,45 +569,25 @@ version - version number of PLY file returns a file identifier, used to refer to this file, or NULL if error ******************************************************************************/ -PlyFile *ply_open_for_reading( - const char *filename, - int *nelems, - char ***elem_names, - int *file_type, - float *version -) +PlyFile *PlyFile::Read( const std::string &filename , std::vector< std::string > &elem_names , int &file_type , float &version ) { - FILE *fp; - PlyFile *plyfile; - char *name; - /* tack on the extension .ply, if necessary */ - - name = (char *) myalloc (int(sizeof (char) * (strlen (filename) + 5))); - strcpy (name, filename); - if (strlen (name) < 4 || - strcmp (name + strlen (name) - 4, ".ply") != 0) - strcat (name, ".ply"); + std::string name = filename; + if( name.length()<4 || name.substr( name.length()-4 )!=".ply" ) name += ".ply"; /* open the file for reading */ - - fp = fopen (name, "rb"); - free(name); - if (fp == NULL) - return (NULL); + FILE *fp = fopen( name.c_str() , "rb" ); + if( fp==NULL ) return NULL; /* create the PlyFile data structure */ - - plyfile = ply_read (fp, nelems, elem_names); + PlyFile *plyfile = _Read( fp , elem_names ); /* determine the file type and version */ - - *file_type = plyfile->file_type; - *version = plyfile->version; + file_type = plyfile->file_type; + version = plyfile->version; /* return a pointer to the file's information */ - - return (plyfile); + return plyfile; } @@ -903,7 +595,6 @@ PlyFile *ply_open_for_reading( Get information about a particular element. Entry: -plyfile - file identifier elem_name - name of element to get information about Exit: @@ -912,74 +603,48 @@ nprops - number of properties returns a list of properties, or NULL if the file doesn't contain that elem ******************************************************************************/ -PlyProperty **ply_get_element_description( - PlyFile *plyfile, - char *elem_name, - int *nelems, - int *nprops -) +std::vector< PlyProperty * > PlyFile::get_element_description( const std::string &elem_name , int &nelems ) { - int i; - PlyElement *elem; - PlyProperty *prop; - PlyProperty **prop_list; + std::vector< PlyProperty * > prop_list; /* find information about the element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) - return (NULL); - - *nelems = elem->num; - *nprops = elem->nprops; + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) return prop_list; + nelems = elem->num; /* make a copy of the element's property list */ - prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); - for (i = 0; i < elem->nprops; i++) { - prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - copy_property (prop, elem->props[i]); - prop_list[i] = prop; - } + prop_list.resize( elem->props.size() ); + for( int i=0 ; iprops.size() ; i++ ) prop_list[i] = new PlyProperty( elem->props[i].prop ); /* return this duplicate property list */ - return (prop_list); + return prop_list; } - /****************************************************************************** Specify which properties of an element are to be returned. This should be called before a call to the routine ply_get_element(). Entry: -plyfile - file identifier elem_name - which element we're talking about nprops - number of properties prop_list - list of properties ******************************************************************************/ -void ply_get_element_setup( - PlyFile *plyfile, - char *elem_name, - int nprops, - PlyProperty *prop_list -) +void PlyFile::get_element_setup( const std::string &elem_name , int nprops , PlyProperty *prop_list ) { - int i; - PlyElement *elem; - PlyProperty *prop; - int index; - /* find information about the element */ - elem = find_element (plyfile, elem_name); - plyfile->which_elem = elem; + PlyElement *elem = find_element( elem_name ); + which_elem = elem; /* deposit the property information into the element's description */ - for (i = 0; i < nprops; i++) { - + for( int i=0 ; ifind_property( prop_list[i].name , index ); + if( prop==NULL ) + { + fprintf( stderr , "Warning: Can't find property '%s' in element '%s'\n" , prop_list[i].name.c_str() , elem_name.c_str() ); continue; } @@ -990,7 +655,7 @@ void ply_get_element_setup( prop->count_offset = prop_list[i].count_offset; /* specify that the user wants this property */ - elem->store_prop[index] = STORE_PROP; + elem->props[index].store = STORE_PROP; } } @@ -1002,41 +667,28 @@ This routine should be used in preference to the less flexible old routine called ply_get_element_setup(). Entry: -plyfile - file identifier elem_name - which element we're talking about prop - property to add to those that will be returned ******************************************************************************/ -int ply_get_property( - PlyFile *plyfile, - char *elem_name, - const PlyProperty *prop -) +int PlyFile::get_property( const std::string &elem_name , const PlyProperty *prop ) { - PlyElement *elem; - PlyProperty *prop_ptr; - int index; - /* find information about the element */ - elem = find_element (plyfile, elem_name); - plyfile->which_elem = elem; + PlyElement *elem = find_element( elem_name ); + which_elem = elem; /* deposit the property information into the element's description */ - - prop_ptr = find_property (elem, prop->name, &index); - if (prop_ptr == NULL) { - // fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", - // prop->name, elem_name); - // return; - return 0; - } + int index; + PlyProperty *prop_ptr = elem->find_property( prop->name , index ); + if( prop_ptr==NULL ) return 0; prop_ptr->internal_type = prop->internal_type; prop_ptr->offset = prop->offset; prop_ptr->count_internal = prop->count_internal; prop_ptr->count_offset = prop->count_offset; /* specify that the user wants this property */ - elem->store_prop[index] = STORE_PROP; + elem->props[index].store = STORE_PROP; + return 1; } @@ -1047,55 +699,34 @@ the type of element specified in the last call to the routine ply_get_element_setup(). Entry: -plyfile - file identifier elem_ptr - pointer to location where the element information should be put ******************************************************************************/ -void ply_get_element(PlyFile *plyfile, void *elem_ptr) +void PlyFile::get_element( void *elem_ptr ) { - if (plyfile->file_type == PLY_ASCII) - ascii_get_element (plyfile, (char *) elem_ptr); - else - binary_get_element (plyfile, (char *) elem_ptr); + if( file_type==PLY_ASCII ) _ascii_get_element( (char *)elem_ptr ); + else _binary_get_element( (char *)elem_ptr ); } - /****************************************************************************** Extract the comments from the header information of a PLY file. -Entry: -plyfile - file identifier - Exit: num_comments - number of comments returned returns a pointer to a list of comments ******************************************************************************/ -char **ply_get_comments(PlyFile *plyfile, int *num_comments) -{ - *num_comments = plyfile->num_comments; - return (plyfile->comments); -} - +std::vector< std::string > &PlyFile::get_comments( void ){ return comments; } /****************************************************************************** Extract the object information (arbitrary text) from the header information of a PLY file. -Entry: -plyfile - file identifier - Exit: num_obj_info - number of lines of text information returned returns a pointer to a list of object info lines ******************************************************************************/ - -char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info) -{ - *num_obj_info = plyfile->num_obj_info; - return (plyfile->obj_info); -} - +std::vector< std::string > &PlyFile::get_obj_info( void ){ return obj_info; } /****************************************************************************** Make ready for "other" properties of an element-- those properties that @@ -1104,60 +735,56 @@ in a special structure to be carried along with the element's other information. Entry: -plyfile - file identifier elem - element for which we want to save away other properties ******************************************************************************/ -void setup_other_props(PlyElement *elem) +void setup_other_props( PlyElement *elem ) { - int i; - PlyProperty *prop; int size = 0; - int type_size; /* Examine each property in decreasing order of size. */ /* We do this so that all data types will be aligned by */ /* word, half-word, or whatever within the structure. */ - for (type_size = 8; type_size > 0; type_size /= 2) { + for( int type_size=8 ; type_size>0 ; type_size/=2 ) + { /* add up the space taken by each property, and save this information */ /* away in the property descriptor */ - - for (i = 0; i < elem->nprops; i++) { - + for( int i=0 ; iprops.size() ; i++ ) + { /* don't bother with properties we've been asked to store explicitly */ - if (elem->store_prop[i]) - continue; - - prop = elem->props[i]; + if( elem->props[i].store ) continue; + PlyProperty &prop = elem->props[i].prop; /* internal types will be same as external */ - prop->internal_type = prop->external_type; - prop->count_internal = prop->count_external; + prop.internal_type = prop.external_type; + prop.count_internal = prop.count_external; /* check list case */ - if (prop->is_list) { - + if( prop.is_list ) + { /* pointer to list */ - if (type_size == sizeof (void *)) { - prop->offset = size; - size += sizeof (void *); /* always use size of a pointer here */ + if( type_size==sizeof(void *) ) + { + prop.offset = size; + size += sizeof( void * ); /* always use size of a pointer here */ } /* count of number of list elements */ - if (type_size == ply_type_size[prop->count_external]) { - prop->count_offset = size; - size += ply_type_size[prop->count_external]; + if( type_size==ply_type_size[ prop.count_external ] ) + { + prop.count_offset = size; + size += ply_type_size[ prop.count_external ]; } } /* not list */ - else if (type_size == ply_type_size[prop->external_type]) { - prop->offset = size; - size += ply_type_size[prop->external_type]; + else if( type_size==ply_type_size[ prop.external_type ] ) + { + prop.offset = size; + size += ply_type_size[ prop.external_type ]; } } - } /* save the size for the other_props structure */ @@ -1171,7 +798,6 @@ away within the user's structure. The user needn't be concerned for how these properties are stored. Entry: -plyfile - file identifier elem_name - name of element that we want to store other_props in offset - offset to where other_props will be stored inside user's structure @@ -1179,65 +805,35 @@ Exit: returns pointer to structure containing description of other_props ******************************************************************************/ -PlyOtherProp *ply_get_other_properties( - PlyFile *plyfile, - char *elem_name, - int offset -) +bool PlyFile::set_other_properties( const std::string &elem_name , int offset , PlyOtherProp &other ) { - int i; - PlyElement *elem; - PlyOtherProp *other; - PlyProperty *prop; - int nprops; - /* find information about the element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", - elem_name); - return (NULL); + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) + { + fprintf( stderr , "[WARNING] PlyFile::get_other_properties: Can't find element '%s'\n" , elem_name.c_str() ); + return false; } /* remember that this is the "current" element */ - plyfile->which_elem = elem; + which_elem = elem; /* save the offset to where to store the other_props */ elem->other_offset = offset; /* place the appropriate pointers, etc. in the element's property list */ - setup_other_props (elem); + setup_other_props( elem ); /* create structure for describing other_props */ - other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); - other->name = _strdup (elem_name); - other->size = elem->other_size; - other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); - - /* save descriptions of each "other" property */ - nprops = 0; - for (i = 0; i < elem->nprops; i++) { - if (elem->store_prop[i]) - continue; - prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - copy_property (prop, elem->props[i]); - other->props[nprops] = prop; - nprops++; - } - other->nprops = nprops; + other.size = elem->other_size; + other.props.reserve( elem->props.size() ); + for( int i=0 ; iprops.size() ; i++ ) if( !elem->props[i].store ) other.props.push_back( elem->props[i].prop ); /* set other_offset pointer appropriately if there are NO other properties */ - if (other->nprops == 0) { - elem->other_offset = NO_OTHER_PROPS; - } - - /* return structure */ - return (other); + if( !other.props.size() ) elem->other_offset = NO_OTHER_PROPS; + return true; } - - - /*************************/ /* Other Element Stuff */ /*************************/ @@ -1250,7 +846,6 @@ Grab all the data for an element that a user does not want to explicitly read in. Entry: -plyfile - pointer to file elem_name - name of element whose data is to be read in elem_count - number of instances of this element stored in the file @@ -1258,66 +853,34 @@ Exit: returns pointer to ALL the "other" element data for this PLY file ******************************************************************************/ -PlyOtherElems *ply_get_other_element ( - PlyFile *plyfile, - char *elem_name, - int elem_count -) +PlyOtherElems *PlyFile::get_other_element( std::string &elem_name , int elem_count ) { - int i; - PlyElement *elem; - PlyOtherElems *other_elems; - OtherElem *other; - /* look for appropriate element */ - elem = find_element (plyfile, elem_name); - if (elem == NULL) { - fprintf (stderr, - "ply_get_other_element: can't find element '%s'\n", elem_name); - exit (-1); - } + PlyElement *elem = find_element( elem_name ); + if( elem==NULL ) fprintf( stderr, "[ERROR] PlyFile::get_other_element: can't find element '%s'\n" , elem_name.c_str() ) , exit (-1); - /* create room for the new "other" element, initializing the */ - /* other data structure if necessary */ - - if (plyfile->other_elems == NULL) { - plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); - other_elems = plyfile->other_elems; - other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); - other = &(other_elems->other_list[0]); - other_elems->num_elems = 1; - } - else { - other_elems = plyfile->other_elems; - other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, - sizeof (OtherElem) * other_elems->num_elems + 1); - other = &(other_elems->other_list[other_elems->num_elems]); - other_elems->num_elems++; - } - - /* count of element instances in file */ - other->elem_count = elem_count; + if( other_elems==NULL ) other_elems = new PlyOtherElems(); + other_elems->other_list.resize( other_elems->other_list.size()+1 ); + OtherElem *other = &other_elems->other_list.back(); /* save name of element */ - other->elem_name = _strdup (elem_name); + other->elem_name = elem_name; /* create a list to hold all the current elements */ - other->other_data = (OtherData **) - malloc (sizeof (OtherData *) * other->elem_count); + other->other_data.resize( elem_count ); /* set up for getting elements */ - other->other_props = ply_get_other_properties (plyfile, elem_name, - offsetof(OtherData,other_props)); + set_other_properties( elem_name , offsetof( OtherData , other_props ) , other->other_props ); /* grab all these elements */ - for (i = 0; i < other->elem_count; i++) { + for( int i=0 ; iother_data.size() ; i++ ) + { /* grab and element from the file */ - other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); - ply_get_element (plyfile, (void *) other->other_data[i]); + get_element( (void *)&other->other_data[i] ); } /* return pointer to the other elements data */ - return (other_elems); + return other_elems; } @@ -1326,170 +889,84 @@ Pass along a pointer to "other" elements that we want to save in a given PLY file. These other elements were presumably read from another PLY file. Entry: -plyfile - file pointer in which to store this other element info other_elems - info about other elements that we want to store ******************************************************************************/ -void ply_describe_other_elements ( - PlyFile *plyfile, - PlyOtherElems *other_elems -) +void PlyFile::describe_other_elements( PlyOtherElems *other_elems ) { - int i; - OtherElem *other; - PlyElement *elem; - /* ignore this call if there is no other element */ - if (other_elems == NULL) - return; + if( other_elems==NULL ) return; /* save pointer to this information */ - plyfile->other_elems = other_elems; + this->other_elems = other_elems; /* describe the other properties of this element */ /* store them in the main element list as elements with only other properties */ - REALLOCN(plyfile->elems, PlyElement *, - plyfile->nelems, plyfile->nelems + other_elems->num_elems); - for (i = 0; i < other_elems->num_elems; i++) { - other = &(other_elems->other_list[i]); - elem = (PlyElement *) myalloc (sizeof (PlyElement)); - plyfile->elems[plyfile->nelems++] = elem; - elem->name = _strdup (other->elem_name); - elem->num = other->elem_count; - elem->nprops = 0; - ply_describe_other_properties (plyfile, other->other_props, - offsetof(OtherData,other_props)); + elems.reserve( elems.size() + other_elems->other_list.size() ); + for( int i=0 ; iother_list.size() ; i++ ) + { + PlyElement elem; + elem.name = other_elems->other_list[i].elem_name; + elem.num = (int)other_elems->other_list[i].other_data.size(); + elem.props.resize(0); + describe_other_properties( other_elems->other_list[i].other_props , offsetof( OtherData , other_props ) ); + elems.push_back( elem ); } } /****************************************************************************** Write out the "other" elements specified for this PLY file. - -Entry: -plyfile - pointer to PLY file to write out other elements for ******************************************************************************/ -void ply_put_other_elements (PlyFile *plyfile) +void PlyFile::put_other_elements( void ) { - int i,j; OtherElem *other; /* make sure we have other elements to write */ - if (plyfile->other_elems == NULL) - return; + if( other_elems==NULL ) return; /* write out the data for each "other" element */ - - for (i = 0; i < plyfile->other_elems->num_elems; i++) { - - other = &(plyfile->other_elems->other_list[i]); - ply_put_element_setup (plyfile, other->elem_name); + for( int i=0 ; iother_list.size() ; i++ ) + { + other = &(other_elems->other_list[i]); + put_element_setup( other->elem_name ); /* write out each instance of the current element */ - for (j = 0; j < other->elem_count; j++) - ply_put_element (plyfile, (void *) other->other_data[j]); + for( int j=0 ; jother_data.size() ; j++ ) put_element( (void *)&other->other_data[j] ); } } - -/****************************************************************************** -Free up storage used by an "other" elements data structure. - -Entry: -other_elems - data structure to free up -******************************************************************************/ - -void ply_free_other_elements (PlyOtherElems *other_elems) -{ - other_elems = other_elems; -} - - - /*******************/ /* Miscellaneous */ /*******************/ - - -/****************************************************************************** -Close a PLY file. - -Entry: -plyfile - identifier of file to close -******************************************************************************/ - -void ply_close(PlyFile *plyfile) -{ - fclose (plyfile->fp); - - /* free up memory associated with the PLY file */ - free (plyfile); -} - - /****************************************************************************** Get version number and file type of a PlyFile. -Entry: -ply - pointer to PLY file - Exit: version - version of the file file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE ******************************************************************************/ -void ply_get_info(PlyFile *ply, float *version, int *file_type) -{ - if (ply == NULL) - return; - - *version = ply->version; - *file_type = ply->file_type; -} - - -/****************************************************************************** -Compare two strings. Returns 1 if they are the same, 0 if not. -******************************************************************************/ - -int equal_strings(const char *s1, const char *s2) -{ - - while (*s1 && *s2) - if (*s1++ != *s2++) - return (0); - - if (*s1 != *s2) - return (0); - else - return (1); -} - +void PlyFile::get_info( float &version, int &file_type ){ version = this->version , file_type = this->file_type; } /****************************************************************************** Find an element from the element list of a given PLY object. Entry: -plyfile - file id for PLY file element - name of element we're looking for Exit: returns the element, or NULL if not found ******************************************************************************/ -PlyElement *find_element(PlyFile *plyfile, const char *element) +PlyElement *PlyFile::find_element( const std::string &element ) { - int i; - - for (i = 0; i < plyfile->nelems; i++) - if (equal_strings (element, plyfile->elems[i]->name)) - return (plyfile->elems[i]); - - return (NULL); + for( int i=0 ; inprops; i++) - if (equal_strings (prop_name, elem->props[i]->name)) { - *index = i; - return (elem->props[i]); - } - - *index = -1; - return (NULL); + for( int i=0 ; i words; PlyElement *elem; - PlyProperty *prop; - char **words; - int nwords; int which_word; char *elem_data,*item=NULL; char *item_ptr; @@ -1550,94 +1019,86 @@ void ascii_get_element(PlyFile *plyfile, char *elem_ptr) int other_flag; /* the kind of element we're reading currently */ - elem = plyfile->which_elem; + elem = which_elem; /* do we need to setup for other_props? */ - - if (elem->other_offset != NO_OTHER_PROPS) { + if( elem->other_offset!=NO_OTHER_PROPS ) + { char **ptr; other_flag = 1; /* make room for other_props */ - other_data = (char *) myalloc (elem->other_size); + other_data = (char *)malloc( elem->other_size ); /* store pointer in user's structure to the other_props */ ptr = (char **) (elem_ptr + elem->other_offset); *ptr = other_data; } - else - other_flag = 0; + else other_flag = 0; /* read in the element */ - - words = get_words (plyfile->fp, &nwords, &orig_line); - if (words == NULL) { - fprintf (stderr, "ply_get_element: unexpected end of file\n"); - exit (-1); - } + words = get_words( fp , &orig_line ); + if( !words.size() ) fprintf( stderr , "[ERROR] PlyFile::get_element: unexpected end of file\n" ) , exit(-1); which_word = 0; - for (j = 0; j < elem->nprops; j++) { - - prop = elem->props[j]; - store_it = (elem->store_prop[j] | other_flag); + for( int j=0 ; jprops.size() ; j++ ) + { + PlyProperty &prop = elem->props[j].prop; + store_it = (elem->props[j].store | other_flag); /* store either in the user's structure or in other_props */ - if (elem->store_prop[j]) - elem_data = elem_ptr; - else - elem_data = other_data; + if( elem->props[j].store ) elem_data = elem_ptr; + else elem_data = other_data; - if (prop->is_list) { /* a list */ - - /* get and store the number of items in the list */ - get_ascii_item (words[which_word++], prop->count_external, - &int_val, &uint_val, &double_val); - if (store_it) { - item = elem_data + prop->count_offset; - store_item(item, prop->count_internal, int_val, uint_val, double_val); + if( prop.is_list ) /* a list */ + { + /* get and store the number of items in the list */ + get_ascii_item( words[which_word++] , prop.count_external , int_val , uint_val , double_val ); + if( store_it ) + { + item = elem_data + prop.count_offset; + store_item( item , prop.count_internal , int_val , uint_val , double_val ); } /* allocate space for an array of items and store a ptr to the array */ list_count = int_val; - item_size = ply_type_size[prop->internal_type]; - store_array = (char **) (elem_data + prop->offset); + item_size = ply_type_size[ prop.internal_type ]; + store_array = (char **)( elem_data + prop.offset ); - if (list_count == 0) { - if (store_it) - *store_array = NULL; + if( list_count==0 ) + { + if( store_it ) *store_array = NULL; } - else { - if (store_it) { - item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + else + { + if( store_it ) + { + item_ptr = (char *) malloc (sizeof (char) * item_size * list_count); item = item_ptr; *store_array = item_ptr; } /* read items and store them into the array */ - for (k = 0; k < list_count; k++) { - get_ascii_item (words[which_word++], prop->external_type, - &int_val, &uint_val, &double_val); - if (store_it) { - store_item (item, prop->internal_type, - int_val, uint_val, double_val); + for( int k=0 ; kexternal_type, - &int_val, &uint_val, &double_val); - if (store_it) { - item = elem_data + prop->offset; - store_item (item, prop->internal_type, int_val, uint_val, double_val); + else /* not a list */ + { + get_ascii_item( words[which_word++] , prop.external_type , int_val , uint_val , double_val ); + if( store_it ) + { + item = elem_data + prop.offset; + store_item( item , prop.internal_type , int_val , uint_val , double_val ); } } - } - - free (words); } @@ -1645,16 +1106,12 @@ void ascii_get_element(PlyFile *plyfile, char *elem_ptr) Read an element from a binary file. Entry: -plyfile - file identifier elem_ptr - pointer to an element ******************************************************************************/ -void binary_get_element(PlyFile *plyfile, char *elem_ptr) +void PlyFile::_binary_get_element( char *elem_ptr ) { - int j,k; PlyElement *elem; - PlyProperty *prop; - FILE *fp = plyfile->fp; char *elem_data,*item=NULL; char *item_ptr; int item_size; @@ -1668,15 +1125,15 @@ void binary_get_element(PlyFile *plyfile, char *elem_ptr) int other_flag; /* the kind of element we're reading currently */ - elem = plyfile->which_elem; + elem = which_elem; /* do we need to setup for other_props? */ - - if (elem->other_offset != NO_OTHER_PROPS) { + if( elem->other_offset!=NO_OTHER_PROPS ) + { char **ptr; other_flag = 1; /* make room for other_props */ - other_data = (char *) myalloc (elem->other_size); + other_data = (char *) malloc (elem->other_size); /* store pointer in user's structure to the other_props */ ptr = (char **) (elem_ptr + elem->other_offset); *ptr = other_data; @@ -1686,64 +1143,63 @@ void binary_get_element(PlyFile *plyfile, char *elem_ptr) /* read in a number of elements */ - for (j = 0; j < elem->nprops; j++) { - - prop = elem->props[j]; - store_it = (elem->store_prop[j] | other_flag); + for( int j=0 ; jprops.size() ; j++ ) + { + PlyProperty &prop = elem->props[j].prop; + store_it = ( elem->props[j].store | other_flag ); /* store either in the user's structure or in other_props */ - if (elem->store_prop[j]) - elem_data = elem_ptr; - else - elem_data = other_data; + if( elem->props[j].store ) elem_data = elem_ptr; + else elem_data = other_data; - if (prop->is_list) { /* a list */ - - /* get and store the number of items in the list */ - get_binary_item (fp, plyfile->file_type, prop->count_external, - &int_val, &uint_val, &double_val); - if (store_it) { - item = elem_data + prop->count_offset; - store_item(item, prop->count_internal, int_val, uint_val, double_val); + if( prop.is_list ) /* a list */ + { + /* get and store the number of items in the list */ + get_binary_item( fp , file_type , prop.count_external , int_val, uint_val , double_val ); + if( store_it ) + { + item = elem_data + prop.count_offset; + store_item( item , prop.count_internal , int_val , uint_val , double_val ); } /* allocate space for an array of items and store a ptr to the array */ list_count = int_val; - item_size = ply_type_size[prop->internal_type]; - store_array = (char **) (elem_data + prop->offset); - if (list_count == 0) { - if (store_it) - *store_array = NULL; + item_size = ply_type_size[ prop.internal_type ]; + store_array = (char **) (elem_data + prop.offset); + if( list_count==0 ) + { + if( store_it ) *store_array = NULL; } - else { - if (store_it) { - item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + else + { + if( store_it ) + { + item_ptr = (char *)malloc(sizeof (char) * item_size * list_count); item = item_ptr; *store_array = item_ptr; } /* read items and store them into the array */ - for (k = 0; k < list_count; k++) { - get_binary_item (fp, plyfile->file_type, prop->external_type, - &int_val, &uint_val, &double_val); - if (store_it) { - store_item (item, prop->internal_type, - int_val, uint_val, double_val); + for( int k=0 ; kfile_type, prop->external_type, - &int_val, &uint_val, &double_val); - if (store_it) { - item = elem_data + prop->offset; - store_item (item, prop->internal_type, int_val, uint_val, double_val); + else /* not a list */ + { + get_binary_item( fp , file_type , prop.external_type , int_val , uint_val , double_val ); + if( store_it ) + { + item = elem_data + prop.offset; + store_item( item , prop.internal_type , int_val , uint_val , double_val ); } } - } } @@ -1859,26 +1315,23 @@ orig_line - the original line of characters returns a list of words from the line, or NULL if end-of-file ******************************************************************************/ -char **get_words(FILE *fp, int *nwords, char **orig_line) +std::vector< std::string > get_words( FILE *fp , char **orig_line ) { #define BIG_STRING 4096 static char str[BIG_STRING]; static char str_copy[BIG_STRING]; - char **words; + std::vector< std::string > words; int max_words = 10; int num_words = 0; - char *ptr,*ptr2; + char *ptr , *ptr2; char *result; - words = (char **) myalloc (sizeof (char *) * max_words); - /* read in a line */ - result = fgets (str, BIG_STRING, fp); - if (result == NULL) { - free(words); - *nwords = 0; + result = fgets( str , BIG_STRING , fp ); + if( result==NULL ) + { *orig_line = NULL; - return (NULL); + return words; } /* convert line-feed and tabs into spaces */ /* (this guarentees that there will be a space before the */ @@ -1887,14 +1340,17 @@ char **get_words(FILE *fp, int *nwords, char **orig_line) str[BIG_STRING-2] = ' '; str[BIG_STRING-1] = '\0'; - for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { + for( ptr=str , ptr2=str_copy ; *ptr!='\0' ; ptr++ , ptr2++ ) + { *ptr2 = *ptr; // Added line here to manage carriage returns - if (*ptr == '\t' || *ptr == '\r') { + if( *ptr == '\t' || *ptr == '\r' ) + { *ptr = ' '; *ptr2 = ' '; } - else if (*ptr == '\n') { + else if( *ptr=='\n' ) + { *ptr = ' '; *ptr2 = '\0'; break; @@ -1904,38 +1360,31 @@ char **get_words(FILE *fp, int *nwords, char **orig_line) /* find the words in the line */ ptr = str; - while (*ptr != '\0') { - + while( *ptr!='\0' ) + { /* jump over leading spaces */ - while (*ptr == ' ') - ptr++; + while( *ptr==' ' ) ptr++; /* break if we reach the end */ - if (*ptr == '\0') - break; + if( *ptr=='\0' ) break; - /* save pointer to beginning of word */ - if (num_words >= max_words) { - max_words += 10; - words = (char **) realloc (words, sizeof (char *) * max_words); - } - words[num_words++] = ptr; + char *_ptr = ptr; /* jump over non-spaces */ - while (*ptr != ' ') - ptr++; + while( *ptr!=' ' ) ptr++; /* place a null character here to mark the end of the word */ *ptr++ = '\0'; + + /* save pointer to beginning of word */ + words.push_back( _ptr ); } /* return the list of words */ - *nwords = num_words; *orig_line = str_copy; - return (words); + return words; } - /****************************************************************************** Return the value of an item, given a pointer to it and its type. @@ -2249,70 +1698,63 @@ uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ -void get_stored_item( - void *ptr, - int type, - int *int_val, - unsigned int *uint_val, - double *double_val -) +void get_stored_item( void *ptr , int type , int &int_val , unsigned int &uint_val , double &double_val ) { - switch (type) { + switch( type ) + { case PLY_CHAR: case PLY_INT_8: - *int_val = *((char *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((char *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_UCHAR: case PLY_UINT_8: - *uint_val = *((unsigned char *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned char *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_SHORT: case PLY_INT_16: - *int_val = *((short int *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((short int *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_USHORT: case PLY_UINT_16: - *uint_val = *((unsigned short int *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned short int *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_INT: case PLY_INT_32: - *int_val = *((int *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((int *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_UINT: case PLY_UINT_32: - *uint_val = *((unsigned int *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned int *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_FLOAT: case PLY_FLOAT_32: - *double_val = *((float *) ptr); - *int_val = (int) *double_val; - *uint_val = (unsigned int) *double_val; + double_val = *((float *) ptr); + int_val = (int)double_val; + uint_val = (unsigned int)double_val; break; case PLY_DOUBLE: case PLY_FLOAT_64: - *double_val = *((double *) ptr); - *int_val = (int) *double_val; - *uint_val = (unsigned int) *double_val; + double_val = *((double *) ptr); + int_val = (int)double_val; + uint_val = (unsigned int)double_val; break; default: - fprintf (stderr, "get_stored_item: bad type = %d\n", type); - exit (-1); + fprintf( stderr , "[ERROR] get_stored_item: bad type = %d\n" , type) ; exit(-1); } } - /****************************************************************************** Get the value of an item from a binary file, and place the result into an integer, an unsigned integer and a double. @@ -2327,84 +1769,71 @@ uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ -void get_binary_item( - FILE *fp, - int file_type, - int type, - int *int_val, - unsigned int *uint_val, - double *double_val -) +void get_binary_item( FILE *fp , int file_type , int type , int &int_val , unsigned int &uint_val , double &double_val ) { char c[8]; void *ptr; - ptr = (void *) c; + ptr = ( void * )c; - if (fread (ptr, ply_type_size[type], 1, fp) != 1) + if( fread( ptr , ply_type_size[type] , 1 , fp )!=1 ) fprintf( stderr, "[ERROR] get_binary_item: fread() failed -- aborting.\n" ) , exit(1); + if( ( file_type!=native_binary_type ) && ( ply_type_size[type]>1 ) ) swap_bytes( (char *)ptr , ply_type_size[type] ); + + switch( type ) { - fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n"); - exit(1); - } - if ((file_type != native_binary_type) && (ply_type_size[type] > 1)) - swap_bytes((char *)ptr, ply_type_size[type]); - - switch (type) { case PLY_CHAR: case PLY_INT_8: - *int_val = *((char *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((char *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_UCHAR: case PLY_UINT_8: - *uint_val = *((unsigned char *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned char *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_SHORT: case PLY_INT_16: - *int_val = *((short int *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((short int *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_USHORT: case PLY_UINT_16: - *uint_val = *((unsigned short int *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned short int *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_INT: case PLY_INT_32: - *int_val = *((int *) ptr); - *uint_val = *int_val; - *double_val = *int_val; + int_val = *((int *) ptr); + uint_val = int_val; + double_val = int_val; break; case PLY_UINT: case PLY_UINT_32: - *uint_val = *((unsigned int *) ptr); - *int_val = *uint_val; - *double_val = *uint_val; + uint_val = *((unsigned int *) ptr); + int_val = uint_val; + double_val = uint_val; break; case PLY_FLOAT: case PLY_FLOAT_32: - *double_val = *((float *) ptr); - *int_val = (int) *double_val; - *uint_val = (unsigned int) *double_val; + double_val = *((float *) ptr); + int_val = (int)double_val; + uint_val = (unsigned int)double_val; break; case PLY_DOUBLE: case PLY_FLOAT_64: - *double_val = *((double *) ptr); - *int_val = (int) *double_val; - *uint_val = (unsigned int) *double_val; + double_val = *((double *) ptr); + int_val = (int)double_val; + uint_val = (unsigned int)double_val; break; default: - fprintf (stderr, "get_binary_item: bad type = %d\n", type); - exit (-1); + fprintf( stderr , "[ERROR] get_binary_item: bad type = %d\n" , type ) , exit(-1); } } - /****************************************************************************** Extract the value of an item from an ascii word, and place the result into an integer, an unsigned integer and a double. @@ -2418,16 +1847,10 @@ int_val - integer value uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ - -void get_ascii_item( - char *word, - int type, - int *int_val, - unsigned int *uint_val, - double *double_val -) +void get_ascii_item( const std::string &word , int type , int &int_val , unsigned int &uint_val , double &double_val ) { - switch (type) { + switch( type ) + { case PLY_CHAR: case PLY_INT_8: case PLY_UCHAR: @@ -2438,34 +1861,30 @@ void get_ascii_item( case PLY_UINT_16: case PLY_INT: case PLY_INT_32: - *int_val = atoi (word); - *uint_val = (unsigned int) *int_val; - *double_val = (double) *int_val; + int_val = atoi( word.c_str() ); + uint_val = (unsigned int)int_val; + double_val = (double)int_val; break; case PLY_UINT: case PLY_UINT_32: - *uint_val = strtol (word, (char **) NULL, 10); - *int_val = (int) *uint_val; - *double_val = (double) *uint_val; + uint_val = strtol( word.c_str() , (char **)NULL , 10 ); + int_val = (int)uint_val; + double_val = (double)uint_val; break; case PLY_FLOAT: case PLY_FLOAT_32: case PLY_DOUBLE: case PLY_FLOAT_64: - *double_val = atof (word); - *int_val = (int) *double_val; - *uint_val = (unsigned int) *double_val; + double_val = atof( word.c_str() ); + int_val = (int)double_val; + uint_val = (unsigned int)double_val; break; - - default: - fprintf (stderr, "get_ascii_item: bad type = %d\n", type); - exit (-1); + default: fprintf( stderr, "[ERROR] get_ascii_item: bad type = %d\n" , type ) , exit(-1); } } - /****************************************************************************** Store a value into a place being pointed to, guided by a data type. @@ -2553,29 +1972,19 @@ words - list of words describing the element nwords - number of words in the list ******************************************************************************/ -void add_element (PlyFile *plyfile, char **words) +void PlyFile::add_element( const std::vector< std::string > &words ) { - PlyElement *elem; + PlyElement elem; - /* create the new element */ - elem = (PlyElement *) myalloc (sizeof (PlyElement)); - elem->name = _strdup (words[1]); - elem->num = atoi (words[2]); - elem->nprops = 0; - - /* make room for new element in the object's list of elements */ - if (plyfile->nelems == 0) - plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); - else - plyfile->elems = (PlyElement **) realloc (plyfile->elems, - sizeof (PlyElement *) * (plyfile->nelems + 1)); + /* set the new element */ + elem.name = words[1]; + elem.num = atoi( words[2].c_str() ); + elem.props.resize(0); /* add the new element to the object's list */ - plyfile->elems[plyfile->nelems] = elem; - plyfile->nelems++; + elems.push_back( elem ); } - /****************************************************************************** Return the type of a property, given the name of the property. @@ -2586,19 +1995,14 @@ Exit: returns integer code for property, or 0 if not found ******************************************************************************/ -int get_prop_type(char *type_name) +int get_prop_type( const std::string &type_name ) { - int i; - - for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++) - if (equal_strings (type_name, type_names[i])) - return (i); + for( int i=PLY_START_TYPE+1 ; i &words ) { - PlyProperty *prop; - PlyElement *elem; - - /* create the new property */ - - prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - - if (equal_strings (words[1], "list")) { /* is a list */ - prop->count_external = get_prop_type (words[2]); - prop->external_type = get_prop_type (words[3]); - prop->name = _strdup (words[4]); - prop->is_list = 1; + PlyProperty prop; + if( words[1]=="list" ) /* is a list */ + { + prop.count_external = get_prop_type( words[2] ); + prop.external_type = get_prop_type( words[3]) ; + prop.name = words[4]; + prop.is_list = 1; } - else { /* not a list */ - prop->external_type = get_prop_type (words[1]); - prop->name = _strdup (words[2]); - prop->is_list = 0; + else /* not a list */ + { + prop.external_type = get_prop_type( words[1] ); + prop.name = words[2]; + prop.is_list = 0; } /* add this property to the list of properties of the current element */ - - elem = plyfile->elems[plyfile->nelems - 1]; - - if (elem->nprops == 0) - elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); - else - elem->props = (PlyProperty **) realloc (elem->props, - sizeof (PlyProperty *) * (elem->nprops + 1)); - - elem->props[elem->nprops] = prop; - elem->nprops++; + elems.back().props.push_back( PlyStoredProperty( prop , DONT_STORE_PROP ) ); } @@ -2652,16 +2042,13 @@ plyfile - PLY file descriptor line - line containing comment ******************************************************************************/ -void add_comment (PlyFile *plyfile, char *line) +void PlyFile::add_comment( const std::string &line ) { - int i; - /* skip over "comment" and leading spaces and tabs */ - i = 7; - while (line[i] == ' ' || line[i] == '\t') - i++; + int i = 7; + while( line[i]==' ' || line[i] =='\t' ) i++; - ply_put_comment (plyfile, &line[i]); + put_comment( line.substr(i) ); } @@ -2673,56 +2060,10 @@ plyfile - PLY file descriptor line - line containing text info ******************************************************************************/ -void add_obj_info (PlyFile *plyfile, char *line) +void PlyFile::add_obj_info( const std::string &line ) { - int i; - /* skip over "obj_info" and leading spaces and tabs */ - i = 8; - while (line[i] == ' ' || line[i] == '\t') - i++; - - ply_put_obj_info (plyfile, &line[i]); + int i = 8; + while( line[i]==' ' || line[i]=='\t' ) i++; + put_obj_info( line.substr(i) ); } - - -/****************************************************************************** -Copy a property. -******************************************************************************/ - -void copy_property(PlyProperty *dest, const PlyProperty *src) -{ - dest->name = _strdup (src->name); - dest->external_type = src->external_type; - dest->internal_type = src->internal_type; - dest->offset = src->offset; - - dest->is_list = src->is_list; - dest->count_external = src->count_external; - dest->count_internal = src->count_internal; - dest->count_offset = src->count_offset; -} - - -/****************************************************************************** -Allocate some memory. - -Entry: -size - amount of memory requested (in bytes) -lnum - line number from which memory was requested -fname - file name from which memory was requested -******************************************************************************/ - -char *my_alloc(int size, int lnum, const char *fname) -{ - char *ptr; - - ptr = (char *) malloc (size); - - if (ptr == 0) { - fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); - } - - return (ptr); -} - diff --git a/Src/PlyFile.h b/Src/PlyFile.h index 5d40dfa..bce993f 100644 --- a/Src/PlyFile.h +++ b/Src/PlyFile.h @@ -1,62 +1,57 @@ /* - Header for PLY polygon files. - - - Greg Turk, March 1994 - - A PLY file contains a single polygonal _object_. - - An object is composed of lists of _elements_. Typical elements are - vertices, faces, edges and materials. - - Each type of element for a given object has one or more _properties_ - associated with the element type. For instance, a vertex element may - have as properties three floating-point values x,y,z and three unsigned - chars for red, green and blue. - - --------------------------------------------------------------- - - Copyright (c) 1994 The Board of Trustees of The Leland Stanford - Junior University. All rights reserved. - - Permission to use, copy, modify and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that the above copyright notice and this permission notice appear in - all copies of this software and that you do not sell the software. - - THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, - EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - -*/ +Header for PLY polygon files. +- Greg Turk, March 1994 + +A PLY file contains a single polygonal _object_. + +An object is composed of lists of _elements_. Typical elements are +vertices, faces, edges and materials. + +Each type of element for a given object has one or more _properties_ +associated with the element type. For instance, a vertex element may +have as properties three floating-point values x,y,z and three unsigned +chars for red, green and blue. + +--------------------------------------------------------------- + +Copyright (c) 1994 The Board of Trustees of The Leland Stanford +Junior University. All rights reserved. + +Permission to use, copy, modify and distribute this software and its +documentation for any purpose is hereby granted without fee, provided +that the above copyright notice and this permission notice appear in +all copies of this software and that you do not sell the software. + +THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, +EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY +WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +*/ #ifndef __PLY_FILE_H__ #define __PLY_FILE_H__ -#ifndef WIN32 -#define _strdup strdup -#endif +#define MISHA_PLY + +#include +#include -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include #include - + #define PLY_ASCII 1 /* ascii PLY file */ #define PLY_BINARY_BE 2 /* binary PLY file, big endian */ #define PLY_BINARY_LE 3 /* binary PLY file, little endian */ #define PLY_BINARY_NATIVE 4 /* binary PLY file, same endianness as current architecture */ - + #define PLY_OKAY 0 /* ply routine worked okay */ #define PLY_ERROR -1 /* error in ply routine */ - + /* scalar data types supported by PLY format */ - + #define PLY_START_TYPE 0 #define PLY_CHAR 1 #define PLY_SHORT 2 @@ -74,147 +69,130 @@ extern "C" { #define PLY_UINT_32 14 #define PLY_FLOAT_32 15 #define PLY_FLOAT_64 16 - + #define PLY_END_TYPE 17 - + #define PLY_SCALAR 0 #define PLY_LIST 1 - + #define PLY_STRIP_COMMENT_HEADER 0 -typedef struct PlyProperty { /* description of a property */ - char *name; /* property name */ +/* description of a property */ +struct PlyProperty +{ + std::string name; /* property name */ int external_type; /* file's data type */ int internal_type; /* program's data type */ int offset; /* offset bytes of prop in a struct */ - + int is_list; /* 1 = list, 0 = scalar */ int count_external; /* file's count type */ int count_internal; /* program's count type */ int count_offset; /* offset byte for list count */ -} -PlyProperty; -typedef struct PlyElement { /* description of an element */ - char *name; /* element name */ + PlyProperty( const std::string &n , int et , int it , int o , int il=0 , int ce=0 , int ci=0 , int co=0 ) : name(n) , external_type(et) , internal_type(it) , offset(o) , is_list(il) , count_external(ce) , count_internal(ci) , count_offset(co){ } + PlyProperty( const std::string &n ) : PlyProperty( n , 0 , 0 , 0 , 0 , 0 , 0 , 0 ){ } + PlyProperty( void ) : external_type(0) , internal_type(0) , offset(0) , is_list(0) , count_external(0) , count_internal(0) , count_offset(0){ } +}; + +struct PlyStoredProperty +{ + PlyProperty prop ; char store; + PlyStoredProperty( void ){ } + PlyStoredProperty( const PlyProperty &p , char s ) : prop(p) , store(s){ } +}; + +/* description of an element */ +struct PlyElement +{ + std::string name; /* element name */ int num; /* number of elements in this object */ int size; /* size of element (bytes) or -1 if variable */ - int nprops; /* number of properties for this element */ - PlyProperty **props; /* list of properties in the file */ - char *store_prop; /* flags: property wanted by user? */ + std::vector< PlyStoredProperty > props; /* list of properties in the file */ int other_offset; /* offset to un-asked-for props, or -1 if none*/ int other_size; /* size of other_props structure */ -} PlyElement; + PlyProperty *find_property( const std::string &prop_name , int &index ); +}; -typedef struct PlyOtherProp { /* describes other properties in an element */ - char *name; /* element name */ - int size; /* size of other_props */ - int nprops; /* number of properties in other_props */ - PlyProperty **props; /* list of properties in other_props */ -} PlyOtherProp; +/* describes other properties in an element */ +struct PlyOtherProp +{ + std::string name; /* element name */ + int size; /* size of other_props */ + std::vector< PlyProperty > props; /* list of properties in other_props */ +}; -typedef struct OtherData { /* for storing other_props for an other element */ +/* storing other_props for an other element */ +struct OtherData +{ void *other_props; -} OtherData; + OtherData( void ) : other_props(NULL){ } + ~OtherData( void ){ if( other_props ) free( other_props ); } +}; -typedef struct OtherElem { /* data for one "other" element */ - char *elem_name; /* names of other elements */ - int elem_count; /* count of instances of each element */ - OtherData **other_data; /* actual property data for the elements */ - PlyOtherProp *other_props; /* description of the property data */ -} OtherElem; +/* data for one "other" element */ +struct OtherElem +{ + std::string elem_name; /* names of other elements */ + std::vector< OtherData > other_data; /* actual property data for the elements */ + PlyOtherProp other_props; /* description of the property data */ +}; -typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */ - int num_elems; /* number of other elements */ - OtherElem *other_list; /* list of data for other elements */ -} PlyOtherElems; +/* "other" elements, not interpreted by user */ +struct PlyOtherElems +{ + std::vector< OtherElem > other_list; /* list of data for other elements */ +}; -typedef struct PlyFile { /* description of PLY file */ - FILE *fp; /* file pointer */ - int file_type; /* ascii or binary */ - float version; /* version number of file */ - int nelems; /* number of elements of object */ - PlyElement **elems; /* list of elements */ - int num_comments; /* number of comments */ - char **comments; /* list of comments */ - int num_obj_info; /* number of items of object information */ - char **obj_info; /* list of object info items */ - PlyElement *which_elem; /* which element we're currently writing */ - PlyOtherElems *other_elems; /* "other" elements from a PLY file */ -} PlyFile; - - /* memory allocation */ -extern char *my_alloc(); -#define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__) +/* description of PLY file */ +struct PlyFile +{ + FILE *fp; /* file pointer */ + int file_type; /* ascii or binary */ + float version; /* version number of file */ + std::vector< PlyElement > elems; /* list of elements of object */ + std::vector< std::string > comments; /* list of comments */ + std::vector< std::string > obj_info; /* list of object info items */ + PlyElement *which_elem; /* which element we're currently writing */ + PlyOtherElems *other_elems; /* "other" elements from a PLY file */ -#ifndef ALLOCN -#define REALLOCN(PTR,TYPE,OLD_N,NEW_N) \ -{ \ - if ((OLD_N) == 0) \ -{ ALLOCN((PTR),TYPE,(NEW_N));} \ - else \ -{ \ - (PTR) = (TYPE *)realloc((PTR),(NEW_N)*sizeof(TYPE)); \ - if (((PTR) == NULL) && ((NEW_N) != 0)) \ -{ \ - fprintf(stderr, "Memory reallocation failed on line %d in %s\n", \ - __LINE__, __FILE__); \ - fprintf(stderr, " tried to reallocate %d->%d\n", \ - (OLD_N), (NEW_N)); \ - exit(-1); \ -} \ - if ((NEW_N)>(OLD_N)) \ - memset((char *)(PTR)+(OLD_N)*sizeof(TYPE), 0, \ - ((NEW_N)-(OLD_N))*sizeof(TYPE)); \ -} \ -} + static PlyFile *Write( const std::string & , const std::vector< std::string > & , int , float & ); + static PlyFile *Read ( const std::string & , std::vector< std::string > & , int & , float & ); -#define ALLOCN(PTR,TYPE,N) \ -{ (PTR) = (TYPE *) calloc(((unsigned)(N)),sizeof(TYPE));\ - if ((PTR) == NULL) { \ - fprintf(stderr, "Memory allocation failed on line %d in %s\n", \ - __LINE__, __FILE__); \ - exit(-1); \ - } \ -} + PlyFile( FILE *f ) : fp(f) , other_elems(NULL) , version(1.) { } + ~PlyFile( void ){ if( fp ) fclose(fp) ; if(other_elems) delete other_elems; } + void describe_element ( const std::string & , int , int , const PlyProperty * ); + void describe_property( const std::string & , const PlyProperty * ); + void describe_other_elements( PlyOtherElems * ); + PlyElement *find_element( const std::string & ); + void element_count( const std::string & , int ); + void header_complete( void ); + void put_element_setup( const std::string & ); + void put_element ( void * ); + void put_comment ( const std::string & ); + void put_obj_info( const std::string & ); + void put_other_elements( void ); + void add_element ( const std::vector< std::string > & ); + void add_property( const std::vector< std::string > & ); + void add_comment ( const std::string & ); + void add_obj_info( const std::string & ); -#define FREE(PTR) { free((PTR)); (PTR) = NULL; } -#endif + std::vector< PlyProperty * > get_element_description( const std::string & , int & ); + void get_element_setup( const std::string & , int , PlyProperty * ); + int get_property( const std::string & , const PlyProperty * ); + void describe_other_properties( const PlyOtherProp & , int ); + bool set_other_properties( const std::string & , int , PlyOtherProp & ); + void get_element( void * ); + std::vector< std::string > &get_comments( void ); + std::vector< std::string > &get_obj_info( void ); + void get_info( float & , int & ); + PlyOtherElems *get_other_element( std::string & , int ); +protected: + void _ascii_get_element ( char * ); + void _binary_get_element( char * ); + static PlyFile *_Write( FILE * , const std::vector< std::string > & , int ); + static PlyFile *_Read ( FILE * , std::vector< std::string > & ); +}; - -/*** delcaration of routines ***/ - -extern PlyFile *ply_write(FILE *, int, const char **, int); -extern PlyFile *ply_open_for_writing( const char *, int, const char **, int, float *); -extern void ply_describe_element(PlyFile *, char *, int, int, PlyProperty *); -extern void ply_describe_property(PlyFile *, const char *, const PlyProperty *); -extern void ply_element_count(PlyFile *, const char *, int); -extern void ply_header_complete(PlyFile *); -extern void ply_put_element_setup(PlyFile *, const char *); -extern void ply_put_element(PlyFile *, void *); -extern void ply_put_comment(PlyFile *, char *); -extern void ply_put_obj_info(PlyFile *, char *); -extern PlyFile *ply_read(FILE *, int *, char ***); -extern PlyFile *ply_open_for_reading( const char *, int *, char ***, int *, float *); -extern PlyProperty **ply_get_element_description(PlyFile *, char *, int*, int*); -extern void ply_get_element_setup( PlyFile *, char *, int, PlyProperty *); -extern int ply_get_property(PlyFile *, char *, const PlyProperty *); -extern PlyOtherProp *ply_get_other_properties(PlyFile *, char *, int); -extern void ply_get_element(PlyFile *, void *); -extern char **ply_get_comments(PlyFile *, int *); -extern char **ply_get_obj_info(PlyFile *, int *); -extern void ply_close(PlyFile *); -extern void ply_get_info(PlyFile *, float *, int *); -extern PlyOtherElems *ply_get_other_element (PlyFile *, char *, int); -extern void ply_describe_other_elements ( PlyFile *, PlyOtherElems *); -extern void ply_put_other_elements (PlyFile *); -extern void ply_free_other_elements (PlyOtherElems *); -extern void ply_describe_other_properties(PlyFile *, PlyOtherProp *, int); - -extern int equal_strings(const char *, const char *); - -#ifdef __cplusplus -} -#endif #endif /* !__PLY_FILE_H__ */ diff --git a/Src/PointStream.h b/Src/PointStream.h index 44d1d02..9abf464 100644 --- a/Src/PointStream.h +++ b/Src/PointStream.h @@ -286,8 +286,7 @@ class PLYInputPointStream : public InputPointStream< Real , Dim > { char* _fileName; PlyFile* _ply; - int _nr_elems; - char **_elist; + std::vector< std::string > _elist; int _pCount , _pIdx; void _free( void ); @@ -304,8 +303,7 @@ class PLYInputPointStreamWithData : public InputPointStreamWithData< Real , Dim struct _PlyVertexWithData : public PlyVertex< Real , Dim > { Data data; }; char* _fileName; PlyFile* _ply; - int _nr_elems; - char **_elist; + std::vector< std::string > _elist; PlyProperty* _dataProperties; int _dataPropertiesCount; bool (*_validationFunction)( const bool* ); diff --git a/Src/PointStream.inl b/Src/PointStream.inl index 93bd511..6fbf118 100644 --- a/Src/PointStream.inl +++ b/Src/PointStream.inl @@ -133,44 +133,38 @@ void PLYInputPointStream< Real , Dim >::reset( void ) { int fileType; float version; - PlyProperty** plist; + std::vector< PlyProperty * > plist; if( _ply ) _free(); - _ply = ply_open_for_reading( _fileName, &_nr_elems, &_elist, &fileType, &version ); + _ply = PlyFile::Read( _fileName, _elist, fileType, version ); if( !_ply ) { fprintf( stderr, "[ERROR] Failed to open ply file for reading: %s\n" , _fileName ); exit( 0 ); } bool foundVertices = false; - for( int i=0 ; i<_nr_elems ; i++ ) + for( int i=0 ; i<_elist.size() ; i++ ) { int num_elems; - int nr_props; - char* elem_name = _elist[i]; - plist = ply_get_element_description( _ply , elem_name , &num_elems , &nr_props ); - if( !plist ) + std::string &elem_name = _elist[i]; + plist = _ply->get_element_description( elem_name , num_elems ); + if( !plist.size() ) { fprintf( stderr , "[ERROR] Failed to get element description: %s\n" , elem_name ); exit( 0 ); } - if( equal_strings( "vertex" , elem_name ) ) + if( elem_name=="vertex" , elem_name ) { foundVertices = true; _pCount = num_elems , _pIdx = 0; for( int i=0 ; i::ReadComponents ; i++ ) - if( !ply_get_property( _ply , elem_name , &(PlyVertex< Real , Dim >::Properties()[i]) ) ) + if( !_ply->get_property( elem_name , &(PlyVertex< Real , Dim >::Properties()[i]) ) ) { fprintf( stderr , "[ERROR] Failed to find property in ply file: %s\n" , PlyVertex< Real , Dim >::Properties()[i].name ); exit( 0 ); } } - for( int j=0 ; jname ); - free( plist[j] ); - } - free( plist ); + for( int j=0 ; j::reset( void ) } } template< class Real , int Dim > -void PLYInputPointStream< Real , Dim >::_free( void ) -{ - if( _ply->comments ) - { - for( int i=0 ; i<_ply->num_comments ; i++ ) free( _ply->comments[i] ); - free( _ply->comments ); - } - if( _ply->obj_info ) - { - for( int i=0 ; i<_ply->num_obj_info ; i++ ) free( _ply->obj_info[i] ); - free( _ply->obj_info ); - } - if( _ply ) ply_close( _ply ) , _ply = NULL; - if( _elist ) - { - for( int i=0 ; i<_nr_elems ; i++ ) free( _elist[i] ); - free( _elist ); - } -} +void PLYInputPointStream< Real , Dim >::_free( void ){ delete _ply; } + template< class Real , int Dim > PLYInputPointStream< Real , Dim >::~PLYInputPointStream( void ) { @@ -211,7 +188,7 @@ bool PLYInputPointStream< Real , Dim >::nextPoint( Point< Real , Dim >& p ) if( _pIdx<_pCount ) { PlyVertex< Real , Dim > v; - ply_get_element( _ply, (void *)&v ); + _ply->get_element( (void *)&v ); p = v.point; _pIdx++; return true; @@ -333,7 +310,7 @@ template< class Real , int Dim , class Data > PLYInputPointStreamWithData< Real , Dim , Data >::PLYInputPointStreamWithData( const char* fileName , const PlyProperty* dataProperties , int dataPropertiesCount , bool (*validationFunction)( const bool* ) ) : _dataPropertiesCount( dataPropertiesCount ) , _validationFunction( validationFunction ) { _dataProperties = new PlyProperty[ _dataPropertiesCount ]; - memcpy( _dataProperties , dataProperties , sizeof(PlyProperty) * _dataPropertiesCount ); + for( int i=0 ; i ); _fileName = new char[ strlen( fileName )+1 ]; strcpy( _fileName , fileName ); @@ -345,34 +322,34 @@ void PLYInputPointStreamWithData< Real , Dim , Data >::reset( void ) { int fileType; float version; - PlyProperty** plist; + std::vector< PlyProperty * > plist; if( _ply ) _free(); - _ply = ply_open_for_reading( _fileName , &_nr_elems , &_elist , &fileType , &version ); + _ply = PlyFile::Read( _fileName , _elist , fileType , version ); if( !_ply ) fprintf( stderr, "[ERROR] Failed to open ply file for reading: %s\n" , _fileName ) , exit( 0 ); bool foundVertices = false; - for( int i=0 ; i<_nr_elems ; i++ ) + for( int i=0 ; i<_elist.size() ; i++ ) { int num_elems; - int nr_props; - char* elem_name = _elist[i]; - plist = ply_get_element_description( _ply , elem_name , &num_elems , &nr_props ); - if( !plist ) fprintf( stderr , "[ERROR] Failed to get element description: %s\n" , elem_name ) , exit( 0 ); + std::string &elem_name = _elist[i]; + plist = _ply->get_element_description( elem_name , num_elems ); + if( !plist.size() ) fprintf( stderr , "[ERROR] Failed to get element description: %s\n" , elem_name.c_str() ) , exit( 0 ); - if( equal_strings( "vertex" , elem_name ) ) + if( elem_name=="vertex" ) { foundVertices = true; _pCount = num_elems , _pIdx = 0; const PlyProperty* PlyReadProperties = PlyVertex< Real , Dim >::PlyReadProperties(); for( int i=0 ; i::PlyReadNum ; i++ ) - if( !ply_get_property( _ply , elem_name , &(PlyReadProperties[i]) ) ) - fprintf( stderr , "[ERROR] Failed to find property in ply file: %s\n" , PlyReadProperties[i].name ) , exit( 0 ); + if( !_ply->get_property( elem_name , &(PlyReadProperties[i]) ) ) + fprintf( stderr , "[ERROR] Failed to find property in ply file: %s\n" , PlyReadProperties[i].name.c_str() ) , exit( 0 ); + if( _validationFunction ) { bool* properties = new bool[_dataPropertiesCount]; for( int i=0 ; i<_dataPropertiesCount ; i++ ) - if( !ply_get_property( _ply , elem_name , &(_dataProperties[i]) ) ) properties[i] = false; - else properties[i] = true; + if( !_ply->get_property( elem_name , &(_dataProperties[i]) ) ) properties[i] = false; + else properties[i] = true; bool valid = _validationFunction( properties ); delete[] properties; if( !valid ) fprintf( stderr , "[ERROR] Failed to validate properties in file\n" ) , exit( 0 ); @@ -380,16 +357,11 @@ void PLYInputPointStreamWithData< Real , Dim , Data >::reset( void ) else { for( int i=0 ; i<_dataPropertiesCount ; i++ ) - if( !ply_get_property( _ply , elem_name , &(_dataProperties[i]) ) ) - fprintf( stderr , "[WARNING] Failed to find property in ply file: %s\n" , _dataProperties[i].name ); + if( !_ply->get_property( elem_name , &(_dataProperties[i]) ) ) + fprintf( stderr , "[WARNING] Failed to find property in ply file: %s\n" , _dataProperties[i].name.c_str() ); } } - for( int j=0 ; jname ); - free( plist[j] ); - } - free( plist ); + for( int j=0 ; j::reset( void ) } } template< class Real , int Dim , class Data > -void PLYInputPointStreamWithData< Real , Dim , Data >::_free( void ) -{ - if( _ply->comments ) - { - for( int i=0 ; i<_ply->num_comments ; i++ ) free( _ply->comments[i] ); - free( _ply->comments ); - } - if( _ply->obj_info ) - { - for( int i=0 ; i<_ply->num_obj_info ; i++ ) free( _ply->obj_info[i] ); - free( _ply->obj_info ); - } - if( _ply->elems ) - { - for( int i=0 ; i<_ply->nelems ; i++ ) - { - free( _ply->elems[i]->name ); - if( _ply->elems[i]->store_prop ) free( _ply->elems[i]->store_prop ); - for( int j=0 ; j<_ply->elems[i]->nprops ; j++ ) - { - free( _ply->elems[i]->props[j]->name ); - free( _ply->elems[i]->props[j] ); - } - free( _ply->elems[i]->props ); - free( _ply->elems[i] ); - } - free( _ply->elems ); - } - if( _ply ) ply_close( _ply ) , _ply = NULL; - if( _elist ) - { - for( int i=0 ; i<_nr_elems ; i++ ) free( _elist[i] ); - free( _elist ); - } -} +void PLYInputPointStreamWithData< Real , Dim , Data >::_free( void ){ delete _ply; } + template< class Real , int Dim , class Data > PLYInputPointStreamWithData< Real , Dim , Data >::~PLYInputPointStreamWithData( void ) { @@ -447,7 +386,7 @@ bool PLYInputPointStreamWithData< Real , Dim , Data >::nextPoint( Point< Real , if( _pIdx<_pCount ) { _PlyVertexWithData v; - ply_get_element( _ply, (void *)&v ); + _ply->get_element( (void*) &v ); p = v.point; d = v.data; _pIdx++; @@ -462,12 +401,9 @@ bool PLYInputPointStreamWithData< Real , Dim , Data >::nextPoint( Point< Real , template< class Real , int Dim > PLYOutputPointStream< Real , Dim >::PLYOutputPointStream( const char* fileName , size_t count , int fileType ) { - static const char *elem_names[] = { "vertex" }; float version; - char* _fileName = new char[ strlen(fileName)+1]; - strcpy( _fileName , fileName ); - _ply = ply_open_for_writing( fileName , 1 , elem_names , fileType , &version ); - delete[] _fileName; + std::vector< std::string > elem_names = { std::string( "vertex" ) }; + _ply = PlyFile::Write( fileName , elem_names , fileType , version ); if( !_ply ) { fprintf( stderr, "[ERROR] Failed to open ply file for writing: %s\n" , fileName ); @@ -476,11 +412,10 @@ PLYOutputPointStream< Real , Dim >::PLYOutputPointStream( const char* fileName , _pIdx = 0; _pCount = count; - ply_element_count( _ply, "vertex" , _pCount ); - for( int i=0 ; i::WriteComponents ; i++ ) ply_describe_property( _ply , "vertex" , &PlyVertex< Real , Dim >::WriteProperties()[i] ); - - ply_header_complete( _ply ); - ply_put_element_setup( _ply , "vertex" ); + _ply->element_count( "vertex" , _pCount ); + for( int i=0 ; i::WriteComponents ; i++ ) _ply->describe_property( "vertex" , &PlyVertex< Real , Dim >::WriteProperties()[i] ); + _ply->header_complete(); + _ply->put_element_setup( "vertex" ); } template< class Real , int Dim > PLYOutputPointStream< Real , Dim >::~PLYOutputPointStream( void ) @@ -490,8 +425,7 @@ PLYOutputPointStream< Real , Dim >::~PLYOutputPointStream( void ) fprintf( stderr , "[ERROR] Streamed points not equal to total count: %d!=%d\n" , _pIdx , _pCount ); exit( 0 ); } - ply_close( _ply ); - _ply = NULL; + delete _ply; } template< class Real , int Dim > void PLYOutputPointStream< Real , Dim >::nextPoint( const Point< Real , Dim >& p ) @@ -503,7 +437,7 @@ void PLYOutputPointStream< Real , Dim >::nextPoint( const Point< Real , Dim >& p } PlyVertex< Real , Dim > op; op.point = p; - ply_put_element( _ply , (void *) &op ); + _ply->put_element( (void *)&op ); _pIdx++; } @@ -513,12 +447,9 @@ void PLYOutputPointStream< Real , Dim >::nextPoint( const Point< Real , Dim >& p template< class Real , int Dim , class Data > PLYOutputPointStreamWithData< Real , Dim , Data >::PLYOutputPointStreamWithData( const char* fileName , size_t count , int fileType , const PlyProperty* dataProperties , int dataPropertiesCount ) { - static const char *elem_names[] = { "vertex" }; float version; - char* _fileName = new char[ strlen(fileName)+1]; - strcpy( _fileName , fileName ); - _ply = ply_open_for_writing( _fileName , 1 , &elem_names[0] , fileType , &version ); - delete[] _fileName; + std::vector< std::string > elem_names = { std::string( "vertex" ) }; + _ply = PlyFile::Write( fileName , elem_names , fileType , version ); if( !_ply ) { fprintf( stderr, "[ERROR] Failed to open ply file for writing: %s\n" , fileName ); @@ -527,17 +458,17 @@ PLYOutputPointStreamWithData< Real , Dim , Data >::PLYOutputPointStreamWithData( _pIdx = 0; _pCount = (int)count; - ply_element_count( _ply, "vertex" , _pCount ); - for( int i=0 ; i::WriteComponents ; i++ ) ply_describe_property( _ply , "vertex" , &PlyVertex< Real , Dim >::Properties()[i] ); + _ply->element_count( "vertex" , _pCount ); + for( int i=0 ; i::WriteComponents ; i++ ) _ply->describe_property( "vertex" , &PlyVertex< Real , Dim >::Properties()[i] ); for( int i=0 ; i ); - ply_describe_property( _ply , "vertex" , &prop ); + _ply->describe_property( "vertex" , &prop ); } - ply_header_complete( _ply ); - ply_put_element_setup( _ply , "vertex" ); + _ply->header_complete(); + _ply->put_element_setup( "vertex" ); } template< class Real , int Dim , class Data > PLYOutputPointStreamWithData< Real , Dim , Data >::~PLYOutputPointStreamWithData( void ) @@ -547,8 +478,7 @@ PLYOutputPointStreamWithData< Real , Dim , Data >::~PLYOutputPointStreamWithData fprintf( stderr , "[ERROR] Streamed points not equal to total count: %d!=%d\n" , _pIdx , _pCount ); exit( 0 ); } - ply_close( _ply ); - _ply = NULL; + delete _ply; } template< class Real , int Dim , class Data > void PLYOutputPointStreamWithData< Real , Dim , Data >::nextPoint( const Point< Real , Dim >& p , const Data& d ) @@ -561,6 +491,6 @@ void PLYOutputPointStreamWithData< Real , Dim , Data >::nextPoint( const Point< _PlyVertexWithData op; op.point = p; op.data = d; - ply_put_element( _ply , (void *) &op ); + _ply->put_element( (void *)&op ); _pIdx++; } diff --git a/Src/PointStreamData.h b/Src/PointStreamData.h index b6bbc72..1c4ef45 100644 --- a/Src/PointStreamData.h +++ b/Src/PointStreamData.h @@ -119,44 +119,44 @@ protected: template<> const PlyProperty PointStreamPosition< float , 2 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamPosition< double , 2 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamPosition< float , 3 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamPosition< double , 3 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamPosition< float , 4 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "w" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[3] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "w" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamPosition , data.coords[3] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamPosition< double , 4 >::_PlyProperties[] = { - { "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "w" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[3] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "x" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "y" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "z" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "w" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamPosition , data.coords[3] ) ) , 0 , 0 , 0 , 0 ) , }; template< class Real , unsigned int Dim > @@ -214,44 +214,44 @@ protected: template<> const PlyProperty PointStreamNormal< float , 2 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamNormal< double , 2 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamNormal< float , 3 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "nz" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nz" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamNormal< double , 3 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "nz" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nz" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamNormal< float , 4 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "nz" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "nw" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[3] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nz" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nw" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamNormal , data.coords[3] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamNormal< double , 4 >::_PlyProperties[] = { - { "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "nz" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "nw" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[3] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "nx" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "ny" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nz" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "nw" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamNormal , data.coords[3] ) ) , 0 , 0 , 0 , 0 ) , }; template< class Real > @@ -298,22 +298,22 @@ protected: template<> const PlyProperty PointStreamColor< float >::_PlyProperties[] = { - { "red" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "green" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "blue" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "r" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "g" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "b" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "red" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "green" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "blue" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "r" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "g" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "b" , PLY_UCHAR , PLY_FLOAT , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamColor< double >::_PlyProperties[] = { - { "red" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "green" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "blue" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , -{ "r" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 } , -{ "g" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 } , -{ "b" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "red" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "green" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "blue" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "r" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[0] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "g" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[1] ) ) , 0 , 0 , 0 , 0 ) , + PlyProperty( "b" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( PointStreamColor , data.coords[2] ) ) , 0 , 0 , 0 , 0 ) , }; template< class Real > @@ -340,13 +340,14 @@ public: template<> const PlyProperty PointStreamValue< float >::_PlyProperties[] = { - { "value" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamValue , data ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "value" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamValue , data ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamValue< double >::_PlyProperties[] = { - { "value" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamValue , data ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "value" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamValue , data ) ) , 0 , 0 , 0 , 0 ) , }; + template< class Real > struct PointStreamRoughness : public PointStreamData< Real , Real > { @@ -371,12 +372,12 @@ public: template<> const PlyProperty PointStreamRoughness< float >::_PlyProperties[] = { - { "rg" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamRoughness , data ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "rg" , PLY_FLOAT , PLY_FLOAT , int( offsetof( PointStreamRoughness , data ) ) , 0 , 0 , 0 , 0 ) , }; template<> const PlyProperty PointStreamRoughness< double >::_PlyProperties[] = { - { "rg" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamRoughness , data ) ) , 0 , 0 , 0 , 0 } , + PlyProperty( "rg" , PLY_FLOAT , PLY_DOUBLE , int( offsetof( PointStreamRoughness , data ) ) , 0 , 0 , 0 , 0 ) , }; template< typename Real , typename ... Data > @@ -438,13 +439,14 @@ public: static PlyProperty* PlyWriteProperties( void ){ _SetPlyWriteProperties<0>( _PlyWriteProperties ) ; return _PlyWriteProperties; } static bool ValidPlyReadProperties( const bool* flags ){ return _ValidPlyReadProperties<0>( flags ) ; } - template< unsigned int I > static bool ValidPlyReadProperties( const bool* flags ){ return DataType< I >::ValidPlyReadProperties( flags + _PlyReadNum< I >() ); } + template< unsigned int I > static bool ValidPlyReadProperties( const bool* flags ){ return DataType< I >::ValidPlyReadProperties( flags + _PlyReadOffset< I >() ); } protected: static PlyProperty _PlyReadProperties[]; static PlyProperty _PlyWriteProperties[]; private: - template< unsigned int I , unsigned int _I=0 > static typename std::enable_if< I==_I , unsigned int >::type _PlyReadNum( void ){ return 0; } - template< unsigned int I , unsigned int _I=0 > static typename std::enable_if< I!=_I , unsigned int >::type _PlyReadNum( void ){ return DataType< I >::PlyReadNum + _PlyReadNum< I , _I+1 >(); } + // Gives the offset to the I-th element + template< unsigned int I > static typename std::enable_if< I==0 , unsigned int >::type _PlyReadOffset( void ){ return 0; } + template< unsigned int I > static typename std::enable_if< I!=0 , unsigned int >::type _PlyReadOffset( void ){ return DataType< I-1 >::PlyReadNum + _PlyReadOffset< I-1 >(); } template< unsigned int I > typename std::enable_if< I!=sizeof...(Data) >::type _readASCII ( FILE* fp ) { DataType< I >:: ReadASCII ( fp , std::get< I >( data ) ) ; _readASCII < I+1 >( fp ); } template< unsigned int I > typename std::enable_if< I==sizeof...(Data) >::type _readASCII ( FILE* fp ) { } diff --git a/Src/PoissonRecon.cpp b/Src/PoissonRecon.cpp index d5489f3..d18379e 100644 --- a/Src/PoissonRecon.cpp +++ b/Src/PoissonRecon.cpp @@ -212,7 +212,7 @@ struct FEMTreeProfiler if( header ) messageWriter( "%s %9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , header , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); else messageWriter( "%9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); } - void dumpOutput2( std::vector< char* >& comments , const char* header ) const + void dumpOutput2( std::vector< std::string >& comments , const char* header ) const { FEMTree< Dim , Real >::MemoryUsage(); if( header ) messageWriter( comments , "%s %9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , header , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); @@ -291,7 +291,7 @@ struct SystemDual< Dim , double > }; template< typename Vertex , typename Real , unsigned int ... FEMSigs , typename ... SampleData > -void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTree< sizeof ... ( FEMSigs ) , Real >& tree , const DenseNodeData< Real , UIntPack< FEMSigs ... > >& solution , Real isoValue , const std::vector< typename FEMTree< sizeof ... ( FEMSigs ) , Real >::PointSample >* samples , std::vector< MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > >* sampleData , const typename FEMTree< sizeof ... ( FEMSigs ) , Real >::template DensityEstimator< WEIGHT_DEGREE >* density , std::function< void ( Vertex& , Point< Real , DIMENSION > , Real , MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > ) > SetVertex , std::vector< char* >& comments , XForm< Real , sizeof...(FEMSigs)+1 > iXForm ) +void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTree< sizeof ... ( FEMSigs ) , Real >& tree , const DenseNodeData< Real , UIntPack< FEMSigs ... > >& solution , Real isoValue , const std::vector< typename FEMTree< sizeof ... ( FEMSigs ) , Real >::PointSample >* samples , std::vector< MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > >* sampleData , const typename FEMTree< sizeof ... ( FEMSigs ) , Real >::template DensityEstimator< WEIGHT_DEGREE >* density , std::function< void ( Vertex& , Point< Real , DIMENSION > , Real , MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > ) > SetVertex , std::vector< std::string > &comments , XForm< Real , sizeof...(FEMSigs)+1 > iXForm ) { static const int Dim = sizeof ... ( FEMSigs ); typedef UIntPack< FEMSigs ... > Sigs; @@ -333,8 +333,8 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); else profiler.dumpOutput2( comments , "# Got triangles:" ); - if( NoComments.set ) PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NULL , 0 , iXForm ); - else PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm ); + std::vector< std::string > noComments; + PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NoComments.set ? noComments : comments , iXForm ); } template< class Real , typename ... SampleData , unsigned int ... FEMSigs > @@ -352,7 +352,7 @@ int Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) typedef MultiPointStreamData< Real , NormalPointSampleData , AdditionalPointSampleData > TotalPointSampleData; typedef InputPointStreamWithData< Real , Dim , TotalPointSampleData > InputPointStream; typedef TransformedInputPointStreamWithData< Real , Dim , TotalPointSampleData > XInputPointStream; - std::vector< char* > comments; + std::vector< std::string > comments; messageWriter( comments , "*************************************************************\n" ); messageWriter( comments , "*************************************************************\n" ); messageWriter( comments , "** Running Screened Poisson Reconstruction (Version %s) **\n" , VERSION ); @@ -632,8 +632,6 @@ int Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) if( density ) delete density , density = NULL; messageWriter( comments , "# Total Solve: %9.1f (s), %9.1f (MB)\n" , Time()-startTime , FEMTree< Dim , Real >::MaxMemoryUsage() ); - for( int i=0 ; i::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); else messageWriter( "%9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); } - void dumpOutput2( std::vector< char* >& comments , const char* header ) const + void dumpOutput2( std::vector< std::string >& comments , const char* header ) const { FEMTree< Dim , Real >::MemoryUsage(); if( header ) messageWriter( comments , "%s %9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , header , Time()-t , FEMTree< Dim , Real >::LocalMemoryUsage() , FEMTree< Dim , Real >::MaxMemoryUsage() , MemoryInfo::PeakMemoryUsageMB() ); @@ -312,7 +312,7 @@ struct SystemDual< Dim , double , TotalPointSampleData > }; template< typename Vertex , typename Real , unsigned int ... FEMSigs , typename ... SampleData > -void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTree< sizeof ... ( FEMSigs ) , Real >& tree , const DenseNodeData< Real , UIntPack< FEMSigs ... > >& solution , Real isoValue , const std::vector< typename FEMTree< sizeof ... ( FEMSigs ) , Real >::PointSample >* samples , std::vector< MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > >* sampleData , const typename FEMTree< sizeof ... ( FEMSigs ) , Real >::template DensityEstimator< WEIGHT_DEGREE >* density , std::function< void ( Vertex& , Point< Real , DIMENSION > , Real , MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > ) > SetVertex , std::vector< char* >& comments , XForm< Real , sizeof...(FEMSigs)+1 > iXForm ) +void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTree< sizeof ... ( FEMSigs ) , Real >& tree , const DenseNodeData< Real , UIntPack< FEMSigs ... > >& solution , Real isoValue , const std::vector< typename FEMTree< sizeof ... ( FEMSigs ) , Real >::PointSample >* samples , std::vector< MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > >* sampleData , const typename FEMTree< sizeof ... ( FEMSigs ) , Real >::template DensityEstimator< WEIGHT_DEGREE >* density , std::function< void ( Vertex& , Point< Real , DIMENSION > , Real , MultiPointStreamData< Real , PointStreamNormal< Real , DIMENSION > , MultiPointStreamData< Real , SampleData ... > > ) > SetVertex , std::vector< std::string > &comments , XForm< Real , sizeof...(FEMSigs)+1 > iXForm ) { static const int Dim = sizeof ... ( FEMSigs ); typedef UIntPack< FEMSigs ... > Sigs; @@ -353,8 +353,8 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); else profiler.dumpOutput2( comments , "# Got triangles:" ); - if( NoComments.set ) PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NULL , 0 , iXForm ); - else PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm ); + std::vector< std::string > noComments; + PlyWritePolygons< Vertex , Real , Dim >( Out.value , &mesh , ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE , NoComments.set ? noComments : comments , iXForm ); } template< class Real , typename ... SampleData , unsigned int ... FEMSigs > @@ -372,7 +372,7 @@ int Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) typedef MultiPointStreamData< Real , NormalPointSampleData , AdditionalPointSampleData > TotalPointSampleData; typedef InputPointStreamWithData< Real , Dim , TotalPointSampleData > InputPointStream; typedef TransformedInputPointStreamWithData< Real , Dim , TotalPointSampleData > XInputPointStream; - std::vector< char* > comments; + std::vector< std::string > comments; messageWriter( comments , "************************************************\n" ); messageWriter( comments , "************************************************\n" ); messageWriter( comments , "** Running SSD Reconstruction (Version %s) **\n" , VERSION ); @@ -633,8 +633,6 @@ int Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) if( density ) delete density , density = NULL; messageWriter( comments , "# Total Solve: %9.1f (s), %9.1f (MB)\n" , Time()-startTime , FEMTree< Dim , Real >::MaxMemoryUsage() ); - for( int i=0 ; i vertices; std::vector< std::vector< int > > polygons; - int ft , commentNum = 0; - std::vector< char* > comments; - char** _comments; - PlyReadPolygons< Vertex >( In.value , vertices , polygons , Vertex::PlyReadProperties() , Vertex::PlyReadNum , ft , &_comments , &commentNum ); - for( int i=0 ; i comments; + PlyReadPolygons< Vertex >( In.value , vertices , polygons , Vertex::PlyReadProperties() , Vertex::PlyReadNum , ft , comments ); + for( int i=0 ; i( vertices , polygons ); min = max = std::get< 0 >( vertices[0].data.data ).data; - for( size_t i=0 ; i( min , std::get< 0 >( vertices[0].data.data ).data ) , max = std::max< float >( max , std::get< 0 >( vertices[0].data.data ).data ); - if( Verbose.set ) printf( "Value Range: [%f,%f]\n" , min , max ); + for( size_t i=0 ; i( min , std::get< 0 >( vertices[i].data.data ).data ) , max = std::max< float >( max , std::get< 0 >( vertices[i].data.data ).data ); std::unordered_map< long long, int > vertexTable; std::vector< std::vector< int > > ltPolygons , gtPolygons; @@ -308,6 +306,7 @@ int Execute( void ) if( strlen( str ) ) messageWriter( comments , "\t--%s %s\n" , params[i]->name , str ); else messageWriter( comments , "\t--%s\n" , params[i]->name ); } + if( Verbose.set ) printf( "Value Range: [%f,%f]\n" , min , max ); double t=Time(); for( size_t i=0 ; i( Out.value , vertices , gtPolygons , Vertex::PlyWriteProperties() , Vertex::PlyWriteNum , ft , &comments[0] , (int)comments.size() ); - - for( int i=0 ; i( Out.value , vertices , gtPolygons , Vertex::PlyWriteProperties() , Vertex::PlyWriteNum , ft , comments ); return EXIT_SUCCESS; }