49 const std::vector< FloatT > &v2,
51 bool relative_threshold,
92 bool relative_threshold,
100 if(geom_threshold == 0.0)
103 isequal = (*
this == p);
105 else if(relative_threshold)
112 isequal = (dist_x <= geom_threshold && dist_y <= geom_threshold &&
113 dist_z <= geom_threshold);
122 isequal = (dist_x <= geom_threshold && dist_y <= geom_threshold &&
123 dist_z <= geom_threshold);
127 if(!isequal && errors_log)
129 if(geom_threshold == 0.0)
133 errors_log->insert(std::make_pair(
m_x, p.
m_x));
135 errors_log->insert(std::make_pair(
m_y, p.
m_y));
137 errors_log->insert(std::make_pair(
m_z, p.
m_z));
142 if(dist_x > geom_threshold)
143 errors_log->insert(std::make_pair(
m_x, p.
m_x));
144 if(dist_y > geom_threshold)
145 errors_log->insert(std::make_pair(
m_y, p.
m_y));
146 if(dist_z > geom_threshold)
147 errors_log->insert(std::make_pair(
m_z, p.
m_z));
169 os <<
'(' << p.
m_x <<
' ' << p.
m_y <<
' ' << p.
m_z <<
')';
178 Vertex(
const Point &point,
const std::vector< FloatT > &attributes)
206 bool relative_thresholds,
211 other.
m_point, geom_threshold, relative_thresholds, errors_log);
217 return (p_equal && v_equal);
251 const std::vector< FloatT > &attributes)
266 auto min_vx_it = std::min_element(
270 auto min_vx_it_candidate =
271 std::find(min_vx_it + 1,
m_vertices.end(), *min_vx_it);
272 while(min_vx_it_candidate !=
m_vertices.end())
277 while(*min_vx_it_candidate_next == *min_vx_it_next &&
278 min_vx_it_candidate_next != min_vx_it )
280 min_vx_it_candidate_next =
285 if((*min_vx_it_candidate_next) < (*min_vx_it_next))
286 min_vx_it = min_vx_it_candidate;
288 min_vx_it_candidate =
289 std::find(min_vx_it_candidate + 1,
m_vertices.end(), *min_vx_it);
349 bool relative_thresholds,
355 std::cout <<
"Topological difference detected in face (not the same "
356 "number of vertices). Skip face comparison."
365 if(!(v->isequalto(*fv,
385 std::deque< Vertex >::iterator
390 auto v_next_it = v_it + 1;
423 void load(std::ifstream &file,
int vertices_nbr,
int faces_nbr);
425 #if 0 // replaced by isequalto
426 bool operator==(
const Mesh& m)
const;
431 bool relative_thresholds,
443 Mesh::load(std::ifstream &file,
int vertices_nbr,
int faces_nbr)
453 std::vector< Vertex > vtmp;
457 size_t found = line.find_first_not_of(
" \t");
458 if(found != std::string::npos)
460 if(line[found] ==
'#')
464 std::stringstream strline(line);
465 strline >> x >> y >> z;
466 Point point(x, y, z);
469 std::vector< FloatT > vertex_attributes;
471 while(strline >> value)
473 vertex_attributes.push_back(value);
476 Vertex v(point, vertex_attributes);
485 if( unique_vertices.size() !=
m_vertices.size() )
486 throw std::runtime_error(
"Some vertices are duplicated (same coordinates and attributes). Can't reliably compare the meshes. Aborting.");
493 std::stringstream strline(line);
498 std::deque< Vertex >
face;
499 for(
int j = 0; j < v_nbr; j++)
503 face.push_back(vtmp[v_id]);
507 std::vector< FloatT > face_attributes;
509 while(strline >> value)
511 face_attributes.push_back(value);
524 std::cout <<
' ' << *v <<
'\n';
528 std::cout <<
' ' << *f <<
'\n';
531 #if 0 // replaced by isequalto
532 bool Mesh::operator==(
const Mesh& m)
const
548 std::cout <<
"Difference found between vertices:\n";
549 std::cout <<
"(a) " << *v <<
'\n';
550 std::cout <<
"(b) " << *mv <<
'\n';
563 std::cout <<
"Difference found between faces:\n";
564 std::cout <<
"(a) " << *f <<
'\n';
565 std::cout <<
"(b) " << *mf <<
'\n';
581 bool relative_thresholds,
587 std::cout <<
"Topological difference detected in mesh (not the same number "
588 "of vertices). Skip mesh comparison."
595 std::cout <<
"Topological difference detected in mesh (not the same number "
596 "of faces). Skip mesh comparison."
602 unsigned int vertice_error_nbr = 0;
603 unsigned int face_error_nbr = 0;
608 for(; vi !=
m_vertices.end(); ++vi, ++othervi)
610 if(!(vi->isequalto(*othervi,
616 std::cout <<
"Difference found between vertices:\n";
617 std::cout <<
" (a) " << *vi <<
'\n';
618 std::cout <<
" (b) " << *othervi <<
'\n';
627 auto otherf = other.
m_faces.begin();
628 for(; f !=
m_faces.end(); ++f, ++otherf)
630 if(!(f->isequalto(*otherf,
636 std::cout <<
"Difference found between faces:\n";
637 std::cout <<
" (a) " << *f <<
'\n';
638 std::cout <<
" (b) " << *otherf <<
'\n';
647 std::cout <<
"Number of differences in vertices: " << vertice_error_nbr
649 std::cout <<
"Number of differences in faces: " << face_error_nbr
669 std::getline(file, line);
672 if((!line.empty()) && (line.back() ==
'\r'))
674 }
while(line.empty() || line[0] ==
'#');
689 FloatT mean_abs = (std::abs(a) + std::abs(b)) / 2.0f;
690 FloatT rel_dist = std::abs(a - b) / mean_abs;
702 return std::abs(a - b);
711 const std::vector< FloatT > &v2,
713 bool relative_threshold,
716 if(v1.size() != v2.size())
719 <<
"The two vectors don't have the same size. Skip vectors comparison."
725 bool are_vectors_equal =
true;
726 bool are_values_equal =
true;
727 auto v1i = v1.begin();
728 auto v2i = v2.begin();
729 for(; v1i != v1.end(); ++v1i, ++v2i)
731 are_values_equal =
true;
733 if(attr_threshold == 0)
738 are_values_equal =
false;
739 are_vectors_equal =
false;
742 else if(relative_threshold)
746 if(rel_dist > attr_threshold)
748 are_values_equal =
false;
749 are_vectors_equal =
false;
756 if(dist > attr_threshold)
758 are_values_equal =
false;
759 are_vectors_equal =
false;
763 if(!are_values_equal && errors_log)
766 errors_log->insert(std::make_pair(*v1i, *v2i));
770 return are_vectors_equal;
782 std::string filename_b,
786 bool relative_thresholds)
788 std::ifstream file_a(filename_a);
791 std::cout <<
"Unable to read first file." << filename_a << std::endl;
795 std::ifstream file_b(filename_b);
798 std::cout <<
"Unable to read second file " << filename_b << std::endl;
808 if(line_a !=
"OFF" && line_a !=
"COFF")
810 std::cout << filename_a <<
" is not in OFF format." << std::endl;
815 if(line_b !=
"OFF" && line_b !=
"COFF")
817 std::cout << filename_b <<
" is not in OFF format." << std::endl;
823 int vertices_nbr_a, faces_nbr_a, edges_nbr_a;
825 >> vertices_nbr_a >> faces_nbr_a >> edges_nbr_a;
826 int vertices_nbr_b, faces_nbr_b, edges_nbr_b;
828 >> vertices_nbr_b >> faces_nbr_b >> edges_nbr_b;
830 if(vertices_nbr_a != vertices_nbr_b ||
831 faces_nbr_a != faces_nbr_b
836 std::cout <<
"Meshes do NOT have the same size:" << std::endl;
837 std::cout <<
" - " << filename_a <<
" has " << vertices_nbr_a
838 <<
" vertices, " << faces_nbr_a <<
" faces, and " << edges_nbr_a
839 <<
" edges" << std::endl;
840 std::cout <<
" - " << filename_b <<
" has " << vertices_nbr_b
841 <<
" vertices, " << faces_nbr_b <<
" faces, and " << edges_nbr_b
842 <<
" edges" << std::endl;
849 mesh_a.
load(file_a, vertices_nbr_a, faces_nbr_a);
850 mesh_b.
load(file_b, vertices_nbr_b, faces_nbr_b);
854 std::cout <<
"Mesh A =\n";
857 std::cout <<
"Mesh B =\n";
865 mesh_b, geom_threshold, attr_threshold, relative_thresholds, &errors_log);
871 std::vector< FloatT > errors;
872 if(relative_thresholds)
874 for(
auto pair : errors_log)
880 for(
auto pair : errors_log)
885 auto minmax = std::minmax_element(errors.begin(), errors.end());
886 FloatT min = *(minmax.first);
887 FloatT max = *(minmax.second);
889 std::accumulate(errors.begin(), errors.end(), 0.0f) / errors.size();
891 std::cout <<
"Number of effective numeric errors: " << errors.size()
893 std::cout <<
"Numeric error min = " << min << std::endl;
894 std::cout <<
"Numeric error max = " << max << std::endl;
895 std::cout <<
"Numeric error mean = " <<
mean << std::endl;
896 if(relative_thresholds)
897 std::cout <<
"Mode: relative error" << std::endl;
899 std::cout <<
"Mode: absolute error" << std::endl;
909 std::string filename_b,
912 bool relative_threshold)