diff --git a/modules/odm_cleanmesh/src/CmdLineParser.h b/modules/odm_cleanmesh/src/CmdLineParser.h new file mode 100644 index 00000000..a1fbd0e3 --- /dev/null +++ b/modules/odm_cleanmesh/src/CmdLineParser.h @@ -0,0 +1,106 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#ifndef CMD_LINE_PARSER_INCLUDED +#define CMD_LINE_PARSER_INCLUDED + +#include +#include +#include +#include +#include + +#ifdef WIN32 +int strcasecmp( const char* c1 , const char* c2 ); +#endif // WIN32 + +class cmdLineReadable +{ +public: + bool set; + char *name; + cmdLineReadable( const char *name ); + virtual ~cmdLineReadable( void ); + virtual int read( char** argv , int argc ); + virtual void writeValue( char* str ) const; +}; + +template< class Type > void cmdLineWriteValue( Type t , char* str ); +template< class Type > void cmdLineCleanUp( Type* t ); +template< class Type > Type cmdLineInitialize( void ); +template< class Type > Type cmdLineCopy( Type t ); +template< class Type > Type cmdLineStringToType( const char* str ); + +template< class Type > +class cmdLineParameter : public cmdLineReadable +{ +public: + Type value; + cmdLineParameter( const char *name ); + cmdLineParameter( const char *name , Type v ); + ~cmdLineParameter( void ); + int read( char** argv , int argc ); + void writeValue( char* str ) const; + bool expectsArg( void ) const { return true; } +}; + +template< class Type , int Dim > +class cmdLineParameterArray : public cmdLineReadable +{ +public: + Type values[Dim]; + cmdLineParameterArray( const char *name, const Type* v=NULL ); + ~cmdLineParameterArray( void ); + int read( char** argv , int argc ); + void writeValue( char* str ) const; + bool expectsArg( void ) const { return true; } +}; + +template< class Type > +class cmdLineParameters : public cmdLineReadable +{ +public: + int count; + Type *values; + cmdLineParameters( const char* name ); + ~cmdLineParameters( void ); + int read( char** argv , int argc ); + void writeValue( char* str ) const; + bool expectsArg( void ) const { return true; } +}; + +void cmdLineParse( int argc , char **argv, cmdLineReadable** params ); +char* FileExtension( char* fileName ); +char* LocalFileName( char* fileName ); +char* DirectoryName( char* fileName ); +char* GetFileExtension( const char* fileName ); +char* GetLocalFileName( const char* fileName ); +char** ReadWords( const char* fileName , int& cnt ); + +#include "CmdLineParser.inl" +#endif // CMD_LINE_PARSER_INCLUDED diff --git a/modules/odm_cleanmesh/src/CmdLineParser.inl b/modules/odm_cleanmesh/src/CmdLineParser.inl new file mode 100644 index 00000000..84574a57 --- /dev/null +++ b/modules/odm_cleanmesh/src/CmdLineParser.inl @@ -0,0 +1,300 @@ +/* -*- C++ -*- +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#include +#include + +#if defined( WIN32 ) || defined( _WIN64 ) +inline int strcasecmp( const char* c1 , const char* c2 ){ return _stricmp( c1 , c2 ); } +#endif // WIN32 || _WIN64 + +template< > void cmdLineCleanUp< int >( int* t ){ *t = 0; } +template< > void cmdLineCleanUp< float >( float* t ){ *t = 0; } +template< > void cmdLineCleanUp< double >( double* t ){ *t = 0; } +template< > void cmdLineCleanUp< char* >( char** t ){ if( *t ) free( *t ) ; *t = NULL; } +template< > int cmdLineInitialize< int >( void ){ return 0; } +template< > float cmdLineInitialize< float >( void ){ return 0.f; } +template< > double cmdLineInitialize< double >( void ){ return 0.; } +template< > char* cmdLineInitialize< char* >( void ){ return NULL; } +template< > void cmdLineWriteValue< int >( int t , char* str ){ sprintf( str , "%d" , t ); } +template< > void cmdLineWriteValue< float >( float t , char* str ){ sprintf( str , "%f" , t ); } +template< > void cmdLineWriteValue< double >( double t , char* str ){ sprintf( str , "%f" , t ); } +template< > void cmdLineWriteValue< char* >( char* t , char* str ){ if( t ) sprintf( str , "%s" , t ) ; else str[0]=0; } +template< > int cmdLineCopy( int t ){ return t; } +template< > float cmdLineCopy( float t ){ return t; } +template< > double cmdLineCopy( double t ){ return t; } +#if defined( WIN32 ) || defined( _WIN64 ) +template< > char* cmdLineCopy( char* t ){ return _strdup( t ); } +#else // !WIN32 && !_WIN64 +template< > char* cmdLineCopy( char* t ){ return strdup( t ); } +#endif // WIN32 || _WIN64 +template< > int cmdLineStringToType( const char* str ){ return atoi( str ); } +template< > float cmdLineStringToType( const char* str ){ return float( atof( str ) ); } +template< > double cmdLineStringToType( const char* str ){ return double( atof( str ) ); } +#if defined( WIN32 ) || defined( _WIN64 ) +template< > char* cmdLineStringToType( const char* str ){ return _strdup( str ); } +#else // !WIN32 && !_WIN64 +template< > char* cmdLineStringToType( const char* str ){ return strdup( str ); } +#endif // WIN32 || _WIN64 + + +///////////////////// +// cmdLineReadable // +///////////////////// +#if defined( WIN32 ) || defined( _WIN64 ) +inline cmdLineReadable::cmdLineReadable( const char *name ) : set(false) { this->name = _strdup( name ); } +#else // !WIN32 && !_WIN64 +inline cmdLineReadable::cmdLineReadable( const char *name ) : set(false) { this->name = strdup( name ); } +#endif // WIN32 || _WIN64 + +inline cmdLineReadable::~cmdLineReadable( void ){ if( name ) free( name ) ; name = NULL; } +inline int cmdLineReadable::read( char** , int ){ set = true ; return 0; } +inline void cmdLineReadable::writeValue( char* str ) const { str[0] = 0; } + +////////////////////// +// cmdLineParameter // +////////////////////// +template< class Type > cmdLineParameter< Type >::~cmdLineParameter( void ) { cmdLineCleanUp( &value ); } +template< class Type > cmdLineParameter< Type >::cmdLineParameter( const char *name ) : cmdLineReadable( name ){ value = cmdLineInitialize< Type >(); } +template< class Type > cmdLineParameter< Type >::cmdLineParameter( const char *name , Type v ) : cmdLineReadable( name ){ value = cmdLineCopy< Type >( v ); } +template< class Type > +int cmdLineParameter< Type >::read( char** argv , int argc ) +{ + if( argc>0 ) + { + cmdLineCleanUp< Type >( &value ) , value = cmdLineStringToType< Type >( argv[0] ); + set = true; + return 1; + } + else return 0; +} +template< class Type > +void cmdLineParameter< Type >::writeValue( char* str ) const { cmdLineWriteValue< Type >( value , str ); } + + +/////////////////////////// +// cmdLineParameterArray // +/////////////////////////// +template< class Type , int Dim > +cmdLineParameterArray< Type , Dim >::cmdLineParameterArray( const char *name , const Type* v ) : cmdLineReadable( name ) +{ + if( v ) for( int i=0 ; i( v[i] ); + else for( int i=0 ; i(); +} +template< class Type , int Dim > +cmdLineParameterArray< Type , Dim >::~cmdLineParameterArray( void ){ for( int i=0 ; i( values+i ); } +template< class Type , int Dim > +int cmdLineParameterArray< Type , Dim >::read( char** argv , int argc ) +{ + if( argc>=Dim ) + { + for( int i=0 ; i( values+i ) , values[i] = cmdLineStringToType< Type >( argv[i] ); + set = true; + return Dim; + } + else return 0; +} +template< class Type , int Dim > +void cmdLineParameterArray< Type , Dim >::writeValue( char* str ) const +{ + char* temp=str; + for( int i=0 ; i( values[i] , temp ); + temp = str+strlen( str ); + } +} +/////////////////////// +// cmdLineParameters // +/////////////////////// +template< class Type > +cmdLineParameters< Type >::cmdLineParameters( const char* name ) : cmdLineReadable( name ) , values(NULL) , count(0) { } +template< class Type > +cmdLineParameters< Type >::~cmdLineParameters( void ) +{ + if( values ) delete[] values; + values = NULL; + count = 0; +} +template< class Type > +int cmdLineParameters< Type >::read( char** argv , int argc ) +{ + if( values ) delete[] values; + values = NULL; + + if( argc>0 ) + { + count = atoi(argv[0]); + if( count <= 0 || argc <= count ) return 1; + values = new Type[count]; + if( !values ) return 0; + for( int i=0 ; i( argv[i+1] ); + set = true; + return count+1; + } + else return 0; +} +template< class Type > +void cmdLineParameters< Type >::writeValue( char* str ) const +{ + char* temp=str; + for( int i=0 ; i( values[i] , temp ); + temp = str+strlen( str ); + } +} + + +inline char* FileExtension( char* fileName ) +{ + char* temp = fileName; + for( unsigned int i=0 ; i=0 ; i-- ) + if( fileName[i] =='\\' ) + { + fileName[i] = 0; + return fileName; + } + fileName[0] = 0; + return fileName; +} + +inline void cmdLineParse( int argc , char **argv , cmdLineReadable** params ) +{ + while( argc>0 ) + { + if( argv[0][0]=='-' ) + { + cmdLineReadable* readable=NULL; + for( int i=0 ; params[i]!=NULL && readable==NULL ; i++ ) if( !strcasecmp( params[i]->name , argv[0]+1 ) ) readable = params[i]; + if( readable ) + { + int j = readable->read( argv+1 , argc-1 ); + argv += j , argc -= j; + } + else + { + fprintf( stderr , "[WARNING] Invalid option: %s\n" , argv[0] ); + for( int i=0 ; params[i]!=NULL ; i++ ) printf( "\t-%s\n" , params[i]->name ); + } + } + else fprintf( stderr , "[WARNING] Parameter name should be of the form -: %s\n" , argv[0] ); + ++argv , --argc; + } +} + +inline char** ReadWords(const char* fileName,int& cnt) +{ + char** names; + char temp[500]; + FILE* fp; + + fp=fopen(fileName,"r"); + if(!fp){return NULL;} + cnt=0; + while(fscanf(fp," %s ",temp)==1){cnt++;} + fclose(fp); + + names=new char*[cnt]; + if(!names){return NULL;} + + fp=fopen(fileName,"r"); + if(!fp){ + delete[] names; + cnt=0; + return NULL; + } + cnt=0; + while(fscanf(fp," %s ",temp)==1){ + names[cnt]=new char[strlen(temp)+1]; + if(!names){ + for(int j=0;j +#include +#include "CmdLineParser.h" + +struct Logger{ + bool verbose; + const char* outputFile; + + Logger(){ + this->verbose = false; + this->outputFile = NULL; + } + + void operator() ( 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( verbose ) + { + va_list args; + va_start( args , format ); + vprintf( format , args ); + va_end( args ); + } + } +}; diff --git a/modules/odm_cleanmesh/src/main.cpp b/modules/odm_cleanmesh/src/main.cpp index 2a3fd34d..72419f83 100644 --- a/modules/odm_cleanmesh/src/main.cpp +++ b/modules/odm_cleanmesh/src/main.cpp @@ -5,91 +5,77 @@ #include #include #include +#include "CmdLineParser.h" +#include "Logger.h" #define IS_BIG_ENDIAN (*(uint16_t *)"\0\xff" < 0x100) -std::string inputFile = "", outputFile = ""; -bool verbose = false; +Logger logWriter; + +cmdLineParameter< char* > + InputFile( "inputFile" ) , + OutputFile( "outputFile" ); +cmdLineReadable + Verbose( "verbose" ); + +cmdLineReadable* params[] = +{ + &InputFile , &OutputFile , &Verbose , + NULL +}; // TODO: -// 1. better help // 2. optional decimation filter // 3. optional island removal -// 4. exit macros -void help(){ - std::cout << "HELP TODO" << std::endl; - // log << "Usage: odm_25dmeshing -inputFile [plyFile] [optional-parameters]\n"; - // log << "Create a 2.5D mesh from a point cloud. " - // << "The program requires a path to an input PLY point cloud file, all other input parameters are optional.\n\n"; - // log << " -inputFile to PLY point cloud\n" - // << " -outputFile where the output PLY 2.5D mesh should be saved (default: " << outputFile << ")\n" - // << " -outputDsmFile Optionally output the Digital Surface Model (DSM) computed for generating the mesh. (default: " << outputDsmFile << ")\n" - // << " -logFile log file path (default: " << logFilePath << ")\n" - // << " -verbose whether to print verbose output (default: " << (printInCoutPop ? "true" : "false") << ")\n" - // << " -maxVertexCount <0 - N> Maximum number of vertices in the output mesh. The mesh might have fewer vertices, but will not exceed this limit. (default: " << maxVertexCount << ")\n" - // << " -neighbors <1 - 1000> Number of nearest neighbors to consider when doing shepard's interpolation and outlier removal. Higher values lead to smoother meshes but take longer to process. (default: " << neighbors << ")\n" - // << " -resolution <0 - N> Size of the interpolated digital surface model (DSM) used for deriving the 2.5D mesh, expressed in pixels per meter unit. When set to zero, the program automatically attempts to find a good value based on the point cloud extent and target vertex count. (default: " << resolution << ")\n" - - // << "\n"; - exit(0); +void help(char *ex){ + std::cout << "Usage: " << ex << std::endl + << "\t -" << InputFile.name << " " << std::endl + << "\t -" << OutputFile.name << " " << std::endl + << "\t [-" << Verbose.name << "]" << std::endl; + exit(EXIT_FAILURE); } -void parseArguments(int argc, char **argv) { - for (int argIndex = 1; argIndex < argc; ++argIndex) { - // The argument to be parsed. - std::string argument = std::string(argv[argIndex]); - if (argument == "-help") { - help(); - exit(0); - } else if (argument == "-verbose") { - verbose = true; - } else if (argument == "-inputFile" && argIndex < argc) { - ++argIndex; - if (argIndex >= argc) { - throw std::runtime_error( - "Argument '" + argument - + "' expects 1 more input following it, but no more inputs were provided."); - } - inputFile = std::string(argv[argIndex]); - } else if (argument == "-outputFile" && argIndex < argc) { - ++argIndex; - if (argIndex >= argc) { - throw std::runtime_error( - "Argument '" + argument - + "' expects 1 more input following it, but no more inputs were provided."); - } - outputFile = std::string(argv[argIndex]); - } else { - help(); - } - } +void logParams(){ + logWriter("Running with parameters:\n"); + char str[1024]; + for( int i=0 ; params[i] ; i++ ){ + if( params[i]->set ){ + params[i]->writeValue( str ); + if( strlen( str ) ) logWriter( "\t--%s %s\n" , params[i]->name , str ); + else logWriter( "\t--%s\n" , params[i]->name ); + } + } } int main(int argc, char **argv) { - parseArguments(argc, argv); - if (inputFile.empty() || outputFile.empty()) help(); + cmdLineParse( argc-1 , &argv[1] , params ); + if( !InputFile.set || !OutputFile.set ) help( argv[0] ); + + logWriter.verbose = Verbose.set; + logWriter.outputFile = "odm_cleanmesh_log.txt"; + logParams(); vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName ( inputFile.c_str() ); + reader->SetFileName ( InputFile.value ); vtkSmartPointer connectivityFilter = vtkSmartPointer::New(); connectivityFilter->SetInputConnection(reader->GetOutputPort()); connectivityFilter->SetExtractionModeToLargestRegion(); - std::cout << "Saving cleaned mesh to file... " << std::endl; + logWriter("Saving cleaned mesh to file... \n"); vtkSmartPointer plyWriter = vtkSmartPointer::New(); - plyWriter->SetFileName(outputFile.c_str()); + plyWriter->SetFileName(OutputFile.value); plyWriter->SetInputConnection(connectivityFilter->GetOutputPort()); plyWriter->SetFileTypeToBinary(); plyWriter->Write(); - std::cout << "OK" << std::endl; + logWriter("OK\n"); }