mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			148 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			148 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#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
 |