Fixed a raycaster problem with handling duplicate hits from igl

The duplicate hits confused winding number calculations in the raycaster, which in turn returned incorrect hit.
This commit is contained in:
Lukas Matena 2020-01-09 14:06:39 +01:00
parent e9d340c87f
commit f22961edae
2 changed files with 10 additions and 7 deletions

View File

@ -297,7 +297,14 @@ EigenMesh3D::query_ray_hits(const Vec3d &s, const Vec3d &dir) const
// The sort is necessary, the hits are not always sorted. // The sort is necessary, the hits are not always sorted.
std::sort(hits.begin(), hits.end(), std::sort(hits.begin(), hits.end(),
[](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; }); [](const igl::Hit& a, const igl::Hit& b) { return a.t < b.t; });
// Remove duplicates. They sometimes appear, for example when the ray is cast
// along an axis of a cube due to floating-point approximations in igl (?)
hits.erase(std::unique(hits.begin(), hits.end(),
[](const igl::Hit& a, const igl::Hit& b)
{ return a.t == b.t; }),
hits.end());
// Convert the igl::Hit into hit_result // Convert the igl::Hit into hit_result
outs.reserve(hits.size()); outs.reserve(hits.size());
for (const igl::Hit& hit : hits) { for (const igl::Hit& hit : hits) {
@ -342,14 +349,11 @@ EigenMesh3D::hit_result EigenMesh3D::filter_hits(
for (const sla::DrainHole& hole : m_holes) { for (const sla::DrainHole& hole : m_holes) {
std::array<std::pair<float, Vec3d>, 2> isects; std::array<std::pair<float, Vec3d>, 2> isects;
if (hole.get_intersections(sf, dirf, isects)) { if (hole.get_intersections(sf, dirf, isects)) {
// Ignore hole hits behind the source
if (isects[0].first > 0.f) hole_isects.emplace_back(isects[0].first, isects[0].second, true); if (isects[0].first > 0.f) hole_isects.emplace_back(isects[0].first, isects[0].second, true);
if (isects[1].first > 0.f) hole_isects.emplace_back(isects[1].first, isects[1].second, false); if (isects[1].first > 0.f) hole_isects.emplace_back(isects[1].first, isects[1].second, false);
} }
} }
// // Remove hole hits behind the source
// for (int i=0; i<int(hole_isects.size()); ++i)
// if (hole_isects[i].t < 0.f)
// hole_isects.erase(hole_isects.begin() + (i--));
// Holes can intersect each other, sort the hits by t // Holes can intersect each other, sort the hits by t
std::sort(hole_isects.begin(), hole_isects.end(), std::sort(hole_isects.begin(), hole_isects.end(),

View File

@ -48,11 +48,10 @@ TEST_CASE("Raycaster with loaded drillholes", "[sla_raycast]")
REQUIRE(hit.distance() == Approx(radius)); REQUIRE(hit.distance() == Approx(radius));
} }
// Shouldn't this hit the inside wall through the hole?
SECTION("Fire from outside, hit the back side of the hole cylinder.") { SECTION("Fire from outside, hit the back side of the hole cylinder.") {
s.y() = -1.; s.y() = -1.;
auto hit = emesh.query_ray_hit(s, {0, 1., 0.}); auto hit = emesh.query_ray_hit(s, {0, 1., 0.});
REQUIRE(hit.distance() == Approx(hole_length + 1.f)); REQUIRE(hit.distance() == Approx(boxbb.size().y() - hcfg.min_thickness + 1.));
} }
SECTION("Check for support tree correctness") { SECTION("Check for support tree correctness") {