From d8f2c8cdab10247fe54421bc3aaf46f668ad81a3 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 17 Jan 2020 16:01:49 +0100 Subject: [PATCH] Fixed a bug in the hole-aware raycaster --- src/libslic3r/SLA/Hollowing.cpp | 5 ++++- tests/sla_print/sla_raycast_tests.cpp | 32 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 8dc2d30929..5ab85c1cc4 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -223,7 +223,10 @@ bool DrainHole::get_intersections(const Vec3f& s, const Vec3f& dir, // they are on the cylinder and not past it: for (int i=-1; i<=1 && found !=2; i+=2) { Vec3f isect = closest + i*dist * projected_ray.direction(); - float par = (isect-proj_origin).norm() / par_scale; + Vec3f to_isect = isect-proj_origin; + float par = to_isect.norm() / par_scale; + if (to_isect.normalized().dot(proj_dir.normalized()) < 0.f) + par *= -1.f; Vec3d hit_normal = (pos-isect).normalized().cast(); isect = ray.pointAt(par); // check that the intersection is between the base planes: diff --git a/tests/sla_print/sla_raycast_tests.cpp b/tests/sla_print/sla_raycast_tests.cpp index 4a994f2a93..74c7994723 100644 --- a/tests/sla_print/sla_raycast_tests.cpp +++ b/tests/sla_print/sla_raycast_tests.cpp @@ -8,6 +8,38 @@ using namespace Slic3r; +// First do a simple test of the hole raycaster. +TEST_CASE("Raycaster - find intersections of a line and cylinder") +{ + sla::DrainHole hole{Vec3f(0,0,0), Vec3f(0,0,1), 5, 10}; + std::array, 2> out; + Vec3f s; + Vec3f dir; + + // Start inside the hole and cast perpendicular to its axis. + s = {-1.f, 0, 5.f}; + dir = {1.f, 0, 0}; + hole.get_intersections(s, dir, out); + REQUIRE(out[0].first == Approx(-4.f)); + REQUIRE(out[1].first == Approx(6.f)); + + // Start outside and cast parallel to axis. + s = {0, 0, -1.f}; + dir = {0, 0, 1.f}; + hole.get_intersections(s, dir, out); + REQUIRE(std::abs(out[0].first - 1.f) < 0.001f); + REQUIRE(std::abs(out[1].first - 11.f) < 0.001f); + + // Start outside and cast so that entry is in base and exit on the cylinder + s = {0, -1.f, -1.f}; + dir = {0, 1.f, 1.f}; + dir.normalize(); + hole.get_intersections(s, dir, out); + REQUIRE(std::abs(out[0].first - std::sqrt(2.f)) < 0.001f); + REQUIRE(std::abs(out[1].first - std::sqrt(72.f)) < 0.001f); +} + + // Create a simple scene with a 20mm cube and a big hole in the front wall // with 5mm radius. Then shoot rays from interesting positions and see where // they land.