Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer

This commit is contained in:
enricoturri1966 2020-08-19 08:18:23 +02:00
commit af200e47c1
10 changed files with 285 additions and 21 deletions

View file

@ -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")

View file

@ -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

View file

@ -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();
}

View file

@ -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