diff --git a/apps/metro/defs.h b/apps/metro/defs.h index 7ff1f8f9..2d1b8441 100644 --- a/apps/metro/defs.h +++ b/apps/metro/defs.h @@ -3,40 +3,7 @@ #define _DEFS_H // ----------------------------------------------------------------------------------------------- -// command line parameters -#define CMD_LINE_ARG_HIST 'H' -#define CMD_LINE_ARG_VERTEX_SAMPLE 'V' -#define CMD_LINE_ARG_EDGE_SAMPLE 'E' -#define CMD_LINE_ARG_FACE_SAMPLE 'F' -#define CMD_LINE_ARG_SAMPLE_TYPE 'S' -#define CMD_LINE_ARG_MONTECARLO_SAMPLING 'M' -#define CMD_LINE_ARG_SUBDIVISION_SAMPLING 'S' -#define CMD_LINE_ARG_SIMILAR_TRIANGLES_SAMPLING 'T' -#define CMD_LINE_ARG_N_SAMPLES 'N' -#define CMD_LINE_ARG_SAMPLES_PER_AREA_UNIT 'A' -#define CMD_LINE_ARG_SAVE_DISPLACEMENT 'O' -#define CMD_LINE_ARG_SAVE_ERROR_AS_COLOUR 'C' -#define CMR_LINE_ARG_INCLUDE_UNREF 'U' - // error messages -#define MSG_ERR_N_ARGS "\nUsage: "\ - "metro file1 file2 [opt]\n"\ - "where opt can be:\n"\ - "-V disable vertex sampling\n"\ - "-U ignore unreferred vertices\n"\ - "-E disable edge sampling\n"\ - "-F disable face sampling\n"\ - "-Sx set the face sampling mode\n"\ - " where x can be:\n"\ - " -M montecarlo sampling\n"\ - " -S subdivision sampling\n"\ - " -T similar triangles sampling\n"\ - "-N# set the required number of samples (overrides -A)\n"\ - "-A# set the required number of samples per area unit (overrides -N)\n"\ - "-Hxxx.yyy save histogram of error values in the file xxx.yyy\n"\ - "-O save error as vertex quality\n"\ - "-C save error as vertex colour"\ - "\n" #define MSG_ERR_MESH_LOAD "error loading the input meshes.\n" #define MSG_ERR_INVALID_OPTION "unable to parse option '%s'\n" @@ -51,13 +18,6 @@ #define MIN_SIZE 125 /* 125 = 5^3 */ #define N_HIST_BINS 256 #define PRINT_EVERY_N_ELEMENTS 1000 -#define FILE_EXT_SMF "smf" -#define FILE_EXT_PLY "ply" - -// strings -#define STR_HIST_FILENAME_DEFAULT "hist.txt" -#define STR_NEW_MESH_FILENAME_DEFAULT "error.ply" -#define STR_NEW_MESH_FILENAME_DEFAULT_2 "error_colour.ply" // ----------------------------------------------------------------------------------------------- #endif diff --git a/apps/metro/metro.cpp b/apps/metro/metro.cpp index 3049d875..181362cb 100644 --- a/apps/metro/metro.cpp +++ b/apps/metro/metro.cpp @@ -24,12 +24,16 @@ History $Log: not supported by cvs2svn $ +Revision 1.4 2004/05/14 13:53:12 ganovelli +GPL added + ****************************************************************************/ // ----------------------------------------------------------------------------------------------- // standard libraries #include +#include // project definitions. #include "defs.h" @@ -37,184 +41,163 @@ $Log: not supported by cvs2svn $ #include "mesh_type.h" #include #include +#include +#include //#include #include +#include #include - // ----------------------------------------------------------------------------------------------- ////////////////// Command line Flags and parameters -bool ComputeHistFlag = false; -bool VertexSampleFlag = true; -bool EdgeSampleFlag = true; -bool FaceSampleFlag = true; -bool MontecarloSamplingFlag = false; -bool SubdivisionSamplingFlag = false; -bool SimilarTrianglesSamplingFlag = false; bool NumberOfSamples = false; bool SamplesPerAreaUnit = false; -bool SaveErrorDisplacement = false; -bool SaveErrorAsColour = false; -bool IncludeUnreferred = false; +bool CleaningFlag=false; // ----------------------------------------------------------------------------------------------- - -inline char* GetExtension(char* filename) +void Usage() { - size_t i; - for( i=strlen(filename)-1; i >= 0; i--) - if(filename[i] == '.') - break; - if(i > 0) - return &(filename[i+1]); - else - return NULL; + printf("\nUsage: "\ + "metro file1 file2 [opt]\n"\ + "where opt can be:\n"\ + "-v disable vertex sampling\n"\ + "-e disable edge sampling\n"\ + "-f disable face sampling\n"\ + "-u ignore unreferred vertices\n"\ + "-Sx set the face sampling mode\n"\ + " where x can be:\n"\ + " -S0 montecarlo sampling\n"\ + " -S1 subdivision sampling\n"\ + " -S2 similar triangles sampling (Default)\n"\ + "-n# set the required number of samples (overrides -A)\n"\ + "-a# set the required number of samples per area unit (overrides -N)\n"\ + "-c save error as vertex colour and quality"\ + "-C # # Set the min/max values used for color mapping"\ + "-L Remove duplicated and unreferenced vertices before processing"\ + "\n" + "Default options are to sample vertexes, edge and faces, to take a number of sample that is \n" + ); + exit(-1); +} + + +// simple aux function that compute the name for the file containing the stored computations +string SaveFileName(const string &filename) +{ + int pos=filename.find_last_of('.',filename.length()); + string fileout=filename.substr(0,pos)+"_metro.ply"; + return fileout; +} + + +// simple aux function that returns true if a given file has a given extesnion +bool FileExtension(string filename, string extension) +{ + locale loc1 ; + use_facet > ( loc1 ).tolower(&*filename.begin(),&*filename.end()); + use_facet > ( loc1 ).tolower(&*extension.begin(),&*extension.end()); + string end=filename.substr(filename.length()-extension.length(),extension.length()); + return end==extension; +} + +// Open Mesh +void OpenMesh(const char *filename, CMesh &m) +{ + int err; + if(FileExtension(filename,"ply")) + { + err = tri::io::ImporterPLY::Open(m,filename); + if(err) { + printf("Error in reading %s: '%s'\n",filename,tri::io::ImporterPLY::ErrorMsg(err)); + exit(-1); + } + printf("read mesh `%s'\n", filename); + } + else if(FileExtension(filename,"stl")) + { + err = tri::io::ImporterSTL::Open(m,filename); + if(err) { + printf("Error in reading %s: '%s'\n",filename,tri::io::ImporterSTL::ErrorMsg(err)); + exit(-1); + } + printf("read mesh `%s'\n", filename); + } + else { + printf("Unknown file format for mesh '%s'\n",filename); + exit(-1); + } + if(CleaningFlag){ + int dup = tri::Clean::RemoveDuplicateVertex(m); + int unref = tri::Clean::RemoveUnreferencedVertex(m); + printf("Removed %i duplicate and %i unreferenced vertices from mesh %s\n",dup,unref,filename); + } } int main(int argc, char**argv) { CMesh S1, S2; - double dist1_max, dist1_mean, dist1_RMS, volume_1; - double dist2_max, dist2_mean, dist2_RMS, volume_2; - double mesh_dist_max; - unsigned long n_samples_target, n_samples_output, elapsed_time; + double ColorMin=0, ColorMax=0; + double dist1_max, dist2_max; + unsigned long n_samples_target, elapsed_time; double n_samples_per_area_unit; - int flags, flags_fwd, flags_back, n_samples_area, n_samples_edge, n_samples_vertex, err; - char *fmt, *hist_filename, *new_mesh_filename, *new_mesh_filename_2; - char fname_1[] = STR_NEW_MESH_FILENAME_DEFAULT, fname_2[] = STR_NEW_MESH_FILENAME_DEFAULT_2; - //FILE *fd; - + int flags; + // print program info printf("-------------------------------\n" - " Metro\n" + " Metro V.4.0 \n" + " http://vcg.isti.cnr.it\n" " release date: "__DATE__"\n" "-------------------------------\n\n"); - // load input meshes. - if(argc <= 2) - { - printf(MSG_ERR_N_ARGS); - exit(-1); - } - - // load mesh M1. - if(!(fmt = GetExtension(argv[1]))) - { - printf(MSG_ERR_UNKNOWN_FORMAT, fmt); - exit(-1); - } - if(!strcmp("ply", fmt)) - { - printf("reading the mesh `%s'...", argv[1]); - err = tri::io::ImporterPLY::Open(S1,argv[1]); - } - /* else - if(!strcmp(file_ext_smf, fmt)) - { - printf("reading the mesh `%s'...", argv[1]); - err = tri::io::ImporterSMF::Open(S1,argv[1]); - }*/ - else - { - printf(MSG_ERR_UNKNOWN_FORMAT, fmt); - exit(-1); - } - if(err < 0) - { - printf("\n"); - printf(MSG_ERR_MESH_LOAD); - printf(" error number %d",err); - exit(-1); - } - else - printf("done\n"); - - // load mesh M2. - if(!(fmt = GetExtension(argv[2]))) - { - printf(MSG_ERR_UNKNOWN_FORMAT, fmt); - exit(-1); - } - if(!strcmp("ply", fmt)) - { - printf("reading the mesh `%s'...", argv[2]); - err = tri::io::ImporterPLY::Open(S2,argv[2]); - } - /*else - if(!strcmp(file_ext_smf, fmt)) - { - printf("reading the mesh `%s'...", argv[2]); - err = S2.Load_Smf(argv[2]); - }*/ - else - { - printf(MSG_ERR_UNKNOWN_FORMAT, fmt); - exit(-1); - } - if(err < 0) - { - printf(MSG_ERR_MESH_LOAD); - exit(-1); - } - else - printf("done\n"); + if(argc <= 2) Usage(); + // default parameters + flags = SamplingFlags::VERTEX_SAMPLING | + SamplingFlags::EDGE_SAMPLING | + SamplingFlags::FACE_SAMPLING | + SamplingFlags::SIMILAR_SAMPLING; // parse command line. - for(int i=3; i < argc;) - { - if(argv[i][0]=='-') - switch(argv[i][1]) - { - case CMD_LINE_ARG_HIST : ComputeHistFlag = true; hist_filename = &(argv[i][2]); - if(hist_filename[0] == '\0') - strcpy(hist_filename, STR_HIST_FILENAME_DEFAULT); - break; - case CMD_LINE_ARG_VERTEX_SAMPLE : VertexSampleFlag = false; break; - case CMR_LINE_ARG_INCLUDE_UNREF : IncludeUnreferred = true; break; - case CMD_LINE_ARG_EDGE_SAMPLE : EdgeSampleFlag = false; break; - case CMD_LINE_ARG_FACE_SAMPLE : FaceSampleFlag = false; break; - case CMD_LINE_ARG_SAMPLE_TYPE : - switch(argv[i][2]) - { - case CMD_LINE_ARG_MONTECARLO_SAMPLING : MontecarloSamplingFlag = true; break; - case CMD_LINE_ARG_SUBDIVISION_SAMPLING : SubdivisionSamplingFlag = true; break; - case CMD_LINE_ARG_SIMILAR_TRIANGLES_SAMPLING : SimilarTrianglesSamplingFlag = true; break; - default : printf(MSG_ERR_INVALID_OPTION, argv[i]); - exit(0); - } - break; - case CMD_LINE_ARG_N_SAMPLES : NumberOfSamples = true; n_samples_target = (unsigned long) atoi(&(argv[i][2])); break; - case CMD_LINE_ARG_SAMPLES_PER_AREA_UNIT : SamplesPerAreaUnit = true; n_samples_per_area_unit = (unsigned long) atoi(&(argv[i][2])); break; - case CMD_LINE_ARG_SAVE_DISPLACEMENT : SaveErrorDisplacement = true; new_mesh_filename = &(argv[i][2]); - if(new_mesh_filename[0] == '\0') - new_mesh_filename = fname_1; - break; - case CMD_LINE_ARG_SAVE_ERROR_AS_COLOUR : SaveErrorAsColour = true; new_mesh_filename_2 = &(argv[i][2]); - if(new_mesh_filename_2[0] == '\0') - new_mesh_filename_2 = fname_2; - break; - default : printf(MSG_ERR_INVALID_OPTION, argv[i]); - exit(0); - } - i++; - } - - // set sampling scheme - int sampling_method = MontecarloSamplingFlag + SubdivisionSamplingFlag + SimilarTrianglesSamplingFlag; - // defaults - if(!sampling_method) - SimilarTrianglesSamplingFlag = true; - if(sampling_method > 1) + for(int i=3; i < argc;) { - printf("Cannot choose more than one sampling method. Similar Triangles sampling assumed.\n"); - SimilarTrianglesSamplingFlag = true; - MontecarloSamplingFlag = false; - SubdivisionSamplingFlag = false; + if(argv[i][0]=='-') + switch(argv[i][1]) + { + case 'v' : flags &= ~SamplingFlags::VERTEX_SAMPLING; break; + case 'e' : flags &= ~SamplingFlags::EDGE_SAMPLING; break; + case 'f' : flags &= ~SamplingFlags::FACE_SAMPLING; break; + case 'u' : flags |= SamplingFlags::INCLUDE_UNREFERENCED_VERTICES; break; + case 's' : + switch(argv[i][2]) + { + case 0: flags = (flags | SamplingFlags::MONTECARLO_SAMPLING ) & (~ SamplingFlags::NO_SAMPLING );break; + case 1: flags = (flags | SamplingFlags::SUBDIVISION_SAMPLING ) & (~ SamplingFlags::NO_SAMPLING );break; + case 2: flags = (flags | SamplingFlags::SIMILAR_SAMPLING ) & (~ SamplingFlags::NO_SAMPLING );break; + default : printf(MSG_ERR_INVALID_OPTION, argv[i]); + exit(0); + } + break; + case 'n': NumberOfSamples = true; n_samples_target = (unsigned long) atoi(&(argv[i][2])); break; + case 'a': SamplesPerAreaUnit = true; n_samples_per_area_unit = (unsigned long) atoi(&(argv[i][2])); break; + case 'c': flags |= SamplingFlags::SAVE_ERROR; break; + case 'L': CleaningFlag=true; break; + case 'C': ColorMin=atof(argv[i+1]); ColorMax=atof(argv[i+2]); i+=2; break; + default : printf(MSG_ERR_INVALID_OPTION, argv[i]); + exit(0); + } + i++; } + + // load input meshes. + OpenMesh(argv[1],S1); + OpenMesh(argv[2],S2); + string S1NewName=SaveFileName(argv[1]); + string S2NewName=SaveFileName(argv[2]); + + if(!NumberOfSamples && !SamplesPerAreaUnit) { NumberOfSamples = true; @@ -234,52 +217,16 @@ int main(int argc, char**argv) bbox.Add(S1.bbox); bbox.Add(S2.bbox); bbox.InflateFix(0.02); - S1.bbox = bbox; - S2.bbox = bbox; - - // set flags. - flags = 0; - if(IncludeUnreferred) - flags |= SamplingFlags::INCLUDE_UNREFERENCED_VERTICES; - if(ComputeHistFlag) - flags |= SamplingFlags::HIST; - if(VertexSampleFlag) - flags |= SamplingFlags::VERTEX_SAMPLING; - if(EdgeSampleFlag) - flags |= SamplingFlags::EDGE_SAMPLING; - if(FaceSampleFlag) - flags |= SamplingFlags::FACE_SAMPLING; - if(MontecarloSamplingFlag) - flags |= SamplingFlags::MONTECARLO_SAMPLING; - if(SubdivisionSamplingFlag) - flags |= SamplingFlags::SUBDIVISION_SAMPLING; - if(SimilarTrianglesSamplingFlag) - flags |= SamplingFlags::SIMILAR_TRIANGLES_SAMPLING; - flags_fwd = flags; - flags_back = flags; - if(SaveErrorDisplacement) - { - if(S1.vn >= S2.vn) - flags_fwd |= SamplingFlags::SAVE_ERROR_DISPLACEMENT; - else - flags_back |= SamplingFlags::SAVE_ERROR_DISPLACEMENT; - } - - if(SaveErrorAsColour) - { - if(S1.vn >= S2.vn) - flags_fwd |= SamplingFlags::SAVE_ERROR_AS_COLOUR; - else - flags_back |= SamplingFlags::SAVE_ERROR_AS_COLOUR; - } + S1.bbox = bbox; + S2.bbox = bbox; // initialize time info. int t0=clock(); - // print mesh info. Sampling ForwardSampling(S1,S2); Sampling BackwardSampling(S2,S1); + // print mesh info. printf("Mesh info:\n"); printf(" M1: '%s'\n\t%vertices %7i\n\tfaces %7i\n\tarea %12.4f\n", argv[1], S1.vn, S1.fn, ForwardSampling.GetArea()); printf("\tbbox (%7.4f %7.4f %7.4f)-(%7.4f %7.4f %7.4f)\n", tmp_bbox_M1.min[0], tmp_bbox_M1.min[1], tmp_bbox_M1.min[2], tmp_bbox_M1.max[0], tmp_bbox_M1.max[1], tmp_bbox_M1.max[2]); @@ -290,7 +237,7 @@ int main(int argc, char**argv) // Forward distance. printf("\nForward distance (M1 -> M2):\n"); - ForwardSampling.SetFlags(flags_fwd); + ForwardSampling.SetFlags(flags); if(NumberOfSamples) { ForwardSampling.SetSamplesTarget(n_samples_target); @@ -304,23 +251,18 @@ int main(int argc, char**argv) printf("target # samples : %u\ntarget # samples/area : %f\n", n_samples_target, n_samples_per_area_unit); ForwardSampling.Hausdorff(); dist1_max = ForwardSampling.GetDistMax(); - dist1_mean = ForwardSampling.GetDistMean(); - dist1_RMS = ForwardSampling.GetDistRMS(); - volume_1 = ForwardSampling.GetDistVolume(); - n_samples_output = ForwardSampling.GetNSamples(); - n_samples_area = ForwardSampling.GetNAreaSamples(); - n_samples_edge = ForwardSampling.GetNEdgeSamples(); - n_samples_vertex = ForwardSampling.GetNVertexSamples(); - printf("\ndistance:\n max : %f (%f with respect to bounding box diagonal)\n mean : %f\n RMS : %f\n", (float)dist1_max, (float)dist1_max/bbox.Diag(), (float)dist1_mean, (float)dist1_RMS); - if(VertexSampleFlag) - printf("# vertex samples %d\n", n_samples_vertex); - if(EdgeSampleFlag) - printf("# edge samples %d\n", n_samples_edge); - printf("# area samples %d\n# total samples %d\nsamples per area unit: %f\n\n", n_samples_area, n_samples_output, ForwardSampling.GetNSamplesPerAreaUnit()); + printf("\ndistance:\n max : %f (%f with respect to bounding box diagonal)\n", (float)dist1_max, (float)dist1_max/bbox.Diag()); + printf(" mean : %f\n", ForwardSampling.GetDistMean()); + printf(" RMS : %f\n", ForwardSampling.GetDistRMS()); + printf("# vertex samples %9d\n", ForwardSampling.GetNVertexSamples()); + printf("# edge samples %9d\n", ForwardSampling.GetNEdgeSamples()); + printf("# area samples %9d\n", ForwardSampling.GetNAreaSamples()); + printf("# total samples %9d\n", ForwardSampling.GetNSamples()); + printf("# samples per area unit: %f\n\n", ForwardSampling.GetNSamplesPerAreaUnit()); // Backward distance. printf("\nBackward distance (M2 -> M1):\n"); - BackwardSampling.SetFlags(flags_back); + BackwardSampling.SetFlags(flags); if(NumberOfSamples) { BackwardSampling.SetSamplesTarget(n_samples_target); @@ -334,81 +276,38 @@ int main(int argc, char**argv) printf("target # samples : %u\ntarget # samples/area : %f\n", n_samples_target, n_samples_per_area_unit); BackwardSampling.Hausdorff(); dist2_max = BackwardSampling.GetDistMax(); - dist2_mean = BackwardSampling.GetDistMean(); - dist2_RMS = BackwardSampling.GetDistRMS(); - volume_2 = BackwardSampling.GetDistVolume(); - n_samples_output = BackwardSampling.GetNSamples(); - n_samples_area = BackwardSampling.GetNAreaSamples(); - n_samples_edge = BackwardSampling.GetNEdgeSamples(); - n_samples_vertex = BackwardSampling.GetNVertexSamples(); - printf("\ndistance:\n max : %f (%f with respect to bounding box diagonal)\n mean : %f\n RMS : %f\n", (float)dist2_max, (float)dist2_max/bbox.Diag(), (float)dist2_mean, (float)dist2_RMS); - if(VertexSampleFlag) - printf("# vertex samples %d\n", n_samples_vertex); - if(EdgeSampleFlag) - printf("# edge samples %d\n", n_samples_edge); - printf("# area samples %d\n# total samples %d\nsamples per area unit: %f\n\n", n_samples_area, n_samples_output, BackwardSampling.GetNSamplesPerAreaUnit()); + printf("\ndistance:\n max : %f (%f with respect to bounding box diagonal)\n", (float)dist1_max, (float)dist1_max/bbox.Diag()); + printf("mean : %f\n", BackwardSampling.GetDistMean()); + printf("RMS : %f\n", BackwardSampling.GetDistRMS()); + printf("# vertex samples %9d\n", BackwardSampling.GetNVertexSamples()); + printf("# edge samples %9d\n", BackwardSampling.GetNEdgeSamples()); + printf("# area samples %9d\n", BackwardSampling.GetNAreaSamples()); + printf("# total samples %9d\n", BackwardSampling.GetNSamples()); + printf("# samples per area unit: %f\n\n", BackwardSampling.GetNSamplesPerAreaUnit()); // compute time info. elapsed_time = clock() - t0; - - // save error distribution histogram - /*if(ComputeHistFlag) - { - const Hist &hist1 = ForwardSampling.GetHist(); - const Hist &hist2 = BackwardSampling.GetHist(); - if(!(fd = fopen(hist_filename, "w"))) - { - printf(MSG_ERR_FILE_OPEN); - exit(-1); - } - vector::const_iterator ii; - vector::const_iterator fi; - - fprintf(fd, "error distribution histogram (forward distance)\n\n"); - for(ii=hist1.H.begin(), fi=hist1.R.begin(); ii != hist1.H.end(); ++fi,ii++) - fprintf(fd, "%6.4f\t%d\n", *fi, *ii); - - fprintf(fd, "\n\nerror distribution histogram (backward distance)\n"); - for(ii=hist2.H.begin(), fi=hist2.R.begin(); ii != hist2.H.end(); ++fi,ii++) - fprintf(fd, "%6.4f\t%d\n", *fi, *ii); - - fclose(fd); - }*/ - - // max distance. - mesh_dist_max = max(dist1_max , dist2_max); - printf("\nHausdorff distance: %f (%f with respect to bounding box diagonal)\nComputation time : %d ms\n# samples/second : %f\n\n", (float)mesh_dist_max, (float)mesh_dist_max/bbox.Diag(), (int)elapsed_time, (float)n_samples_output/(float)elapsed_time*2000.0F); + int n_total_sample=ForwardSampling.GetNSamples()+BackwardSampling.GetNSamples(); + float mesh_dist_max = max(dist1_max , dist2_max); + + printf("\nHausdorff distance: %f (%f with respect to bounding box diagonal)\n",(float)mesh_dist_max,(float)mesh_dist_max/bbox.Diag()); + printf(" Computation time : %d ms\n", (int)elapsed_time); + printf(" # samples/second : %f\n\n", (float)n_total_sample/((float)elapsed_time/1000.0)); // save error files. - if((flags_fwd & SamplingFlags::SAVE_ERROR_DISPLACEMENT) && (flags_fwd & SamplingFlags::SAVE_ERROR_AS_COLOUR)) - // if(strcmp(new_mesh_filename, new_mesh_filename_2)) - { - vcg::tri::io::PlyInfo p; - p.mask|=vcg::tri::io::PLYMask::PM_VERTCOLOR|vcg::tri::io::PLYMask::PM_VERTQUALITY; + if(flags & SamplingFlags::SAVE_ERROR) + { + vcg::tri::io::PlyInfo p; + p.mask|=vcg::ply::PLYMask::PM_VERTCOLOR|vcg::ply::PLYMask::PM_VERTQUALITY; + if(ColorMax!=0 || ColorMin != 0){ + vcg::tri::UpdateColor::VertexQuality(S1,ColorMin,ColorMax); + vcg::tri::UpdateColor::VertexQuality(S2,ColorMin,ColorMax); + } + tri::io::ExporterPLY::Save( S1,S1NewName.c_str(),true,p); + tri::io::ExporterPLY::Save( S2,S2NewName.c_str(),true,p); + } - tri::io::ExporterPLY::Save( S1,new_mesh_filename,true,p); - exit(0); - } - if((flags_back & SamplingFlags::SAVE_ERROR_DISPLACEMENT) && (flags_back & SamplingFlags::SAVE_ERROR_AS_COLOUR)) - // if(strcmp(new_mesh_filename, new_mesh_filename_2)) - { - vcg::tri::io::PlyInfo p; - p.mask|=vcg::tri::io::PLYMask::PM_VERTCOLOR|vcg::tri::io::PLYMask::PM_VERTQUALITY; - tri::io::ExporterPLY::Save( S2,new_mesh_filename,true,p); - exit(0); - } - - //if(flags_fwd & SamplingFlags::SAVE_ERROR_DISPLACEMENT) - // S1.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR)); - //else - // if(flags_back & SamplingFlags::SAVE_ERROR_DISPLACEMENT) - // S2.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR)); - //if(flags_fwd & SamplingFlags::SAVE_ERROR_AS_COLOUR) - // S1.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY)); - //else - // if(flags_back & SamplingFlags::SAVE_ERROR_AS_COLOUR) - // S2.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY)); -return 0; + return 0; } // ----------------------------------------------------------------------------------------------- diff --git a/apps/metro/readme.txt b/apps/metro/readme.txt new file mode 100644 index 00000000..0c839027 --- /dev/null +++ b/apps/metro/readme.txt @@ -0,0 +1,69 @@ + +VCGLib http://vcg.sf.net o o +Visual and Computer Graphics Library o o + _ O _ +Copyright(C) 2004 \/)\/ +Visual Computing Lab http://vcg.isti.cnr.it /\/| +ISTI - Italian National Research Council | + \ +All rights reserved. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License (http://www.gnu.org/licenses/gpl.txt) +for more details. + +Metro is a tool designed to evaluate the difference between two triangular meshes. +Metro adopts an approximated approach based on surface sampling and point-to-surface distance computation. +Please, when using this tool cite the following reference: + +Papers +P. Cignoni, C. Rocchini and R. Scopigno +"Metro: measuring error on simplified surfaces" +Computer Graphics Forum, Blackwell Publishers, vol. 17(2), June 1998, pp 167-174 + + +For any question about this software please contact: +Paolo Cignoni ( p.cignoni@isti.cnr.it ) + + +Three different surface sampling methods are implemented: + + * Montecarlo sampling (pick k random samples in the interior of each face) + * Subdivision sampling (recursively subdivide each face along the longest edge and choose the sample in the center of each cell) + * Similar Triangles sampling (subdivide each face F in k polygons similar to F and sample the face in correspondence with the vertices of these polygons, internal to F) + +Note that the three methods described above are used to sample only the interior of each face. +A different scheme is used to sample vertices and edges: vertices are sampled in the straightforward manner, +while edges are sampled by uniformly interleaving samples along each edge. + +Basic usage + +Metro is a command-line tool which allows the user to select among different sampling schemes. +A list of the command-line parameters accepted by the tool is shown in the following. + +Usage: Metro file1 file2 [opts] + +where "file1" and "file2" are the input meshes in PLY or STL format, and opts can be: + + -v disable vertex sampling + -e disable edge sampling + -f disable face sampling + -u does not ignore unreferred vertices (sample also unreferenced vertices + (useful for sampling point clouds against meshes) + -Sx set the face sampling mode + where x can be: + -S0 montecarlo sampling + -S1 subdivision sampling + -S2 similar triangles sampling (Default) + -n# set the required number of samples (overrides -A) + -a# set the required number of samples per area unit (overrides -N) + -c save computed error as vertex colour and quality in two ply files + -C # # Set the min/max values used for color mapping (useful for taking snapshot with coherent color ramp) + -L Remove duplicated and unreferenced vertices before processing to avoid diff --git a/apps/metro/sampling.h b/apps/metro/sampling.h index a5cbbbec..ca3455e4 100644 --- a/apps/metro/sampling.h +++ b/apps/metro/sampling.h @@ -24,6 +24,9 @@ History $Log: not supported by cvs2svn $ +Revision 1.7 2004/05/14 13:49:07 ganovelli +created + Revision 1.6 2004/05/14 00:38:01 ganovelli a bit of cleaning: SamplingFlags struct added @@ -45,6 +48,7 @@ instantiate GridStaticPtr on the simplexClass template. #include #include #include +#include #include using namespace vcg; @@ -56,10 +60,10 @@ struct SamplingFlags{ FACE_SAMPLING = 0x0008, MONTECARLO_SAMPLING = 0x0010, SUBDIVISION_SAMPLING = 0x0020, - SIMILAR_TRIANGLES_SAMPLING = 0x0040, - SAVE_ERROR_DISPLACEMENT = 0x0080, - SAVE_ERROR_AS_COLOUR = 0x0100, - INCLUDE_UNREFERENCED_VERTICES = 0x0200 + SIMILAR_SAMPLING = 0x0040, + NO_SAMPLING = 0x0070, + SAVE_ERROR = 0x0100, + INCLUDE_UNREFERENCED_VERTICES = 0x0200, }; }; // ----------------------------------------------------------------------------------------------- @@ -170,7 +174,7 @@ Sampling::Sampling(MetroMesh &_s1, MetroMesh &_s2):S1(_s1),S2(_s2) inflate_percentage = 0.02; min_size = 125; /* 125 = 5^3 */ n_hist_bins = 256; - print_every_n_elements = 1000; + print_every_n_elements = S1.fn/100; referredBit = VertexType::NewUserBit(); // store the unreferred vertices @@ -267,23 +271,7 @@ void Sampling::VertexSampling() n_total_vertex_samples++; // save vertex quality - if(Flags & (SamplingFlags::SAVE_ERROR_DISPLACEMENT | SamplingFlags::SAVE_ERROR_AS_COLOUR)) - (*vi).Q() = error; - - - if(Flags & SamplingFlags::SAVE_ERROR_AS_COLOUR) - { - Color4b col = Color4b(Color4b::White); - - if(error < dist_upper_bound) - // colour mapped distance - col.ColorRamp(0, dist_upper_bound, dist_upper_bound-error); - //else - // no matching mesh patches -> white - - (*vi).C() = col; - } - + if(Flags & SamplingFlags::SAVE_ERROR) (*vi).Q() = error; // print progress information if(!(++cnt % print_every_n_elements)) @@ -582,7 +570,8 @@ void Sampling::Hausdorff() if(Flags & SamplingFlags::EDGE_SAMPLING) { EdgeSampling(); - n_samples_target -= (int) n_total_samples; + if(n_samples_target > n_total_samples) n_samples_target -= (int) n_total_samples; + else n_samples_target=0; } // Face sampling. if((Flags & SamplingFlags::FACE_SAMPLING) && (n_samples_target > 0)) @@ -590,36 +579,14 @@ void Sampling::Hausdorff() n_samples_per_area_unit = n_samples_target / area_S1; if(Flags & SamplingFlags::MONTECARLO_SAMPLING) MontecarloFaceSampling(); if(Flags & SamplingFlags::SUBDIVISION_SAMPLING) SubdivFaceSampling(); - if(Flags & SamplingFlags::SIMILAR_TRIANGLES_SAMPLING) SimilarFaceSampling(); + if(Flags & SamplingFlags::SIMILAR_SAMPLING) SimilarFaceSampling(); } } // compute vertex colour - if(Flags & SamplingFlags::SAVE_ERROR_AS_COLOUR) - { - VertexIterator vi; - float error; - int cnt = 0; - for(vi=S1.vert.begin();vi!=S1.vert.end();++vi) - { - Color4b col = Color4b(Color4b::White); - error = (*vi).Q(); - - if(error < dist_upper_bound) - // colour mapped distance - col.ColorRamp(0, (float)max_dist, (float)max_dist-error); - //else - // no matching mesh patches -> white - - (*vi).C() = col; - - // print progress information - if(!(++cnt % print_every_n_elements)) - printf("Computing vertex colour %d%%\r", (100 * cnt/S1.vn)); - } - printf(" \r"); - } - + if(Flags & SamplingFlags::SAVE_ERROR) + vcg::tri::UpdateColor::VertexQuality(S1); + // compute statistics n_samples_per_area_unit = (double) n_total_samples / area_S1; volume = mean_dist / n_samples_per_area_unit / 2.0;