Official Release of Metro 4.00

This commit is contained in:
Paolo Cignoni 2004-06-24 09:08:31 +00:00
parent 4333c2177d
commit 21df27313d
4 changed files with 255 additions and 360 deletions

View File

@ -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

View File

@ -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;
}
// -----------------------------------------------------------------------------------------------

69
apps/metro/readme.txt Normal file
View File

@ -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

View File

@ -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;