re-created

This commit is contained in:
ganovelli 2004-05-05 11:30:37 +00:00
parent dd50627cba
commit 9dfae21460
6 changed files with 1356 additions and 0 deletions

63
apps/metro/defs.h Normal file
View File

@ -0,0 +1,63 @@
// -----------------------------------------------------------------------------------------------
#ifndef _DEFS_H
#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'
// error messages
#define MSG_ERR_N_ARGS "\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"\
"-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"
#define MSG_ERR_FILE_OPEN "unable to open the output file.'n"
#define MSG_ERR_UNKNOWN_FORMAT "unknown file format '%s'.\n"
// global constants
#define NO_SAMPLES_PER_FACE 10
#define N_SAMPLES_EDGE_TO_FACE_RATIO 0.1
#define BBOX_FACTOR 0.1
#define INFLATE_PERCENTAGE 0.02
#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
// -----------------------------------------------------------------------------------------------

49
apps/metro/error.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef __METRO__VCG__HAUS
#define __METRO__VCG__HAUS
#include "sampling.h"
template <class MESH_TYPE>
double Distance(MESH_TYPE & S1,MESH_TYPE & S2){
int flags = 0x18;
int n_samples_target = 1.5 * __max(S1.fn,S2.fn);
double dist12_max,dist21_max;
// compute face information
tri::UpdateEdges::Set(S1);
tri::UpdateEdges::Set(S2);
// set bounding boxes for S1 and S2
tri::UpdateBounding::Box(S1);
tri::UpdateBounding::Box(S2);
// set Bounding Box.
Box3<typename MESH_TYPE::ScalarType> bbox, tmp_bbox_M1=S1.bbox, tmp_bbox_M2=S2.bbox;
bbox.Add(S1.bbox);
bbox.Add(S2.bbox);
bbox.InflateFix(0.1);
S1.bbox = bbox;
S2.bbox = bbox;
Sampling<MESH_TYPE> ForwardSampling(S1,S2);
Sampling<MESH_TYPE> BackwardSampling(S2,S1);
ForwardSampling.SetFlags(flags);
BackwardSampling.SetFlags(flags);
ForwardSampling.SetSamplesTarget(n_samples_target);
BackwardSampling.SetSamplesTarget(n_samples_target);
ForwardSampling.Hausdorff();
dist12_max = ForwardSampling.GetDistMax();
BackwardSampling.Hausdorff();
dist21_max = BackwardSampling.GetDistMax();
return math::Max(dist12_max,dist12_max);
}
#endif

56
apps/metro/mesh_type.h Normal file
View File

@ -0,0 +1,56 @@
/*****************************************************************************
* VCGLib *
* *
* Visual Computing Group o> *
* IEI Institute, CNUCE Institute, CNR Pisa <| *
* / \ *
* Copyright(C) 1999 by Paolo Cignoni, Claudio Rocchini *
* All rights reserved. *
* *
* Permission to use, copy, modify, distribute and sell this software and *
* its documentation for any purpose is hereby granted without fee, provided *
* that the above copyright notice appear in all copies and that both that *
* copyright notice and this permission notice appear in supporting *
* documentation. the author makes no representations about the suitability *
* of this software for any purpose. It is provided "as is" without express *
* or implied warranty. *
* *
*****************************************************************************/
/****************************************************************************
History
2003 Dic 17 modifiche per conversione alla versione template (gano)
****************************************************************************/
// -----------------------------------------------------------------------------------------------
#ifndef _CMESH_H
#define _CMESH_H
// -----------------------------------------------------------------------------------------------
#pragma warning(disable:4786 4804 4666)
// standard libraries.
#include <math.h>
// VCG library.
//#include <vcg/tools/plylib.h>
#include <vcg/simplex/vertex/with/cmnq.h>
#include <vcg/simplex/face/with/rtfmfn.h>
#include <vcg/space/index/grid_static_obj.h>
#include <vcg/complex/trimesh/base.h>
using namespace vcg;
using namespace std;
// Vertex, Face, Mesh and Grid definitions.
class MyEdge;
class CFace;
class CVertex : public VertexCMNQ< double,MyEdge,CFace > {};
class CFace : public FaceRTFMFN< CVertex > {public:
CFace*& F(const int j){ return (CFace*&) FaceRTFMFN<CVertex>::F(j);}
};
class CMesh : public tri::TriMesh< vector<CVertex>, vector<CFace> > {};
// -----------------------------------------------------------------------------------------------
#endif
// -----------------------------------------------------------------------------------------------

375
apps/metro/metro.cpp Normal file
View File

@ -0,0 +1,375 @@
// -----------------------------------------------------------------------------------------------
// standard libraries
#include <time.h>
// project definitions.
#include "defs.h"
#include "sampling.h"
#include "mesh_type.h"
#include <vcg/complex/trimesh/update/edges.h>
#include <vcg/complex/trimesh/update/bounding.h>
//#include <wrap/io_trimesh/import_smf.h>
#include <wrap/io_trimesh/import_ply.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;
// -----------------------------------------------------------------------------------------------
inline char* GetExtension(char* filename)
{
for(int i=strlen(filename)-1; i >= 0; i--)
if(filename[i] == '.')
break;
if(i > 0)
return &(filename[i+1]);
else
return NULL;
}
void 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 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;
// print program info
printf("-------------------------------\n"
" Metro\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(!_stricmp(FILE_EXT_PLY, fmt))
{
printf("reading the mesh `%s'...", argv[1]);
err = tri::io::ImporterPLY<CMesh>::Open(S1,argv[1]);
}
/* else
if(!_stricmp(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);
exit(-1);
}
else
printf("done\n");
// load mesh M2.
if(!(fmt = GetExtension(argv[2])))
{
printf(MSG_ERR_UNKNOWN_FORMAT, fmt);
exit(-1);
}
if(!_stricmp(FILE_EXT_PLY, fmt))
{
printf("reading the mesh `%s'...", argv[2]);
err = tri::io::ImporterPLY<CMesh>::Open(S2,argv[2]);
}
/*else
if(!_stricmp(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");
// 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 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 = atoi(&(argv[i][2])); break;
case CMD_LINE_ARG_SAMPLES_PER_AREA_UNIT : SamplesPerAreaUnit = true; n_samples_per_area_unit = (double) atof(&(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)
{
printf("Cannot choose more than one sampling method. Similar Triangles sampling assumed.\n");
SimilarTrianglesSamplingFlag = true;
MontecarloSamplingFlag = false;
SubdivisionSamplingFlag = false;
}
if(!NumberOfSamples && !SamplesPerAreaUnit)
{
NumberOfSamples = true;
n_samples_target = NO_SAMPLES_PER_FACE * max(S1.fn,S2.fn);
}
// compute face information
tri::UpdateEdges<CMesh>::Set(S1);
tri::UpdateEdges<CMesh>::Set(S2);
// set bounding boxes for S1 and S2
tri::UpdateBounding<CMesh>::Box(S1);
tri::UpdateBounding<CMesh>::Box(S2);
// set Bounding Box.
Box3d bbox, tmp_bbox_M1=S1.bbox, tmp_bbox_M2=S2.bbox;
bbox.Add(S1.bbox);
bbox.Add(S2.bbox);
bbox.InflateFix(INFLATE_PERCENTAGE);
S1.bbox = bbox;
S2.bbox = bbox;
// set flags.
flags = 0;
if(ComputeHistFlag)
flags |= FLAG_HIST;
if(VertexSampleFlag)
flags |= FLAG_VERTEX_SAMPLING;
if(EdgeSampleFlag)
flags |= FLAG_EDGE_SAMPLING;
if(FaceSampleFlag)
flags |= FLAG_FACE_SAMPLING;
if(MontecarloSamplingFlag)
flags |= FLAG_MONTECARLO_SAMPLING;
if(SubdivisionSamplingFlag)
flags |= FLAG_SUBDIVISION_SAMPLING;
if(SimilarTrianglesSamplingFlag)
flags |= FLAG_SIMILAR_TRIANGLES_SAMPLING;
flags_fwd = flags;
flags_back = flags;
if(SaveErrorDisplacement)
{
if(S1.vn >= S2.vn)
flags_fwd |= FLAG_SAVE_ERROR_DISPLACEMENT;
else
flags_back |= FLAG_SAVE_ERROR_DISPLACEMENT;
}
if(SaveErrorAsColour)
{
if(S1.vn >= S2.vn)
flags_fwd |= FLAG_SAVE_ERROR_AS_COLOUR;
else
flags_back |= FLAG_SAVE_ERROR_AS_COLOUR;
}
// initialize time info.
int t0=clock();
// print mesh info.
Sampling<CMesh> ForwardSampling(S1,S2);
Sampling<CMesh> BackwardSampling(S2,S1);
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]);
printf("\tbbox diagonal %f\n", (float)tmp_bbox_M1.Diag());
printf(" M2: '%s'\n\t%vertices %7i\n\tfaces %7i\n\tarea %12.4f\n", argv[2], S2.vn, S2.fn, BackwardSampling.GetArea());
printf("\tbbox (%7.4f %7.4f %7.4f)-(%7.4f %7.4f %7.4f)\n", tmp_bbox_M2.min[0], tmp_bbox_M2.min[1], tmp_bbox_M2.min[2], tmp_bbox_M2.max[0], tmp_bbox_M2.max[1], tmp_bbox_M2.max[2]);
printf("\tbbox diagonal %f\n", (float)tmp_bbox_M2.Diag());
// Forward distance.
printf("\nForward distance (M1 -> M2):\n");
ForwardSampling.SetFlags(flags_fwd);
if(NumberOfSamples)
{
ForwardSampling.SetSamplesTarget(n_samples_target);
n_samples_per_area_unit = ForwardSampling.GetNSamplesPerAreaUnit();
}
else
{
ForwardSampling.SetSamplesPerAreaUnit(n_samples_per_area_unit);
n_samples_target = ForwardSampling.GetNSamplesTarget();
}
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());
// Backward distance.
printf("\nBackward distance (M2 -> M1):\n");
BackwardSampling.SetFlags(flags_back);
if(NumberOfSamples)
{
BackwardSampling.SetSamplesTarget(n_samples_target);
n_samples_per_area_unit = BackwardSampling.GetNSamplesPerAreaUnit();
}
else
{
BackwardSampling.SetSamplesPerAreaUnit(n_samples_per_area_unit);
n_samples_target = BackwardSampling.GetNSamplesTarget();
}
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());
// 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);
// save error files.
if((flags_fwd & FLAG_SAVE_ERROR_DISPLACEMENT) && (flags_fwd & FLAG_SAVE_ERROR_AS_COLOUR))
if(!strcmp(new_mesh_filename, new_mesh_filename_2))
{
tri::io::ExporterPLY<CMesh>::Save( S1,new_mesh_filename);
exit(0);
}
if((flags_back & FLAG_SAVE_ERROR_DISPLACEMENT) && (flags_back & FLAG_SAVE_ERROR_AS_COLOUR))
if(!strcmp(new_mesh_filename, new_mesh_filename_2))
{
tri::io::ExporterPLY<CMesh>::Save( S2,new_mesh_filename_2);
exit(0);
}
//if(flags_fwd & FLAG_SAVE_ERROR_DISPLACEMENT)
// S1.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR));
//else
// if(flags_back & FLAG_SAVE_ERROR_DISPLACEMENT)
// S2.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR));
//if(flags_fwd & FLAG_SAVE_ERROR_AS_COLOUR)
// S1.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY));
//else
// if(flags_back & FLAG_SAVE_ERROR_AS_COLOUR)
// S2.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY));
}
// -----------------------------------------------------------------------------------------------

206
apps/metro/min_dist_point.h Normal file
View File

@ -0,0 +1,206 @@
/*#***************************************************************************
* MinDistPoint.h o o *
* o o *
* Visual Computing Group _ O _ *
* IEI Institute, CNUCE Institute, CNR Pisa \/)\/ *
* /\/| *
* Copyright(C) 1999 by Paolo Cignoni, Paolo Pingi, Claudio Rocchini | *
* All rights reserved. \ *
* *
* Permission to use, copy, modify, distribute and sell this software and *
* its documentation for any purpose is hereby granted without fee, provided *
* that the above copyright notice appear in all copies and that both that *
* copyright notice and this permission notice appear in supporting *
* documentation. the author makes no representations about the suitability *
* of this software for any purpose. It is provided "as is" without express *
* or implied warranty. *
* *
* NOTE THAT THIS FILE SHOULD NOT DIRECTL BE INCLUDED *
* It is automatically included by Mesh.h *
* *
***************************************************************************#*/
/*#**************************************************************************
History
2000 Nov 06 First Working release (pc)
08 Aggiunto if(gr.bbox.IsIn(p)) per evitare piantamenti se si chiede
un punto fuori.
Tolto un Normalize inutile
2001 May 17 Aggiunta versione della Mindistpoint che da anche le coord
baricentriche del punto trovato (pc); aggiunto wrapper per la vecchia
versione.
Dec 10 Corretto prodotto scalare vettore nell'ordine giusto in un paio di posti
2002 Mar 29 Templatata anche in funzione del tipo scalare. (pc)
Oct 24 Corretti warning (unsigned mismatch) del vc7,
2003 Apr 15 Corretti mismatch iterator / pointer
Jun 08 Aggiornato UGridLink -> UGrid::Link
2004 Gen 09 Aggiunte le inclusioni a Point3[4].h
2004 Gen 19 Corretto qualche ->Normal() in ->cN()
****************************************************************************/
#ifndef __VCG_MINDISTPOINT
#define __VCG_MINDISTPOINT
#include <math.h>
#include <vcg/space/point3.h>
#include <vcg/space/Point4.h>
#include <vcg/math/base.h>
using namespace vcg;
/*
aka MetroCore
data una mesh m e una ug sulle sue facce trova il punto di m piu' vicino ad
un punto dato.
*/
// input: mesh, punto, griglia, distanza limite
// output: normale alla faccia e punto piu' vicino su di essa
// Nota che il parametro template GRID non ci dovrebbe essere, visto che deve essere
// UGrid<MESH::FaceContainer >, ma non sono riuscito a definirlo implicitamente
template <class MESH, class GRID, class SCALAR>
void MinDistPoint( MESH & mesh, const Point3<SCALAR> & p, GRID & gr, SCALAR & mdist,
Point3<SCALAR> & normf, Point3<SCALAR> & bestq, typename MESH::FaceType * &f, Point3<SCALAR> &ip)
{
typedef SCALAR scalar;
typedef Point3<scalar> Point3x;
typedef Box3<SCALAR> Box3x;
if(!gr.bbox.IsIn(p)) return;
typedef GridStaticObj<typename MESH::FaceContainer>::Link A2UGridLink;
scalar ax = p[0] - gr.bbox.min[0]; // Real coodinate of point refer to
scalar ay = p[1] - gr.bbox.min[1];
scalar az = p[2] - gr.bbox.min[2];
int gx = int( ax/gr.voxel[0] ); // Integer coordinate of the point
int gy = int( ay/gr.voxel[1] ); // voxel
int gz = int( az/gr.voxel[2] );
scalar vx = gr.bbox.min[0]+gx*gr.voxel[0]; // Real world coordinate of the Voxel
scalar vy = gr.bbox.min[1]+gy*gr.voxel[1]; // origin
scalar vz = gr.bbox.min[2]+gz*gr.voxel[2];
scalar dx = math::Min(p[0] - vx, vx+gr.voxel[0]-p[0]); // Dist from the voxel
scalar dy = math::Min(p[1] - vy, vy+gr.voxel[1]-p[1]);
scalar dz = math::Min(p[2] - vz, vz+gr.voxel[2]-p[2]);
scalar vdist,vstep;
if(dx<dy && dx<dz)
{
vdist = dx;
vstep = gr.voxel[0];
}
else if(dy<dz)
{
vdist = dy;
vstep = gr.voxel[1];
}
else
{
vdist = dz;
vstep = gr.voxel[2];
}
//scalar error = gr.bbox.SquaredDiag();
//scalar error = gr.bbox.Diag();
scalar error = mdist;
Point3x q;
MESH::FaceIterator bestf = 0;
mesh.UnMarkAll();
int mxsd = gr.siz[0];
if(mxsd<gr.siz[1]) mxsd = gr.siz[1];
if(mxsd<gr.siz[2]) mxsd = gr.siz[2];
for(int s=0;s<mxsd;++s)
{
if(s==0)
{
A2UGridLink *first, *last, *l;
gr.Grid( gx, gy, gz, first, last );
for(l=first;l!=last;++l)
if( ! mesh.IsMarked( &*(l->Elem())) )
{
if( (*(l->Elem())).Dist( p, error, q) )
{
bestq = q;
bestf = l->Elem();
MESH::ScalarType alfa=1, beta=1, gamma=1;
//bestf->InterpolationParameters(q, alfa, beta);
//calcolo normale con interpolazione trilineare
/*normf = (1-(alfa+beta))*(bestf->V(0)->Normal())+
(alfa*(bestf->V(1)->Normal()))+
(beta*(bestf->V(2)->Normal()));*/
bool ret=bestf->InterpolationParameters(q, alfa, beta, gamma);
//assert(ret);
normf = (bestf->V(0)->cN())*alfa+
(bestf->V(1)->cN())*beta+
(bestf->V(2)->cN())*gamma;
normf.Normalize();
ip[0]=alfa;ip[1]=beta;ip[2]=gamma;
}
mesh.Mark( &*(l->Elem()) );
}
}
else
{
for(int ix=gx-s;ix<=gx+s;++ix)
if( ix>=0 && ix<gr.siz[0] )
{
for(int iy=gy-s;iy<=gy+s;++iy)
if( iy>=0 && iy<gr.siz[1] )
{
int sz = ( ix==gx-s || ix==gx+s ||
iy==gy-s || iy==gy+s )?1:2*s;
for(int iz=gz-s;iz<=gz+s;iz+=sz)
if( iz>=0 && iz<gr.siz[2] )
{
A2UGridLink *first, *last, *l;
gr.Grid( ix, iy, iz, first, last );
for(l=first;l!=last;++l)
if( ! mesh.IsMarked( &*(l->Elem())) )
{
if( (*(l->Elem())).Dist( p, error, q) )
{
bestq = q;
bestf = l->Elem();
MESH::ScalarType alfa, beta, gamma;
//bestf->InterpolationParameters(q, alfa, beta);
//calcolo normale con interpolazione trilineare
bestf->InterpolationParameters(q, alfa, beta, gamma);
normf = (bestf->V(0)->cN())*alfa+
(bestf->V(1)->cN())*beta+
(bestf->V(2)->cN())*gamma ;
ip[0]=alfa;ip[1]=beta;ip[2]=gamma;
//normf.Normalize(); inutile si assume le normali ai vertici benfatte
}
mesh.Mark(&*l->Elem());
}
}
}
}
}
if( fabs(error)<vdist )
break;
vdist += vstep;
}
f=&*bestf;
mdist = scalar(fabs(error));
}
template <class MESH, class GRID, class SCALAR>
void MinDistPoint( MESH & mesh, const Point3<SCALAR> & p, GRID & gr, SCALAR & mdist,
Point3<SCALAR> & normf, Point3<SCALAR> & bestq, typename MESH::face_type * &f)
{
Point3<SCALAR> ip;
MinDistPoint(mesh,p,gr,mdist,normf,bestq,f,ip);
}
#endif

607
apps/metro/sampling.h Normal file
View File

@ -0,0 +1,607 @@
/*****************************************************************************
* VCGLib *
* *
* Visual Computing Group o> *
* IEI Institute, CNUCE Institute, CNR Pisa <| *
* / \ *
* Copyright(C) 1999 by Paolo Cignoni, Claudio Rocchini *
* All rights reserved. *
* *
* Permission to use, copy, modify, distribute and sell this software and *
* its documentation for any purpose is hereby granted without fee, provided *
* that the above copyright notice appear in all copies and that both that *
* copyright notice and this permission notice appear in supporting *
* documentation. the author makes no representations about the suitability *
* of this software for any purpose. It is provided "as is" without express *
* or implied warranty. *
* *
*****************************************************************************/
/****************************************************************************
History
2003 Dic 17 modifiche per conversione alla versione template (gano)
2004 Jan 19 qualche ->P() in ->cP() (Snarf)
****************************************************************************/
// -----------------------------------------------------------------------------------------------
#ifndef _SAMPLING_H
#define _SAMPLING_H
// -----------------------------------------------------------------------------------------------
// standard libraries.
#include <time.h>
// VCG library.
//#include <vcg/tools/xml/xml.h>
#include "min_dist_point.h"
//#include <vcg/tools/Align/Hist.h>
#include <vcg/space/box3.h>
#include <vcg/space/color4.h>
#include <vcg/space/index/grid_static_obj.h>
using namespace vcg;
// -----------------------------------------------------------------------------------------------
// flags.
#define FLAG_HIST 0x0001
#define FLAG_VERTEX_SAMPLING 0x0002
#define FLAG_EDGE_SAMPLING 0x0004
#define FLAG_FACE_SAMPLING 0x0008
#define FLAG_MONTECARLO_SAMPLING 0x0010
#define FLAG_SUBDIVISION_SAMPLING 0x0020
#define FLAG_SIMILAR_TRIANGLES_SAMPLING 0x0040
#define FLAG_SAVE_ERROR_DISPLACEMENT 0x0080
#define FLAG_SAVE_ERROR_AS_COLOUR 0x0100
// global constants
#define NO_SAMPLES_PER_FACE 10
#define N_SAMPLES_EDGE_TO_FACE_RATIO 0.1
#define BBOX_FACTOR 0.1
#define INFLATE_PERCENTAGE 0.02
#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"
// -----------------------------------------------------------------------------------------------
template <class MetroMesh>
class Sampling
{
private:
typedef GridStaticObj< typename MetroMesh::FaceContainer > MetroMeshGrid;
typedef Point3<typename MetroMesh::ScalarType> Point3x;
// data structures
MetroMesh &S1;
MetroMesh &S2;
MetroMeshGrid gS2;
// parameters
double dist_upper_bound;
double n_samples_per_area_unit;
double n_samples_target;
int Flags;
// results
// Hist hist;
unsigned long n_total_samples;
unsigned long n_total_area_samples;
unsigned long n_total_edge_samples;
unsigned long n_total_vertex_samples;
double max_dist;
double mean_dist;
double RMS_dist;
double volume;
double area_S1;
// globals
int n_samples;
// private methods
inline double ComputeMeshArea(MetroMesh & mesh);
float AddSample(const Point3x &p);
inline void AddRandomSample(typename MetroMesh::FaceIterator &T);
inline void SampleEdge(const Point3x & v0, const Point3x & v1, int n_samples_per_edge);
void VertexSampling();
void EdgeSampling();
void FaceSubdiv(const Point3x & v0, const Point3x &v1, const Point3x & v2, int maxdepth);
void SimilarTriangles(const Point3x &v0, const Point3x &v1, const Point3x &v2, int n_samples_per_edge);
void MontecarloFaceSampling();
void SubdivFaceSampling();
void SimilarFaceSampling();
public :
// public methods
Sampling(MetroMesh &_s1, MetroMesh &_s2);
void Hausdorff();
double GetArea() {return area_S1;}
double GetDistMax() {return max_dist;}
double GetDistMean() {return mean_dist;}
double GetDistRMS() {return RMS_dist;}
double GetDistVolume() {return volume;}
double GetNSamples() {return n_total_samples;}
double GetNAreaSamples() {return n_total_area_samples;}
double GetNEdgeSamples() {return n_total_edge_samples;}
double GetNVertexSamples() {return n_total_vertex_samples;}
double GetNSamplesPerAreaUnit() {return n_samples_per_area_unit;}
double GetNSamplesTarget() {return n_samples_target;}
// Hist &GetHist() {return hist;}
void SetFlags(int flags) {Flags = flags;}
void ClearFlag(int flag) {Flags &= (flag ^ -1);}
void SetParam(double _n_samp) {n_samples_target = _n_samp;}
void SetSamplesTarget(int _n_samp);
void SetSamplesPerAreaUnit(double _n_samp);
};
// -----------------------------------------------------------------------------------------------
// constructor
template <class MetroMesh>
Sampling<MetroMesh>::Sampling(MetroMesh &_s1, MetroMesh &_s2):S1(_s1),S2(_s2)
{
Flags = 0;
area_S1 = ComputeMeshArea(_s1);
}
// set sampling parameters
template <class MetroMesh>
void Sampling<MetroMesh>::SetSamplesTarget(int _n_samp)
{
n_samples_target = _n_samp;
n_samples_per_area_unit = (double) n_samples_target / area_S1;
}
template <class MetroMesh>
void Sampling<MetroMesh>::SetSamplesPerAreaUnit(double _n_samp)
{
n_samples_per_area_unit = _n_samp;
n_samples_target = (int)((double) n_samples_per_area_unit * area_S1);
}
// auxiliary functions
template <class MetroMesh>
inline double Sampling<MetroMesh>::ComputeMeshArea(MetroMesh & mesh)
{
MetroMesh::FaceIterator face;
double area = 0.0;
for(face=mesh.face.begin(); face != mesh.face.end(); face++)
if(!(*face).IsD())
area += face->Area();
return area;
}
template <class MetroMesh>
float Sampling<MetroMesh>::AddSample(const Point3x &p)
{
MetroMesh::FaceType *f=0;
Point3x normf, bestq, ip;
MetroMesh::ScalarType dist;
dist = dist_upper_bound;
// compute distance between p_i and the mesh S2
MinDistPoint(S2, p, gS2, dist, normf, bestq, f, ip);
// update distance measures
if(dist == dist_upper_bound)
return -1.0;
if(dist > max_dist)
max_dist = dist; // L_inf
mean_dist += dist; // L_1
RMS_dist += dist*dist; // L_2
n_total_samples++;
//if(Flags & FLAG_HIST)
// hist.Add((float)fabs(dist));
return (float)dist;
}
// -----------------------------------------------------------------------------------------------
// --- Vertex Sampling ---------------------------------------------------------------------------
template <class MetroMesh>
void Sampling<MetroMesh>::VertexSampling()
{
// Vertex sampling.
int cnt = 0;
float error;
printf("Vertex sampling\n");
MetroMesh::VertexIterator vi;
for(vi=S1.vert.begin();vi!=S1.vert.end();++vi)
{
error = AddSample((*vi).cP());
n_total_vertex_samples++;
// save vertex quality
if(Flags & (FLAG_SAVE_ERROR_DISPLACEMENT | FLAG_SAVE_ERROR_AS_COLOUR))
(*vi).Q() = error;
/*
if(Flags & FLAG_SAVE_ERROR_AS_COLOUR)
{
ColorUB col = ColorUB(ColorUB::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;
}
*/
// print progress information
if(!(++cnt % PRINT_EVERY_N_ELEMENTS))
printf("Sampling vertices %d%%\r", (100 * cnt/S1.vn));
}
printf(" \r");
}
// -----------------------------------------------------------------------------------------------
// --- Edge Sampling -----------------------------------------------------------------------------
template <class MetroMesh>
inline void Sampling<MetroMesh>::SampleEdge(const Point3x & v0, const Point3x & v1, int n_samples_per_edge)
{
// uniform sampling of the segment v0v1.
Point3x e((v1-v0)/(double)(n_samples_per_edge+1));
int i;
for(i=1; i <= n_samples_per_edge; i++)
{
AddSample(v0 + e*i);
n_total_edge_samples++;
}
}
template <class MetroMesh>
void Sampling<MetroMesh>::EdgeSampling()
{
// Edge sampling.
typedef pair<typename MetroMesh::VertexPointer, typename MetroMesh::VertexPointer> pvv;
vector< pvv > Edges;
printf("Edge sampling\n");
// compute edge list.
MetroMesh::FaceIterator fi;
for(fi=S1.face.begin(); fi != S1.face.end(); fi++)
for(int i=0; i<3; ++i)
{
Edges.push_back(make_pair((*fi).V0(i),(*fi).V1(i)));
if(Edges.back().first > Edges.back().second)
swap(Edges.back().first, Edges.back().second);
}
sort(Edges.begin(), Edges.end());
vector<pvv>::iterator edgeend = unique(Edges.begin(), Edges.end());
Edges.resize(edgeend-Edges.begin());
// sample edges.
vector<pvv>::iterator ei;
double n_samples_per_length_unit;
double n_samples_decimal = 0.0;
int cnt=0;
if(Flags & FLAG_FACE_SAMPLING)
n_samples_per_length_unit = sqrt(n_samples_per_area_unit);
else
n_samples_per_length_unit = n_samples_per_area_unit;
for(ei=Edges.begin(); ei!=Edges.end(); ++ei)
{
n_samples_decimal += Distance((*ei).first->cP(),(*ei).second->cP()) * n_samples_per_length_unit;
n_samples = (int) n_samples_decimal;
SampleEdge((*ei).first->cP(), (*ei).second->cP(), (int) n_samples);
n_samples_decimal -= (double) n_samples;
// print progress information
if(!(++cnt % PRINT_EVERY_N_ELEMENTS))
printf("Sampling edge %d%%\r", (100 * cnt/Edges.size()));
}
printf(" \r");
}
// -----------------------------------------------------------------------------------------------
// --- Face Sampling -----------------------------------------------------------------------------
// Montecarlo sampling.
template <class MetroMesh>
inline void Sampling<MetroMesh>::AddRandomSample(typename MetroMesh::FaceIterator &T)
{
// random sampling over the input face.
double rnd_1, rnd_2;
// vertices of the face T.
Point3x p0(T->V(0)->cP());
Point3x p1(T->V(1)->cP());
Point3x p2(T->V(2)->cP());
// calculate two edges of T.
Point3x v1(p1 - p0);
Point3x v2(p2 - p0);
// choose two random numbers.
rnd_1 = (double)rand() / (double)RAND_MAX;
rnd_2 = (double)rand() / (double)RAND_MAX;
if(rnd_1 + rnd_2 > 1.0)
{
rnd_1 = 1.0 - rnd_1;
rnd_2 = 1.0 - rnd_2;
}
// add a random point on the face T.
AddSample (p0 + (v1 * rnd_1 + v2 * rnd_2));
n_total_area_samples++;
}
template <class MetroMesh>
void Sampling<MetroMesh>::MontecarloFaceSampling()
{
// Montecarlo sampling.
int cnt = 0;
double n_samples_decimal = 0.0;
MetroMesh::FaceIterator fi;
srand(clock());
// printf("Montecarlo face sampling\n");
for(fi=S1.face.begin(); fi != S1.face.end(); fi++)
if(!(*fi).IsD())
{
// compute # samples in the current face.
n_samples_decimal += fi->Area() * n_samples_per_area_unit;
n_samples = (int) n_samples_decimal;
// for every sample p_i in T...
for(int i=0; i < n_samples; i++)
AddRandomSample(fi);
n_samples_decimal -= (double) n_samples;
// print progress information
// if(!(++cnt % PRINT_EVERY_N_ELEMENTS))
// printf("Sampling face %d%%\r", (100 * cnt/S1.fn));
}
// printf(" \r");
}
// Subdivision sampling.
template <class MetroMesh>
void Sampling<MetroMesh>::FaceSubdiv(const Point3x & v0, const Point3x & v1, const Point3x & v2, int maxdepth)
{
// recursive face subdivision.
if(maxdepth == 0)
{
// ground case.
AddSample((v0+v1+v2)/3.0f);
n_total_area_samples++;
n_samples++;
return;
}
// compute the longest edge.
double maxd01 = SquaredDistance(v0,v1);
double maxd12 = SquaredDistance(v1,v2);
double maxd20 = SquaredDistance(v2,v0);
int res;
if(maxd01 > maxd12)
if(maxd01 > maxd20) res = 0;
else res = 2;
else
if(maxd12 > maxd20) res = 1;
else res = 2;
// break the input triangle along the median to the the longest edge.
Point3x pp;
switch(res)
{
case 0 : pp = (v0+v1)/2;
FaceSubdiv(v0,pp,v2,maxdepth-1);
FaceSubdiv(pp,v1,v2,maxdepth-1);
break;
case 1 : pp = (v1+v2)/2;
FaceSubdiv(v0,v1,pp,maxdepth-1);
FaceSubdiv(v0,pp,v2,maxdepth-1);
break;
case 2 : pp = (v2+v0)/2;
FaceSubdiv(v0,v1,pp,maxdepth-1);
FaceSubdiv(pp,v1,v2,maxdepth-1);
break;
}
}
template <class MetroMesh>
void Sampling<MetroMesh>::SubdivFaceSampling()
{
// Subdivision sampling.
int cnt = 0, maxdepth;
double n_samples_decimal = 0.0;
MetroMesh::FaceIterator fi;
printf("Subdivision face sampling\n");
for(fi=S1.face.begin(); fi != S1.face.end(); fi++)
{
// compute # samples in the current face.
n_samples_decimal += fi->Area() * n_samples_per_area_unit;
n_samples = (int) n_samples_decimal;
if(n_samples)
{
// face sampling.
maxdepth = (int)log((double)n_samples)/log(2.0);
n_samples = 0;
FaceSubdiv((*fi).V(0)->cP(), (*fi).V(1)->cP(), (*fi).V(2)->cP(), maxdepth);
}
n_samples_decimal -= (double) n_samples;
// print progress information
if(!(++cnt % PRINT_EVERY_N_ELEMENTS))
printf("Sampling face %d%%\r", (100 * cnt/S1.fn));
}
printf(" \r");
}
// Similar Triangles sampling.
template <class MetroMesh>
void Sampling<MetroMesh>::SimilarTriangles(const Point3x & v0, const Point3x & v1, const Point3x & v2, int n_samples_per_edge)
{
Point3x V1((v1-v0)/(double)(n_samples_per_edge-1));
Point3x V2((v2-v0)/(double)(n_samples_per_edge-1));
int i, j;
// face sampling.
for(i=1; i < n_samples_per_edge-1; i++)
for(j=1; j < n_samples_per_edge-1-i; j++)
{
AddSample( v0 + (V1*(double)i + V2*(double)j) );
n_total_area_samples++;
n_samples++;
}
}
template <class MetroMesh>
void Sampling<MetroMesh>::SimilarFaceSampling()
{
// Similar Triangles sampling.
int cnt = 0, n_samples_per_edge;
double n_samples_decimal = 0.0;
MetroMesh::FaceIterator fi;
printf("Similar Triangles face sampling\n");
for(fi=S1.face.begin(); fi != S1.face.end(); fi++)
{
// compute # samples in the current face.
n_samples_decimal += fi->Area() * n_samples_per_area_unit;
n_samples = (int) n_samples_decimal;
if(n_samples)
{
// face sampling.
n_samples_per_edge = (int)((sqrt(1.0+8.0*(double)n_samples) +5.0)/2.0);
n_samples = 0;
SimilarTriangles((*fi).V(0)->cP(), (*fi).V(1)->cP(), (*fi).V(2)->cP(), n_samples_per_edge);
}
n_samples_decimal -= (double) n_samples;
// print progress information
if(!(++cnt % PRINT_EVERY_N_ELEMENTS))
printf("Sampling face %d%%\r", (100 * cnt/S1.fn));
}
printf(" \r");
}
// -----------------------------------------------------------------------------------------------
// --- Distance ----------------------------------------------------------------------------------
template <class MetroMesh>
void Sampling<MetroMesh>::Hausdorff()
{
Box3< MetroMesh::ScalarType> bbox;
// set grid meshes.
gS2.SetBBox(S2.bbox);
if(S2.face.size() < MIN_SIZE)
gS2.Set(S2.face, MIN_SIZE);
else
gS2.Set(S2.face);
// set bounding box
bbox = S2.bbox;
dist_upper_bound = /*BBOX_FACTOR * */bbox.Diag();
//if(Flags & FLAG_HIST)
// hist.SetRange(0.0, dist_upper_bound, N_HIST_BINS);
// initialize sampling statistics.
n_total_area_samples = n_total_edge_samples = n_total_vertex_samples = n_total_samples = n_samples = 0;
max_dist = -HUGE_VAL;
mean_dist = RMS_dist = 0;
// Vertex sampling.
if(Flags & FLAG_VERTEX_SAMPLING)
VertexSampling();
// Edge sammpling.
n_samples_target -= (int) n_total_samples;
if(n_samples_target > 0)
{
n_samples_per_area_unit = n_samples_target / area_S1;
if(Flags & FLAG_EDGE_SAMPLING)
{
EdgeSampling();
n_samples_target -= (int) n_total_samples;
}
// Face sampling.
if((Flags & FLAG_FACE_SAMPLING) && (n_samples_target > 0))
{
n_samples_per_area_unit = n_samples_target / area_S1;
if(Flags & FLAG_MONTECARLO_SAMPLING) MontecarloFaceSampling();
if(Flags & FLAG_SUBDIVISION_SAMPLING) SubdivFaceSampling();
if(Flags & FLAG_SIMILAR_TRIANGLES_SAMPLING) SimilarFaceSampling();
}
}
// compute vertex colour
if(Flags & FLAG_SAVE_ERROR_AS_COLOUR)
{
MetroMesh::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");
}
// compute statistics
n_samples_per_area_unit = (double) n_total_samples / area_S1;
volume = mean_dist / n_samples_per_area_unit / 2.0;
mean_dist /= n_total_samples;
RMS_dist = sqrt(RMS_dist / n_total_samples);
}
// -----------------------------------------------------------------------------------------------
//#undef FLAG_HIST
//#undef FLAG_VERTEX_SAMPLING
//#undef FLAG_EDGE_SAMPLING
//#undef FLAG_FACE_SAMPLING
//#undef FLAG_MONTECARLO_SAMPLING
//#undef FLAG_SUBDIVISION_SAMPLING
//#undef FLAG_SIMILAR_TRIANGLES_SAMPLING
//#undef FLAG_SAVE_ERROR_DISPLACEMENT
//#undef FLAG_SAVE_ERROR_AS_COLOUR
//
//// global constants
//#undef NO_SAMPLES_PER_FACE
//#undef N_SAMPLES_EDGE_TO_FACE_RATIO
//#undef BBOX_FACTOR
//#undef INFLATE_PERCENTAGE
//#undef MIN_SIZE
//#undef N_HIST_BINS
//#undef PRINT_EVERY_N_ELEMENTS
//#undef FILE_EXT_SMF
//#undef FILE_EXT_PLY
//
#endif
// -----------------------------------------------------------------------------------------------