Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authortamasmeszaros <meszaros.q@gmail.com>2020-08-18 12:41:14 +0300
committertamasmeszaros <meszaros.q@gmail.com>2020-08-18 12:41:14 +0300
commit4ef52af9066aff676818cd3b1d157083c72805b2 (patch)
tree8b22e9f55df9367db384774b5d0346350910fb39 /tests
parent1172dfcb402b6fdd5df31262009d123fbb2ca918 (diff)
Add dedicated tests for support point generation
Diffstat (limited to 'tests')
-rw-r--r--tests/sla_print/CMakeLists.txt5
-rw-r--r--tests/sla_print/sla_supptgen_tests.cpp148
-rw-r--r--tests/sla_print/sla_test_utils.cpp68
-rw-r--r--tests/sla_print/sla_test_utils.hpp9
4 files changed, 228 insertions, 2 deletions
diff --git a/tests/sla_print/CMakeLists.txt b/tests/sla_print/CMakeLists.txt
index f6b261fda..d071b4973 100644
--- a/tests/sla_print/CMakeLists.txt
+++ b/tests/sla_print/CMakeLists.txt
@@ -1,7 +1,8 @@
get_filename_component(_TEST_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
-add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
- sla_print_tests.cpp
+add_executable(${_TEST_NAME}_tests ${_TEST_NAME}_tests_main.cpp
+ sla_print_tests.cpp
sla_test_utils.hpp sla_test_utils.cpp sla_treebuilder_tests.cpp
+ sla_supptgen_tests.cpp
sla_raycast_tests.cpp)
target_link_libraries(${_TEST_NAME}_tests test_common libslic3r)
set_property(TARGET ${_TEST_NAME}_tests PROPERTY FOLDER "tests")
diff --git a/tests/sla_print/sla_supptgen_tests.cpp b/tests/sla_print/sla_supptgen_tests.cpp
new file mode 100644
index 000000000..1d7a3ebee
--- /dev/null
+++ b/tests/sla_print/sla_supptgen_tests.cpp
@@ -0,0 +1,148 @@
+#include <catch2/catch.hpp>
+#include <test_utils.hpp>
+
+#include <libslic3r/ExPolygon.hpp>
+#include <libslic3r/BoundingBox.hpp>
+
+#include "sla_test_utils.hpp"
+
+namespace Slic3r { namespace sla {
+
+TEST_CASE("Overhanging point should be supported", "[SupGen]") {
+
+ // Pyramid with 45 deg slope
+ TriangleMesh mesh = make_pyramid(10.f, 10.f);
+ mesh.rotate_y(PI);
+ mesh.require_shared_vertices();
+ mesh.WriteOBJFile("Pyramid.obj");
+
+ sla::SupportPoints pts = calc_support_pts(mesh);
+
+ // The overhang, which is the upside-down pyramid's edge
+ Vec3f overh{0., 0., -10.};
+
+ REQUIRE(!pts.empty());
+
+ float dist = (overh - pts.front().pos).norm();
+
+ for (const auto &pt : pts)
+ dist = std::min(dist, (overh - pt.pos).norm());
+
+ // Should require exactly one support point at the overhang
+ REQUIRE(pts.size() > 0);
+ REQUIRE(dist < 1.f);
+}
+
+double min_point_distance(const sla::SupportPoints &pts)
+{
+ sla::PointIndex index;
+
+ for (size_t i = 0; i < pts.size(); ++i)
+ index.insert(pts[i].pos.cast<double>(), i);
+
+ auto d = std::numeric_limits<double>::max();
+ index.foreach([&d, &index](const sla::PointIndexEl &el) {
+ auto res = index.nearest(el.first, 2);
+ for (const sla::PointIndexEl &r : res)
+ if (r.second != el.second)
+ d = std::min(d, (el.first - r.first).norm());
+ });
+
+ return d;
+}
+
+TEST_CASE("Overhanging horizontal surface should be supported", "[SupGen]") {
+ double width = 10., depth = 10., height = 1.;
+
+ TriangleMesh mesh = make_cube(width, depth, height);
+ mesh.translate(0., 0., 5.); // lift up
+ mesh.require_shared_vertices();
+ mesh.WriteOBJFile("Cuboid.obj");
+
+ sla::SupportPointGenerator::Config cfg;
+ sla::SupportPoints pts = calc_support_pts(mesh, cfg);
+
+ double mm2 = width * depth;
+
+ REQUIRE(!pts.empty());
+ REQUIRE(pts.size() * cfg.support_force() > mm2 * cfg.tear_pressure());
+ REQUIRE(min_point_distance(pts) >= cfg.minimal_distance);
+}
+
+template<class M> auto&& center_around_bb(M &&mesh)
+{
+ auto bb = mesh.bounding_box();
+ mesh.translate(-bb.center().template cast<float>());
+
+ return std::forward<M>(mesh);
+}
+
+TEST_CASE("Overhanging edge should be supported", "[SupGen]") {
+ float width = 10.f, depth = 10.f, height = 5.f;
+
+ TriangleMesh mesh = make_prism(width, depth, height);
+ mesh.rotate_y(PI); // rotate on its back
+ mesh.translate(0., 0., height);
+ mesh.require_shared_vertices();
+ mesh.WriteOBJFile("Prism.obj");
+
+ sla::SupportPointGenerator::Config cfg;
+ sla::SupportPoints pts = calc_support_pts(mesh, cfg);
+
+ REQUIRE(min_point_distance(pts) >= cfg.minimal_distance);
+
+ Linef3 overh{ {0.f, -depth / 2.f, 0.f}, {0.f, depth / 2.f, 0.f}};
+
+ // Get all the points closer that 1 mm to the overhanging edge:
+ sla::SupportPoints overh_pts; overh_pts.reserve(pts.size());
+
+ std::copy_if(pts.begin(), pts.end(), std::back_inserter(overh_pts),
+ [&overh](const sla::SupportPoint &pt){
+ return line_alg::distance_to(overh, Vec3d{pt.pos.cast<double>()}) < 1.;
+ });
+
+ REQUIRE(overh_pts.size() * cfg.support_force() > overh.length() * cfg.tear_pressure());
+ REQUIRE(min_point_distance(pts) >= cfg.minimal_distance);
+}
+
+// FIXME: Not working yet
+//TEST_CASE("Hollowed cube should be supported from the inside", "[SupGen][Hollowed]") {
+// TriangleMesh mesh = make_cube(20., 20., 20.);
+
+// hollow_mesh(mesh, HollowingConfig{});
+
+// mesh.WriteOBJFile("cube_hollowed.obj");
+
+// auto bb = mesh.bounding_box();
+// auto h = float(bb.max.z() - bb.min.z());
+// Vec3f mv = bb.center().cast<float>() - Vec3f{0.f, 0.f, 0.5f * h};
+// mesh.translate(-mv);
+// mesh.require_shared_vertices();
+
+// sla::SupportPointGenerator::Config cfg;
+// sla::SupportPoints pts = calc_support_pts(mesh, cfg);
+// sla::remove_bottom_points(pts, mesh.bounding_box().min.z() + EPSILON);
+
+// REQUIRE(!pts.empty());
+//}
+
+TEST_CASE("Two parallel plates should be supported", "[SupGen][Hollowed]")
+{
+ double width = 20., depth = 20., height = 1.;
+
+ TriangleMesh mesh = center_around_bb(make_cube(width + 5., depth + 5., height));
+ TriangleMesh mesh_high = center_around_bb(make_cube(width, depth, height));
+ mesh_high.translate(0., 0., 10.); // lift up
+ mesh.merge(mesh_high);
+ mesh.require_shared_vertices();
+
+ mesh.WriteOBJFile("parallel_plates.obj");
+
+ sla::SupportPointGenerator::Config cfg;
+ sla::SupportPoints pts = calc_support_pts(mesh, cfg);
+ sla::remove_bottom_points(pts, mesh.bounding_box().min.z() + EPSILON);
+
+ REQUIRE(!pts.empty());
+}
+
+}} // namespace Slic3r::sla
diff --git a/tests/sla_print/sla_test_utils.cpp b/tests/sla_print/sla_test_utils.cpp
index 8978281d8..f6b548fa0 100644
--- a/tests/sla_print/sla_test_utils.cpp
+++ b/tests/sla_print/sla_test_utils.cpp
@@ -411,3 +411,71 @@ double predict_error(const ExPolygon &p, const sla::RasterBase::PixelDim &pd)
return error;
}
+
+
+// Make a 3D pyramid
+TriangleMesh make_pyramid(float base, float height)
+{
+ float a = base / 2.f;
+
+ TriangleMesh mesh(
+ {
+ {-a, -a, 0}, {a, -a, 0}, {a, a, 0},
+ {-a, a, 0}, {0.f, 0.f, height}
+ },
+ {
+ {0, 1, 2},
+ {0, 2, 3},
+ {0, 1, 4},
+ {1, 2, 4},
+ {2, 3, 4},
+ {3, 0, 4}
+ });
+
+ mesh.repair();
+
+ return mesh;
+}
+
+ TriangleMesh make_prism(double width, double length, double height)
+{
+ // We need two upward facing triangles
+
+ double x = width / 2., y = length / 2.;
+
+ TriangleMesh mesh(
+ {
+ {-x, -y, 0.}, {x, -y, 0.}, {0., -y, height},
+ {-x, y, 0.}, {x, y, 0.}, {0., y, height},
+ },
+ {
+ {0, 1, 2}, // side 1
+ {4, 3, 5}, // side 2
+ {1, 4, 2}, {2, 4, 5}, // roof 1
+ {0, 2, 5}, {0, 5, 3}, // roof 2
+ {3, 4, 1}, {3, 1, 0} // bottom
+ });
+
+ return mesh;
+}
+
+sla::SupportPoints calc_support_pts(
+ const TriangleMesh & mesh,
+ const sla::SupportPointGenerator::Config &cfg)
+{
+ // Prepare the slice grid and the slices
+ std::vector<ExPolygons> slices;
+ auto bb = cast<float>(mesh.bounding_box());
+ std::vector<float> heights = grid(bb.min.z(), bb.max.z(), 0.1f);
+ slice_mesh(mesh, heights, slices, CLOSING_RADIUS, [] {});
+
+ // Prepare the support point calculator
+ sla::IndexedMesh emesh{mesh};
+ sla::SupportPointGenerator spgen{emesh, cfg, []{}, [](int){}};
+
+ // Calculate the support points
+ spgen.seed(0);
+ spgen.execute(slices, heights);
+
+ return spgen.output();
+}
diff --git a/tests/sla_print/sla_test_utils.hpp b/tests/sla_print/sla_test_utils.hpp
index fdd883ed8..d10a85b25 100644
--- a/tests/sla_print/sla_test_utils.hpp
+++ b/tests/sla_print/sla_test_utils.hpp
@@ -185,4 +185,13 @@ long raster_pxsum(const sla::RasterGrayscaleAA &raster);
double predict_error(const ExPolygon &p, const sla::RasterBase::PixelDim &pd);
+// Make a 3D pyramid
+TriangleMesh make_pyramid(float base, float height);
+
+TriangleMesh make_prism(double width, double length, double height);
+
+sla::SupportPoints calc_support_pts(
+ const TriangleMesh & mesh,
+ const sla::SupportPointGenerator::Config &cfg = {});
+
#endif // SLA_TEST_UTILS_HPP