EigenMesh upgraded with inside check capability.
This commit is contained in:
parent
7a677a673f
commit
e160cf3ffb
3 changed files with 95 additions and 27 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
* ****************************************************************************/
|
* ****************************************************************************/
|
||||||
|
|
Loading…
Reference in a new issue