Official Release of Metro 4.00
This commit is contained in:
parent
4333c2177d
commit
21df27313d
|
@ -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
|
||||
|
|
|
@ -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 <time.h>
|
||||
#include <locale>
|
||||
|
||||
// project definitions.
|
||||
#include "defs.h"
|
||||
|
@ -37,184 +41,163 @@ $Log: not supported by cvs2svn $
|
|||
#include "mesh_type.h"
|
||||
#include <vcg/complex/trimesh/update/edges.h>
|
||||
#include <vcg/complex/trimesh/update/bounding.h>
|
||||
#include <vcg/math/histogram.h>
|
||||
#include <vcg/complex/trimesh/clean.h>
|
||||
//#include <wrap/io_trimesh/import_smf.h>
|
||||
#include <wrap/io_trimesh/import_ply.h>
|
||||
#include <wrap/io_trimesh/import_stl.h>
|
||||
#include <wrap/io_trimesh/export_ply.h>
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
////////////////// 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<ctype<char> > ( loc1 ).tolower(&*filename.begin(),&*filename.end());
|
||||
use_facet<ctype<char> > ( 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<CMesh>::Open(m,filename);
|
||||
if(err) {
|
||||
printf("Error in reading %s: '%s'\n",filename,tri::io::ImporterPLY<CMesh>::ErrorMsg(err));
|
||||
exit(-1);
|
||||
}
|
||||
printf("read mesh `%s'\n", filename);
|
||||
}
|
||||
else if(FileExtension(filename,"stl"))
|
||||
{
|
||||
err = tri::io::ImporterSTL<CMesh>::Open(m,filename);
|
||||
if(err) {
|
||||
printf("Error in reading %s: '%s'\n",filename,tri::io::ImporterSTL<CMesh>::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<CMesh>::RemoveDuplicateVertex(m);
|
||||
int unref = tri::Clean<CMesh>::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<CMesh>::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<CMesh>::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<CMesh> ForwardSampling(S1,S2);
|
||||
Sampling<CMesh> 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<int>::const_iterator ii;
|
||||
vector<float>::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<CMesh>::VertexQuality(S1,ColorMin,ColorMax);
|
||||
vcg::tri::UpdateColor<CMesh>::VertexQuality(S2,ColorMin,ColorMax);
|
||||
}
|
||||
tri::io::ExporterPLY<CMesh>::Save( S1,S1NewName.c_str(),true,p);
|
||||
tri::io::ExporterPLY<CMesh>::Save( S2,S2NewName.c_str(),true,p);
|
||||
}
|
||||
|
||||
tri::io::ExporterPLY<CMesh>::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<CMesh>::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;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
|
@ -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 <vcg/space/box3.h>
|
||||
#include <vcg/space/color4.h>
|
||||
#include <vcg/simplex/face/distance.h>
|
||||
#include <vcg/complex/trimesh/update/color.h>
|
||||
#include <vcg/space/index/grid_static_ptr.h>
|
||||
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<MetroMesh>::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<MetroMesh>::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<MetroMesh>::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<MetroMesh>::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<MetroMesh>::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;
|
||||
|
|
Loading…
Reference in New Issue