// ----------------------------------------------------------------------------------------------- // standard libraries #include // project definitions. #include "defs.h" #include "sampling.h" #include "mesh_type.h" #include #include //#include #include #include // ----------------------------------------------------------------------------------------------- ////////////////// Command line Flags and parameters bool ComputeHistFlag = false; bool VertexSampleFlag = true; bool EdgeSampleFlag = true; bool FaceSampleFlag = true; bool MontecarloSamplingFlag = false; bool SubdivisionSamplingFlag = false; bool SimilarTrianglesSamplingFlag = false; bool NumberOfSamples = false; bool SamplesPerAreaUnit = false; bool SaveErrorDisplacement = false; bool SaveErrorAsColour = false; // ----------------------------------------------------------------------------------------------- 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::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::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::Set(S1); tri::UpdateEdges::Set(S2); // set bounding boxes for S1 and S2 tri::UpdateBounding::Box(S1); tri::UpdateBounding::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 ForwardSampling(S1,S2); Sampling 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::const_iterator ii; vector::const_iterator fi; fprintf(fd, "error distribution histogram (forward distance)\n\n"); for(ii=hist1.H.begin(), fi=hist1.R.begin(); ii != hist1.H.end(); ++fi,ii++) fprintf(fd, "%6.4f\t%d\n", *fi, *ii); fprintf(fd, "\n\nerror distribution histogram (backward distance)\n"); for(ii=hist2.H.begin(), fi=hist2.R.begin(); ii != hist2.H.end(); ++fi,ii++) fprintf(fd, "%6.4f\t%d\n", *fi, *ii); fclose(fd); }*/ // max distance. mesh_dist_max = max(dist1_max , dist2_max); printf("\nHausdorff distance: %f (%f with respect to bounding box diagonal)\nComputation time : %d ms\n# samples/second : %f\n\n", (float)mesh_dist_max, (float)mesh_dist_max/bbox.Diag(), (int)elapsed_time, (float)n_samples_output/(float)elapsed_time*2000.0F); // 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::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::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)); } // -----------------------------------------------------------------------------------------------