From 35a906139ebf900ada4ea5aeb1e59d7c8a7082f6 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 8 Jul 2021 08:33:06 +0200 Subject: [PATCH] Extend test with checking simplified model distance to original model --- tests/libslic3r/test_indexed_triangle_set.cpp | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/libslic3r/test_indexed_triangle_set.cpp b/tests/libslic3r/test_indexed_triangle_set.cpp index ac676267a..094c17fd6 100644 --- a/tests/libslic3r/test_indexed_triangle_set.cpp +++ b/tests/libslic3r/test_indexed_triangle_set.cpp @@ -103,6 +103,93 @@ TEST_CASE("Split two watertight meshes", "[its_split][its]") { } #include +static float triangle_area(const Vec3f &v0, const Vec3f &v1, const Vec3f &v2) +{ + Vec3f ab = v1 - v0; + Vec3f ac = v2 - v0; + return ab.cross(ac).norm() / 2.f; +} + +static float triangle_area(const Vec3crd &triangle_inices, const std::vector &vertices) +{ + return triangle_area(vertices[triangle_inices[0]], + vertices[triangle_inices[1]], + vertices[triangle_inices[2]]); +} + +static std::mt19937 create_random_generator() { + std::random_device rd; + std::mt19937 gen(rd()); + return gen; +} + +std::vector its_sample_surface(const indexed_triangle_set &its, + double sample_per_mm2, + std::mt19937 &random_generator = create_random_generator()) +{ + std::vector samples; + std::uniform_real_distribution rand01(0.f, 1.f); + for (const auto &triangle_indices : its.indices) { + float area = triangle_area(triangle_indices, its.vertices); + float countf; + float fractional = std::modf(area * sample_per_mm2, &countf); + int count = static_cast(countf); + + float generate = rand01(random_generator); + if (generate < fractional) ++count; + if (count == 0) continue; + + const Vec3f &v0 = its.vertices[triangle_indices[0]]; + const Vec3f &v1 = its.vertices[triangle_indices[1]]; + const Vec3f &v2 = its.vertices[triangle_indices[2]]; + for (int c = 0; c < count; c++) { + // barycentric coordinate + Vec3f b; + b[0] = rand01(random_generator); + b[1] = rand01(random_generator); + if ((b[0] + b[1]) > 1.f) { + b[0] = 1.f - b[0]; + b[1] = 1.f - b[1]; + } + b[2] = 1.f - b[0] - b[1]; + Vec3f pos; + for (int i = 0; i < 3; i++) { + pos[i] = b[0] * v0[i] + b[1] * v1[i] + b[2] * v2[i]; + } + samples.push_back(pos); + } + } + return samples; +} + + +#include "libslic3r/AABBTreeIndirect.hpp" + +// return Average abs distance to original +float compare(const indexed_triangle_set &original, + const indexed_triangle_set &simplified, + double sample_per_mm2) +{ + // create ABBTree + auto tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set( + original.vertices, original.indices); + + unsigned int init = 0; + std::mt19937 rnd(init); + auto samples = its_sample_surface(simplified, sample_per_mm2, rnd); + + float sumDistance = 0; + for (const Vec3f &sample : samples) { + size_t hit_idx; + Vec3f hit_point; + float distance2 = AABBTreeIndirect::squared_distance_to_indexed_triangle_set( + original.vertices, original.indices, tree, sample, hit_idx, + hit_point); + sumDistance += sqrt(distance2); + } + return sumDistance / samples.size(); +} + TEST_CASE("Reduce one edge by Quadric Edge Collapse", "[its]") { indexed_triangle_set its; @@ -139,6 +226,8 @@ TEST_CASE("Reduce one edge by Quadric Edge Collapse", "[its]") (v[i] > v4[i] && v[i] < v2[i]); CHECK(is_between); } + float avg_distance = compare(its_, its, 10); + CHECK(avg_distance < 8e-3f); } #include "test_utils.hpp" @@ -154,4 +243,7 @@ TEST_CASE("Symplify mesh by Quadric edge collapse to 5%", "[its]") CHECK(its.indices.size() <= wanted_count); double volume = its_volume(its); CHECK(fabs(original_volume - volume) < 30.); + + float avg_distance = compare(mesh.its, its, 10); + CHECK(avg_distance < 0.021f); // 0.02022 | 0.0199614074 } \ No newline at end of file