EigenMesh upgraded with inside check capability.

This commit is contained in:
tamasmeszaros 2019-01-17 16:44:26 +01:00
parent 7a677a673f
commit e160cf3ffb
3 changed files with 95 additions and 27 deletions

View file

@ -639,12 +639,10 @@ double pinhead_mesh_intersect(const Vec3d& s_original,
c(Y) + rpbcos * a(Y) + rpbsin * b(Y), c(Y) + rpbcos * a(Y) + rpbsin * b(Y),
c(Z) + rpbcos * a(Z) + rpbsin * b(Z)); c(Z) + rpbcos * a(Z) + rpbsin * b(Z));
Vec3d n = (p - ps).normalized(); if(m.inside(ps) && m.inside(p)) {
Vec3d n = (p - ps).normalized();
phi = m.query_ray_hit(ps, n); phi = m.query_ray_hit(ps, n);
} else phi = std::numeric_limits<double>::infinity();
// TODO: this should be an inside check
if(phi < r_pin) phi = std::numeric_limits<double>::infinity();
std::cout << "t = " << phi << std::endl; std::cout << "t = " << phi << std::endl;
} }
@ -684,7 +682,8 @@ double bridge_mesh_intersect(const Vec3d& s_original,
s(Y) + rcos * a(Y) + rsin * b(Y), s(Y) + rcos * a(Y) + rsin * b(Y),
s(Z) + rcos * a(Z) + rsin * b(Z)); s(Z) + rcos * a(Z) + rsin * b(Z));
phi = m.query_ray_hit(p, dir); if(m.inside(p)) phi = m.query_ray_hit(p, dir);
else phi = std::numeric_limits<double>::infinity();
} }
auto mit = std::min_element(phis.begin(), phis.end()); auto mit = std::min_element(phis.begin(), phis.end());
@ -1195,9 +1194,7 @@ bool SLASupportTree::generate(const PointSet &points,
w, w,
mesh); mesh);
if(t > 2*w || std::isinf(t)) { if(t > w || std::isinf(t)) {
// 2*w because of lower and upper pinhead
head_pos.row(pcount) = hp; head_pos.row(pcount) = hp;
// save the verified and corrected normal // save the verified and corrected normal
@ -1269,17 +1266,59 @@ bool SLASupportTree::generate(const PointSet &points,
for(unsigned i = 0; i < head_pos.rows(); i++) { for(unsigned i = 0; i < head_pos.rows(); i++) {
tifcl(); tifcl();
auto& head = result.heads()[i]; auto& head = result.head(i);
Vec3d dir(0, 0, -1); Vec3d dir(0, 0, -1);
Vec3d startpoint = head.junction_point(); bool accept = false;
int ri = 1;
double t = std::numeric_limits<double>::infinity();
double hw = head.width_mm;
double t = ray_mesh_intersect(startpoint, dir, mesh); while(!accept && head.width_mm > 0) {
Vec3d startpoint = head.junction_point();
// Collision detection
t = bridge_mesh_intersect(startpoint, dir, head.r_back_mm, mesh);
// Precise distance measurement
double tprec = ray_mesh_intersect(startpoint, dir, mesh);
if(std::isinf(tprec) && !std::isinf(t)) {
// This is a damned case where the pillar melds into the model
// but its center ray can reach the ground. We can not route
// this to the ground nor to the model surface. We have to
// modify the head or discard this support point.
head.width_mm = hw + (ri % 2? -1 : 1) * ri * head.r_back_mm;
} else {
accept = true; t = tprec;
auto id = head.id;
// We need to regenerate the head geometry
head = Head(head.r_back_mm,
head.r_pin_mm,
head.width_mm,
head.penetration_mm,
head.dir,
head.tr);
head.id = id;
}
ri++;
}
gndheight.emplace_back(t); gndheight.emplace_back(t);
if(std::isinf(t)) gndidx.emplace_back(i); if(accept) {
else nogndidx.emplace_back(i); if(std::isinf(t)) gndidx.emplace_back(i);
else nogndidx.emplace_back(i);
} else {
BOOST_LOG_TRIVIAL(warning) << "A support point at "
<< head.tr.transpose()
<< " had to be discarded as there is"
<< " nowhere to route it.";
head.invalidate();
}
} }
PointSet gnd(gndidx.size(), 3); PointSet gnd(gndidx.size(), 3);
@ -1321,7 +1360,6 @@ bool SLASupportTree::generate(const PointSet &points,
double zstep = pillar_dist * std::tan(-cfg.tilt); double zstep = pillar_dist * std::tan(-cfg.tilt);
ej(Z) = sj(Z) + zstep; ej(Z) = sj(Z) + zstep;
// double chkd = ray_mesh_intersect(sj, dirv(sj, ej), emesh);
double chkd = bridge_mesh_intersect(sj, dirv(sj, ej), pillar.r, emesh); double chkd = bridge_mesh_intersect(sj, dirv(sj, ej), pillar.r, emesh);
double bridge_distance = pillar_dist / std::cos(-cfg.tilt); double bridge_distance = pillar_dist / std::cos(-cfg.tilt);
@ -1348,10 +1386,6 @@ bool SLASupportTree::generate(const PointSet &points,
Vec3d bej(sj(X), sj(Y), ej(Z)); Vec3d bej(sj(X), sj(Y), ej(Z));
// need to check collision for the cross stick // need to check collision for the cross stick
// double backchkd = ray_mesh_intersect(bsj,
// dirv(bsj, bej),
// emesh);
double backchkd = bridge_mesh_intersect(bsj, double backchkd = bridge_mesh_intersect(bsj,
dirv(bsj, bej), dirv(bsj, bej),
pillar.r, pillar.r,
@ -1365,7 +1399,6 @@ bool SLASupportTree::generate(const PointSet &points,
} }
sj.swap(ej); sj.swap(ej);
ej(Z) = sj(Z) + zstep; ej(Z) = sj(Z) + zstep;
// chkd = ray_mesh_intersect(sj, dirv(sj, ej), emesh);
chkd = bridge_mesh_intersect(sj, dirv(sj, ej), pillar.r, emesh); chkd = bridge_mesh_intersect(sj, dirv(sj, ej), pillar.r, emesh);
} }
}; };
@ -1444,7 +1477,7 @@ bool SLASupportTree::generate(const PointSet &points,
// is distributed more effectively on the pillar. // is distributed more effectively on the pillar.
auto search_nearest = auto search_nearest =
[&cfg, &result, &emesh, maxbridgelen, gndlvl] [&cfg, &result, &emesh, maxbridgelen, gndlvl, pradius]
(SpatIndex& spindex, const Vec3d& jsh) (SpatIndex& spindex, const Vec3d& jsh)
{ {
long nearest_id = -1; long nearest_id = -1;
@ -1476,7 +1509,9 @@ bool SLASupportTree::generate(const PointSet &points,
double d = distance(jp, jn); double d = distance(jp, jn);
if(jn(Z) <= gndlvl || d > max_len) break; if(jn(Z) <= gndlvl || d > max_len) break;
double chkd = ray_mesh_intersect(jp, dirv(jp, jn), emesh); double chkd = bridge_mesh_intersect(jp, dirv(jp, jn),
pradius,
emesh);
if(chkd >= d) nearest_id = ne.second; if(chkd >= d) nearest_id = ne.second;
spindex.remove(ne); spindex.remove(ne);
@ -1695,10 +1730,15 @@ bool SLASupportTree::generate(const PointSet &points,
Vec3d dir = {0, 0, -1}; Vec3d dir = {0, 0, -1};
Vec3d sj = sp + R * n; Vec3d sj = sp + R * n;
double dist = ray_mesh_intersect(sj, dir, emesh);
// This is only for checking
double dist = bridge_mesh_intersect(sj, dir, R, emesh);
if(std::isinf(dist) || std::isnan(dist) || dist < 2*R) continue; if(std::isinf(dist) || std::isnan(dist) || dist < 2*R) continue;
// This on the other hand will return the exact distance available
// measured through the center of the stick.
dist = ray_mesh_intersect(sj, dir, emesh);
Vec3d ej = sj + (dist + HWIDTH_MM)* dir; Vec3d ej = sj + (dist + HWIDTH_MM)* dir;
result.add_compact_bridge(sp, ej, n, R); result.add_compact_bridge(sp, ej, n, R);
} }

View file

@ -120,16 +120,21 @@ public:
~EigenMesh3D(); ~EigenMesh3D();
EigenMesh3D(const EigenMesh3D& other); EigenMesh3D(const EigenMesh3D& other);
// EigenMesh3D(EigenMesh3D&&) = default;
EigenMesh3D& operator=(const EigenMesh3D&); EigenMesh3D& operator=(const EigenMesh3D&);
// EigenMesh3D& operator=(EigenMesh3D&&) = default;
inline double ground_level() const { return m_ground_level; } inline double ground_level() const { return m_ground_level; }
inline const Eigen::MatrixXd& V() const { return m_V; } inline const Eigen::MatrixXd& V() const { return m_V; }
inline const Eigen::MatrixXi& F() const { return m_F; } inline const Eigen::MatrixXi& F() const { return m_F; }
// Casting a ray on the mesh, returns the distance where the hit occures.
double query_ray_hit(const Vec3d &s, const Vec3d &dir) const; double query_ray_hit(const Vec3d &s, const Vec3d &dir) const;
// The signed distance from a point to the mesh. Outputs the distance,
// the index of the triangle and the closest point in mesh coordinate space.
std::tuple<double, unsigned, Vec3d> signed_distance(const Vec3d& p) const;
bool inside(const Vec3d& p) const;
}; };
using PointSet = Eigen::MatrixXd; using PointSet = Eigen::MatrixXd;

View file

@ -3,6 +3,9 @@
#include "SLA/SLABoilerPlate.hpp" #include "SLA/SLABoilerPlate.hpp"
#include "SLA/SLASpatIndex.hpp" #include "SLA/SLASpatIndex.hpp"
// Workaround: IGL signed_distance.h will define PI in the igl namespace.
#undef PI
// HEAVY headers... takes eternity to compile // HEAVY headers... takes eternity to compile
// for concave hull merging decisions // for concave hull merging decisions
@ -12,6 +15,7 @@
#include <igl/ray_mesh_intersect.h> #include <igl/ray_mesh_intersect.h>
#include <igl/point_mesh_squared_distance.h> #include <igl/point_mesh_squared_distance.h>
#include <igl/remove_duplicate_vertices.h> #include <igl/remove_duplicate_vertices.h>
#include <igl/signed_distance.h>
#include "SLASpatIndex.hpp" #include "SLASpatIndex.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
@ -19,6 +23,9 @@
namespace Slic3r { namespace Slic3r {
namespace sla { namespace sla {
// Bring back PI from the igl namespace
using igl::PI;
/* ************************************************************************** /* **************************************************************************
* SpatIndex implementation * SpatIndex implementation
* ************************************************************************** */ * ************************************************************************** */
@ -86,7 +93,10 @@ size_t SpatIndex::size() const
* EigenMesh3D implementation * EigenMesh3D implementation
* ****************************************************************************/ * ****************************************************************************/
class EigenMesh3D::AABBImpl: public igl::AABB<Eigen::MatrixXd, 3> {}; class EigenMesh3D::AABBImpl: public igl::AABB<Eigen::MatrixXd, 3> {
public:
igl::WindingNumberAABB<Vec3d, Eigen::MatrixXd, Eigen::MatrixXi> windtree;
};
EigenMesh3D::EigenMesh3D(): m_aabb(new AABBImpl()) {} EigenMesh3D::EigenMesh3D(): m_aabb(new AABBImpl()) {}
@ -128,6 +138,9 @@ EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) {
// Build the AABB accelaration tree // Build the AABB accelaration tree
m_aabb->init(m_V, m_F); m_aabb->init(m_V, m_F);
m_aabb->windtree.set_mesh(m_V, m_F);
m_aabb->windtree.init();
} }
EigenMesh3D::~EigenMesh3D() {} EigenMesh3D::~EigenMesh3D() {}
@ -153,6 +166,16 @@ double EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
return double(hit.t); return double(hit.t);
} }
std::tuple<double, unsigned, Vec3d>
EigenMesh3D::signed_distance(const Vec3d &/*p*/) const {
// TODO: implement
return std::make_tuple(0.0, 0, Vec3d());
}
bool EigenMesh3D::inside(const Vec3d &p) const {
return m_aabb->windtree.inside(p);
}
/* **************************************************************************** /* ****************************************************************************
* Misc functions * Misc functions
* ****************************************************************************/ * ****************************************************************************/