MagicDGP::LightMesh3D* PoissonReconstruction::SurfaceTrimmer(int argc , char* argv[], std::vector< PlyValueVertex< float > >& vertices, std::vector< std::vector< int > >& polygons) { cmdLineString In( "in" ) , Out( "out" ); cmdLineInt Smooth( "smooth" , 5 ); cmdLineFloat Trim( "trim" ) , IslandAreaRatio( "aRatio" , 0.001f ); cmdLineFloatArray< 2 > ColorRange( "color" ); cmdLineReadable PolygonMesh( "polygonMesh" ); cmdLineReadable* params[] = { &In , &Out , &Trim , &PolygonMesh , &ColorRange , &Smooth , &IslandAreaRatio }; int paramNum = sizeof(params)/sizeof(cmdLineReadable*); cmdLineParse( argc , argv, paramNum , params , 0 ); float min , max; //std::vector< PlyValueVertex< float > > vertices; //std::vector< std::vector< int > > polygons; //int ft , commentNum = paramNum+2; //char** comments; //bool readFlags[ PlyValueVertex< float >::Components ]; //PlyReadPolygons( In.value , vertices , polygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , &comments , &commentNum , readFlags ); //if( !readFlags[3] ){ fprintf( stderr , "[ERROR] vertices do not have value flag\n" ) ; return EXIT_FAILURE; } for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); min = max = vertices[0].value; for( size_t i=0 ; i<vertices.size() ; i++ ) min = std::min< float >( min , vertices[i].value ) , max = std::max< float >( max , vertices[i].value ); printf( "Value Range: [%f,%f]\n" , min , max ); if( Trim.set ) { hash_map< long long , int > vertexTable; std::vector< std::vector< int > > ltPolygons , gtPolygons; std::vector< bool > ltFlags , gtFlags; /*for( int i=0 ; i<paramNum+2 ; i++ ) comments[i+commentNum]=new char[1024]; sprintf( comments[commentNum++] , "Running Surface Trimmer (V5)" ); if( In.set ) sprintf(comments[commentNum++],"\t--%s %s" , In.name , In.value ); if( Out.set ) sprintf(comments[commentNum++],"\t--%s %s" , Out.name , Out.value ); if( Trim.set ) sprintf(comments[commentNum++],"\t--%s %f" , Trim.name , Trim.value ); if( Smooth.set ) sprintf(comments[commentNum++],"\t--%s %d" , Smooth.name , Smooth.value ); if( IslandAreaRatio.set ) sprintf(comments[commentNum++],"\t--%s %f" , IslandAreaRatio.name , IslandAreaRatio.value ); if( PolygonMesh.set ) sprintf(comments[commentNum++],"\t--%s" , PolygonMesh.name );*/ double t=Time(); for( size_t i=0 ; i<polygons.size() ; i++ ) SplitPolygon( polygons[i] , vertices , <Polygons , >Polygons , <Flags , >Flags , vertexTable , Trim.value ); if( IslandAreaRatio.value>0 ) { std::vector< std::vector< int > > _ltPolygons , _gtPolygons; std::vector< std::vector< int > > ltComponents , gtComponents; SetConnectedComponents( ltPolygons , ltComponents ); SetConnectedComponents( gtPolygons , gtComponents ); std::vector< double > ltAreas( ltComponents.size() , 0. ) , gtAreas( gtComponents.size() , 0. ); std::vector< bool > ltComponentFlags( ltComponents.size() , false ) , gtComponentFlags( gtComponents.size() , false ); double area = 0.; for( size_t i=0 ; i<ltComponents.size() ; i++ ) { for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) { ltAreas[i] += PolygonArea( vertices , ltPolygons[ ltComponents[i][j] ] ); ltComponentFlags[i] = ( ltComponentFlags[i] || ltFlags[ ltComponents[i][j] ] ); } area += ltAreas[i]; } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) { gtAreas[i] += PolygonArea( vertices , gtPolygons[ gtComponents[i][j] ] ); gtComponentFlags[i] = ( gtComponentFlags[i] || gtFlags[ gtComponents[i][j] ] ); } area += gtAreas[i]; } for( size_t i=0 ; i<ltComponents.size() ; i++ ) { if( ltAreas[i]<area*IslandAreaRatio.value && ltComponentFlags[i] ) for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _gtPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); else for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _ltPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { if( gtAreas[i]<area*IslandAreaRatio.value && gtComponentFlags[i] ) for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _ltPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); else for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _gtPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); } ltPolygons = _ltPolygons , gtPolygons = _gtPolygons; } if( !PolygonMesh.set ) { { std::vector< std::vector< int > > polys = ltPolygons; Triangulate( vertices , ltPolygons , polys ) , ltPolygons = polys; } { std::vector< std::vector< int > > polys = gtPolygons; Triangulate( vertices , gtPolygons , polys ) , gtPolygons = polys; } } RemoveHangingVertices( vertices , gtPolygons ); MagicDGP::LightMesh3D* pExportMesh = new MagicDGP::LightMesh3D; for (int pIndex = 0; pIndex < vertices.size(); pIndex++) { PlyValueVertex< float > vert = vertices.at(pIndex); MagicMath::Vector3 vertPos(vert.point[0], vert.point[1], vert.point[2]); pExportMesh->InsertVertex(vertPos); } for (int pIndex = 0; pIndex < gtPolygons.size(); pIndex++) { MagicDGP::FaceIndex faceIdx; for (int k = 0; k < 3; k++) { faceIdx.mIndex[k] = gtPolygons.at(pIndex).at(k); } pExportMesh->InsertFace(faceIdx); } pExportMesh->UpdateNormal(); return pExportMesh; } else { //if( ColorRange.set ) min = ColorRange.values[0] , max = ColorRange.values[1]; //std::vector< PlyColorVertex< float > > outVertices; //ColorVertices( vertices , outVertices , min , max ); ////if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , ft , comments , commentNum ); //if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , 1 , NULL , 0 ); } return NULL; }
int main( int argc , char* argv[] ) { int paramNum = sizeof(params)/sizeof(cmdLineReadable*); cmdLineParse( argc-1 , &argv[1] , paramNum , params , 0 ); #if FOR_RELEASE if( !In.set || !Trim.set ) { ShowUsage( argv[0] ); return EXIT_FAILURE; } #else // !FOR_RELEASE if( !In.set ) { ShowUsage( argv[0] ); return EXIT_FAILURE; } #endif // FOR_RELEASE float min , max; std::vector< PlyValueVertex< float > > vertices; std::vector< std::vector< int > > polygons; int ft , commentNum = paramNum+2; char** comments; bool readFlags[ PlyValueVertex< float >::Components ]; PlyReadPolygons( In.value , vertices , polygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , &comments , &commentNum , readFlags ); if( !readFlags[3] ){ fprintf( stderr , "[ERROR] vertices do not have value flag\n" ) ; return EXIT_FAILURE; } #if 0 if( Trim.set ) for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons , Trim.value-0.5f , Trim.value+0.5f ); else for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); #else for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); #endif min = max = vertices[0].value; for( size_t i=0 ; i<vertices.size() ; i++ ) min = std::min< float >( min , vertices[i].value ) , max = std::max< float >( max , vertices[i].value ); printf( "Value Range: [%f,%f]\n" , min , max ); if( Trim.set ) { hash_map< long long , int > vertexTable; std::vector< std::vector< int > > ltPolygons , gtPolygons; std::vector< bool > ltFlags , gtFlags; for( int i=0 ; i<paramNum+2 ; i++ ) comments[i+commentNum]=new char[1024]; sprintf( comments[commentNum++] , "Running Surface Trimmer (V5)" ); if( In.set ) sprintf(comments[commentNum++],"\t--%s %s" , In.name , In.value ); if( Out.set ) sprintf(comments[commentNum++],"\t--%s %s" , Out.name , Out.value ); if( Trim.set ) sprintf(comments[commentNum++],"\t--%s %f" , Trim.name , Trim.value ); if( Smooth.set ) sprintf(comments[commentNum++],"\t--%s %d" , Smooth.name , Smooth.value ); if( IslandAreaRatio.set ) sprintf(comments[commentNum++],"\t--%s %f" , IslandAreaRatio.name , IslandAreaRatio.value ); if( PolygonMesh.set ) sprintf(comments[commentNum++],"\t--%s" , PolygonMesh.name ); double t=Time(); for( size_t i=0 ; i<polygons.size() ; i++ ) SplitPolygon( polygons[i] , vertices , <Polygons , >Polygons , <Flags , >Flags , vertexTable , Trim.value ); if( IslandAreaRatio.value>0 ) { std::vector< std::vector< int > > _ltPolygons , _gtPolygons; std::vector< std::vector< int > > ltComponents , gtComponents; SetConnectedComponents( ltPolygons , ltComponents ); SetConnectedComponents( gtPolygons , gtComponents ); std::vector< double > ltAreas( ltComponents.size() , 0. ) , gtAreas( gtComponents.size() , 0. ); std::vector< bool > ltComponentFlags( ltComponents.size() , false ) , gtComponentFlags( gtComponents.size() , false ); double area = 0.; for( size_t i=0 ; i<ltComponents.size() ; i++ ) { for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) { ltAreas[i] += PolygonArea( vertices , ltPolygons[ ltComponents[i][j] ] ); ltComponentFlags[i] = ( ltComponentFlags[i] || ltFlags[ ltComponents[i][j] ] ); } area += ltAreas[i]; } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) { gtAreas[i] += PolygonArea( vertices , gtPolygons[ gtComponents[i][j] ] ); gtComponentFlags[i] = ( gtComponentFlags[i] || gtFlags[ gtComponents[i][j] ] ); } area += gtAreas[i]; } for( size_t i=0 ; i<ltComponents.size() ; i++ ) { if( ltAreas[i]<area*IslandAreaRatio.value && ltComponentFlags[i] ) for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _gtPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); else for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _ltPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { if( gtAreas[i]<area*IslandAreaRatio.value && gtComponentFlags[i] ) for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _ltPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); else for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _gtPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); } ltPolygons = _ltPolygons , gtPolygons = _gtPolygons; } if( !PolygonMesh.set ) { { std::vector< std::vector< int > > polys = ltPolygons; Triangulate( vertices , ltPolygons , polys ) , ltPolygons = polys; } { std::vector< std::vector< int > > polys = gtPolygons; Triangulate( vertices , gtPolygons , polys ) , gtPolygons = polys; } } RemoveHangingVertices( vertices , gtPolygons ); sprintf( comments[commentNum++] , "#Trimmed In: %9.1f (s)" , Time()-t ); if( Out.set ) PlyWritePolygons( Out.value , vertices , gtPolygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , comments , commentNum ); } else { if( ColorRange.set ) min = ColorRange.values[0] , max = ColorRange.values[1]; std::vector< PlyColorVertex< float > > outVertices; ColorVertices( vertices , outVertices , min , max ); if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , ft , comments , commentNum ); } return EXIT_SUCCESS; }