2004-05-14 15:53:12 +02:00
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright ( C ) 2004 \ / ) \ / *
* Visual Computing Lab / \ / | *
* 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 . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
History
$ Log : not supported by cvs2svn $
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-05-05 13:30:37 +02:00
// -----------------------------------------------------------------------------------------------
// 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 ;
2004-05-14 15:53:12 +02:00
bool IncludeUnreferred = false ;
2004-05-05 13:30:37 +02:00
// -----------------------------------------------------------------------------------------------
inline char * GetExtension ( char * filename )
{
2004-05-11 16:39:17 +02:00
size_t i ;
for ( i = strlen ( filename ) - 1 ; i > = 0 ; i - - )
2004-05-05 13:30:37 +02:00
if ( filename [ i ] = = ' . ' )
break ;
if ( i > 0 )
return & ( filename [ i + 1 ] ) ;
else
return NULL ;
}
2004-05-11 16:39:17 +02:00
int main ( int argc , char * * argv )
2004-05-05 13:30:37 +02:00
{
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 ;
2004-05-11 16:39:17 +02:00
double n_samples_per_area_unit ;
2004-05-05 13:30:37 +02:00
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 ;
2004-05-11 16:39:17 +02:00
//FILE *fd;
2004-05-05 13:30:37 +02:00
// 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 ) ;
}
2004-05-14 02:33:02 +02:00
if ( ! strcmp ( " ply " , fmt ) )
2004-05-11 16:39:17 +02:00
{
2004-05-05 13:30:37 +02:00
printf ( " reading the mesh `%s'... " , argv [ 1 ] ) ;
err = tri : : io : : ImporterPLY < CMesh > : : Open ( S1 , argv [ 1 ] ) ;
}
/* else
2004-05-14 02:33:02 +02:00
if ( ! strcmp ( file_ext_smf , fmt ) )
2004-05-05 13:30:37 +02:00
{
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 ) ;
2004-05-14 02:33:02 +02:00
printf ( " error number %d " , err ) ;
2004-05-05 13:30:37 +02:00
exit ( - 1 ) ;
}
else
printf ( " done \n " ) ;
// load mesh M2.
if ( ! ( fmt = GetExtension ( argv [ 2 ] ) ) )
{
printf ( MSG_ERR_UNKNOWN_FORMAT , fmt ) ;
exit ( - 1 ) ;
}
2004-05-14 02:33:02 +02:00
if ( ! strcmp ( " ply " , fmt ) )
2004-05-05 13:30:37 +02:00
{
printf ( " reading the mesh `%s'... " , argv [ 2 ] ) ;
err = tri : : io : : ImporterPLY < CMesh > : : Open ( S2 , argv [ 2 ] ) ;
}
/*else
2004-05-14 02:33:02 +02:00
if ( ! strcmp ( file_ext_smf , fmt ) )
2004-05-05 13:30:37 +02:00
{
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 ;
2004-05-14 15:53:12 +02:00
case CMR_LINE_ARG_INCLUDE_UNREF : IncludeUnreferred = true ; break ;
2004-05-05 13:30:37 +02:00
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 ;
2004-05-11 16:39:17 +02:00
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 ;
2004-05-05 13:30:37 +02:00
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 ;
2004-05-14 02:33:02 +02:00
n_samples_target = 10 * max ( S1 . fn , S2 . fn ) ; // take 10 samples per face
2004-05-05 13:30:37 +02:00
}
// 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 ) ;
2004-05-14 02:33:02 +02:00
bbox . InflateFix ( 0.02 ) ;
2004-05-05 13:30:37 +02:00
S1 . bbox = bbox ;
S2 . bbox = bbox ;
// set flags.
2004-05-14 02:33:02 +02:00
flags = 0 ;
2004-05-14 15:53:12 +02:00
if ( IncludeUnreferred )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : INCLUDE_UNREFERENCED_VERTICES ;
2004-05-05 13:30:37 +02:00
if ( ComputeHistFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : HIST ;
2004-05-05 13:30:37 +02:00
if ( VertexSampleFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : VERTEX_SAMPLING ;
2004-05-05 13:30:37 +02:00
if ( EdgeSampleFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : EDGE_SAMPLING ;
2004-05-05 13:30:37 +02:00
if ( FaceSampleFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : FACE_SAMPLING ;
2004-05-05 13:30:37 +02:00
if ( MontecarloSamplingFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : MONTECARLO_SAMPLING ;
2004-05-05 13:30:37 +02:00
if ( SubdivisionSamplingFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : SUBDIVISION_SAMPLING ;
2004-05-05 13:30:37 +02:00
if ( SimilarTrianglesSamplingFlag )
2004-05-14 02:33:02 +02:00
flags | = SamplingFlags : : SIMILAR_TRIANGLES_SAMPLING ;
2004-05-05 13:30:37 +02:00
flags_fwd = flags ;
flags_back = flags ;
if ( SaveErrorDisplacement )
{
if ( S1 . vn > = S2 . vn )
2004-05-14 02:33:02 +02:00
flags_fwd | = SamplingFlags : : SAVE_ERROR_DISPLACEMENT ;
2004-05-05 13:30:37 +02:00
else
2004-05-14 02:33:02 +02:00
flags_back | = SamplingFlags : : SAVE_ERROR_DISPLACEMENT ;
2004-05-05 13:30:37 +02:00
}
if ( SaveErrorAsColour )
{
if ( S1 . vn > = S2 . vn )
2004-05-14 02:33:02 +02:00
flags_fwd | = SamplingFlags : : SAVE_ERROR_AS_COLOUR ;
2004-05-05 13:30:37 +02:00
else
2004-05-14 02:33:02 +02:00
flags_back | = SamplingFlags : : SAVE_ERROR_AS_COLOUR ;
2004-05-05 13:30:37 +02:00
}
// 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 \t faces %7i \n \t area %12.4f \n " , argv [ 1 ] , S1 . vn , S1 . fn , ForwardSampling . GetArea ( ) ) ;
printf ( " \t bbox (%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 ( " \t bbox diagonal %f \n " , ( float ) tmp_bbox_M1 . Diag ( ) ) ;
printf ( " M2: '%s' \n \t %vertices %7i \n \t faces %7i \n \t area %12.4f \n " , argv [ 2 ] , S2 . vn , S2 . fn , BackwardSampling . GetArea ( ) ) ;
printf ( " \t bbox (%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 ( " \t bbox diagonal %f \n " , ( float ) tmp_bbox_M2 . Diag ( ) ) ;
// Forward distance.
printf ( " \n Forward 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 \n target # 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 ( " \n distance: \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 \n samples per area unit: %f \n \n " , n_samples_area , n_samples_output , ForwardSampling . GetNSamplesPerAreaUnit ( ) ) ;
// Backward distance.
printf ( " \n Backward 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 \n target # 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 ( " \n distance: \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 \n samples 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 \n error 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 ( " \n Hausdorff distance: %f (%f with respect to bounding box diagonal) \n Computation 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.
2004-05-14 02:33:02 +02:00
if ( ( flags_fwd & SamplingFlags : : SAVE_ERROR_DISPLACEMENT ) & & ( flags_fwd & SamplingFlags : : SAVE_ERROR_AS_COLOUR ) )
// if(strcmp(new_mesh_filename, new_mesh_filename_2))
2004-05-05 13:30:37 +02:00
{
2004-05-14 02:33:02 +02:00
vcg : : tri : : io : : PlyInfo p ;
p . mask | = vcg : : tri : : io : : PLYMask : : PM_VERTCOLOR | vcg : : tri : : io : : PLYMask : : PM_VERTQUALITY ;
tri : : io : : ExporterPLY < CMesh > : : Save ( S1 , new_mesh_filename , true , p ) ;
exit ( 0 ) ;
2004-05-05 13:30:37 +02:00
}
2004-05-14 02:33:02 +02:00
if ( ( flags_back & SamplingFlags : : SAVE_ERROR_DISPLACEMENT ) & & ( flags_back & SamplingFlags : : SAVE_ERROR_AS_COLOUR ) )
// if(strcmp(new_mesh_filename, new_mesh_filename_2))
2004-05-05 13:30:37 +02:00
{
2004-05-14 02:33:02 +02:00
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 ) ;
2004-05-05 13:30:37 +02:00
}
2004-05-14 02:33:02 +02:00
//if(flags_fwd & SamplingFlags::SAVE_ERROR_DISPLACEMENT)
2004-05-05 13:30:37 +02:00
// S1.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR));
//else
2004-05-14 02:33:02 +02:00
// if(flags_back & SamplingFlags::SAVE_ERROR_DISPLACEMENT)
2004-05-05 13:30:37 +02:00
// S2.SavePly(new_mesh_filename, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTCOLOR));
2004-05-14 02:33:02 +02:00
//if(flags_fwd & SamplingFlags::SAVE_ERROR_AS_COLOUR)
2004-05-05 13:30:37 +02:00
// S1.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY));
//else
2004-05-14 02:33:02 +02:00
// if(flags_back & SamplingFlags::SAVE_ERROR_AS_COLOUR)
2004-05-05 13:30:37 +02:00
// S2.SavePly(new_mesh_filename_2, CMesh::SM_ALL & (CMesh::SM_ALL ^ CMesh::SM_VERTQUALITY));
2004-05-11 16:39:17 +02:00
return 0 ;
2004-05-05 13:30:37 +02:00
}
// -----------------------------------------------------------------------------------------------