mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-10 00:59:10 +08:00
Getting around signed_distance in pinhead_mesh_intersect
This commit is contained in:
parent
4e82e32a27
commit
3f10b2f7f8
@ -565,7 +565,7 @@ inline double ray_mesh_intersect(const Vec3d& s,
|
|||||||
const Vec3d& dir,
|
const Vec3d& dir,
|
||||||
const EigenMesh3D& m)
|
const EigenMesh3D& m)
|
||||||
{
|
{
|
||||||
return m.query_ray_hit(s, dir);
|
return m.query_ray_hit(s, dir).distance();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function will test if a future pinhead would not collide with the model
|
// This function will test if a future pinhead would not collide with the model
|
||||||
@ -588,7 +588,7 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
|||||||
double r_back,
|
double r_back,
|
||||||
double width,
|
double width,
|
||||||
const EigenMesh3D& m,
|
const EigenMesh3D& m,
|
||||||
unsigned samples = 4,
|
unsigned samples = 8,
|
||||||
double safety_distance = 0.001)
|
double safety_distance = 0.001)
|
||||||
{
|
{
|
||||||
// method based on:
|
// method based on:
|
||||||
@ -643,15 +643,26 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
|||||||
// Point ps is not on mesh but can be inside or outside as well. This
|
// Point ps is not on mesh but can be inside or outside as well. This
|
||||||
// would cause many problems with ray-casting. So we query the closest
|
// would cause many problems with ray-casting. So we query the closest
|
||||||
// point on the mesh to this.
|
// point on the mesh to this.
|
||||||
auto psq = m.signed_distance(ps);
|
// auto psq = m.signed_distance(ps);
|
||||||
|
|
||||||
// This is the point on the circle on the back sphere
|
// This is the point on the circle on the back sphere
|
||||||
Vec3d p(c(X) + rpbcos * a(X) + rpbsin * b(X),
|
Vec3d p(c(X) + rpbcos * a(X) + rpbsin * b(X),
|
||||||
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 - psq.point_on_mesh()).normalized();
|
// Vec3d n = (p - psq.point_on_mesh()).normalized();
|
||||||
phi = m.query_ray_hit(psq.point_on_mesh() + sd*n, n);
|
// phi = m.query_ray_hit(psq.point_on_mesh() + sd*n, n);
|
||||||
|
|
||||||
|
Vec3d n = (p - ps).normalized();
|
||||||
|
auto hr = m.query_ray_hit(ps + sd*n, n);
|
||||||
|
|
||||||
|
if(hr.is_inside()) { // the hit is inside the model
|
||||||
|
if(hr.distance() > 2*r_pin) phi = 0;
|
||||||
|
else {
|
||||||
|
auto hr2 = m.query_ray_hit(ps + (hr.distance() + 2*sd)*n, n);
|
||||||
|
phi = hr2.distance();
|
||||||
|
}
|
||||||
|
} else phi = hr.distance();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto mit = std::min_element(phis.begin(), phis.end());
|
auto mit = std::min_element(phis.begin(), phis.end());
|
||||||
@ -659,10 +670,14 @@ double pinhead_mesh_intersect(const Vec3d& s,
|
|||||||
return *mit;
|
return *mit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checking bridge (pillar and stick as well) intersection with the model. If
|
||||||
|
// the function is used for headless sticks, the ins_check parameter have to be
|
||||||
|
// true as the beginning of the stick might be inside the model geometry.
|
||||||
double bridge_mesh_intersect(const Vec3d& s,
|
double bridge_mesh_intersect(const Vec3d& s,
|
||||||
const Vec3d& dir,
|
const Vec3d& dir,
|
||||||
double r,
|
double r,
|
||||||
const EigenMesh3D& m,
|
const EigenMesh3D& m,
|
||||||
|
bool ins_check = false,
|
||||||
unsigned samples = 4,
|
unsigned samples = 4,
|
||||||
double safety_distance = 0.001)
|
double safety_distance = 0.001)
|
||||||
{
|
{
|
||||||
@ -678,7 +693,7 @@ double bridge_mesh_intersect(const Vec3d& s,
|
|||||||
for(size_t i = 0; i < phis.size(); ++i) phis[i] = i*2*PI/phis.size();
|
for(size_t i = 0; i < phis.size(); ++i) phis[i] = i*2*PI/phis.size();
|
||||||
|
|
||||||
tbb::parallel_for(size_t(0), phis.size(),
|
tbb::parallel_for(size_t(0), phis.size(),
|
||||||
[&phis, &m, a, b, sd, dir, r, s](size_t i)
|
[&phis, &m, a, b, sd, dir, r, s, ins_check](size_t i)
|
||||||
{
|
{
|
||||||
double& phi = phis[i];
|
double& phi = phis[i];
|
||||||
double sinphi = std::sin(phi);
|
double sinphi = std::sin(phi);
|
||||||
@ -693,11 +708,13 @@ double bridge_mesh_intersect(const Vec3d& s,
|
|||||||
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));
|
||||||
|
|
||||||
|
Vec3d sp;
|
||||||
|
if(ins_check) {
|
||||||
auto result = m.signed_distance(p);
|
auto result = m.signed_distance(p);
|
||||||
|
sp = result.value() < 0 ? result.point_on_mesh() : p;
|
||||||
|
} else sp = p;
|
||||||
|
|
||||||
Vec3d sp = result.value() < 0 ? result.point_on_mesh() : p;
|
phi = m.query_ray_hit(sp + sd*dir, dir).distance();
|
||||||
|
|
||||||
phi = m.query_ray_hit(sp + sd*dir, dir);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
auto mit = std::min_element(phis.begin(), phis.end());
|
auto mit = std::min_element(phis.begin(), phis.end());
|
||||||
@ -1538,12 +1555,12 @@ 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, pradius]
|
[&tifcl, &cfg, &result, &emesh, maxbridgelen, gndlvl, pradius]
|
||||||
(SpatIndex& spindex, const Vec3d& jsh)
|
(SpatIndex& spindex, const Vec3d& jsh)
|
||||||
{
|
{
|
||||||
long nearest_id = -1;
|
long nearest_id = -1;
|
||||||
const double max_len = maxbridgelen / 2;
|
const double max_len = maxbridgelen / 2;
|
||||||
while(nearest_id < 0 && !spindex.empty()) {
|
while(nearest_id < 0 && !spindex.empty()) { tifcl();
|
||||||
// loop until a suitable head is not found
|
// loop until a suitable head is not found
|
||||||
// if there is a pillar closer than the cluster center
|
// if there is a pillar closer than the cluster center
|
||||||
// (this may happen as the clustering is not perfect)
|
// (this may happen as the clustering is not perfect)
|
||||||
@ -1660,7 +1677,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
if(!ring.empty()) {
|
if(!ring.empty()) {
|
||||||
// inner ring is now in 'newring' and outer ring is in 'ring'
|
// inner ring is now in 'newring' and outer ring is in 'ring'
|
||||||
SpatIndex innerring;
|
SpatIndex innerring;
|
||||||
for(unsigned i : newring) {
|
for(unsigned i : newring) { tifcl();
|
||||||
const Pillar& pill = result.head_pillar(gndidx[i]);
|
const Pillar& pill = result.head_pillar(gndidx[i]);
|
||||||
assert(pill.id >= 0);
|
assert(pill.id >= 0);
|
||||||
innerring.insert(pill.endpoint, unsigned(pill.id));
|
innerring.insert(pill.endpoint, unsigned(pill.id));
|
||||||
@ -1669,7 +1686,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
// For all pillars in the outer ring find the closest in the
|
// For all pillars in the outer ring find the closest in the
|
||||||
// inner ring and connect them. This will create the spider web
|
// inner ring and connect them. This will create the spider web
|
||||||
// fashioned connections between pillars
|
// fashioned connections between pillars
|
||||||
for(unsigned i : ring) {
|
for(unsigned i : ring) { tifcl();
|
||||||
const Pillar& outerpill = result.head_pillar(gndidx[i]);
|
const Pillar& outerpill = result.head_pillar(gndidx[i]);
|
||||||
auto res = innerring.nearest(outerpill.endpoint, 1);
|
auto res = innerring.nearest(outerpill.endpoint, 1);
|
||||||
if(res.empty()) continue;
|
if(res.empty()) continue;
|
||||||
@ -1695,6 +1712,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
next != ring.end();
|
next != ring.end();
|
||||||
++it, ++next)
|
++it, ++next)
|
||||||
{
|
{
|
||||||
|
tifcl();
|
||||||
const Pillar& pillar = result.head_pillar(gndidx[*it]);
|
const Pillar& pillar = result.head_pillar(gndidx[*it]);
|
||||||
const Pillar& nextpillar = result.head_pillar(gndidx[*next]);
|
const Pillar& nextpillar = result.head_pillar(gndidx[*next]);
|
||||||
interconnect(pillar, nextpillar, emesh, result);
|
interconnect(pillar, nextpillar, emesh, result);
|
||||||
@ -1802,7 +1820,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
|||||||
Vec3d sj = sp + R * n; // stick start point
|
Vec3d sj = sp + R * n; // stick start point
|
||||||
|
|
||||||
// This is only for checking
|
// This is only for checking
|
||||||
double idist = bridge_mesh_intersect(sph, dir, R, emesh);
|
double idist = bridge_mesh_intersect(sph, dir, R, emesh, true);
|
||||||
double dist = ray_mesh_intersect(sj, dir, emesh);
|
double dist = ray_mesh_intersect(sj, dir, emesh);
|
||||||
|
|
||||||
if(std::isinf(idist) || std::isnan(idist) || idist < 2*R ||
|
if(std::isinf(idist) || std::isnan(idist) || idist < 2*R ||
|
||||||
|
@ -125,8 +125,38 @@ public:
|
|||||||
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; }
|
||||||
|
|
||||||
|
// Result of a raycast
|
||||||
|
class hit_result {
|
||||||
|
double m_t = std::numeric_limits<double>::infinity();
|
||||||
|
int m_face_id = -1;
|
||||||
|
const EigenMesh3D& m_mesh;
|
||||||
|
Vec3d m_dir;
|
||||||
|
inline hit_result(const EigenMesh3D& em): m_mesh(em) {}
|
||||||
|
friend class EigenMesh3D;
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline double distance() const { return m_t; }
|
||||||
|
|
||||||
|
inline int face() const { return m_face_id; }
|
||||||
|
|
||||||
|
inline Vec3d normal() const {
|
||||||
|
if(m_face_id < 0) return {};
|
||||||
|
auto trindex = m_mesh.m_F.row(m_face_id);
|
||||||
|
const Vec3d& p1 = m_mesh.V().row(trindex(0));
|
||||||
|
const Vec3d& p2 = m_mesh.V().row(trindex(1));
|
||||||
|
const Vec3d& p3 = m_mesh.V().row(trindex(2));
|
||||||
|
Eigen::Vector3d U = p2 - p1;
|
||||||
|
Eigen::Vector3d V = p3 - p1;
|
||||||
|
return U.cross(V).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_inside() {
|
||||||
|
return m_face_id >= 0 && normal().dot(m_dir) > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Casting a ray on the mesh, returns the distance where the hit occures.
|
// Casting a ray on the mesh, returns the distance where the hit occures.
|
||||||
double query_ray_hit(const Vec3d &s, const Vec3d &dir) const;
|
hit_result query_ray_hit(const Vec3d &s, const Vec3d &dir) const;
|
||||||
|
|
||||||
class si_result {
|
class si_result {
|
||||||
double m_value;
|
double m_value;
|
||||||
|
@ -153,13 +153,19 @@ EigenMesh3D &EigenMesh3D::operator=(const EigenMesh3D &other)
|
|||||||
m_aabb.reset(new AABBImpl(*other.m_aabb)); return *this;
|
m_aabb.reset(new AABBImpl(*other.m_aabb)); return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
double EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
EigenMesh3D::hit_result
|
||||||
|
EigenMesh3D::query_ray_hit(const Vec3d &s, const Vec3d &dir) const
|
||||||
{
|
{
|
||||||
igl::Hit hit;
|
igl::Hit hit;
|
||||||
hit.t = std::numeric_limits<float>::infinity();
|
hit.t = std::numeric_limits<float>::infinity();
|
||||||
m_aabb->intersect_ray(m_V, m_F, s, dir, hit);
|
m_aabb->intersect_ray(m_V, m_F, s, dir, hit);
|
||||||
|
|
||||||
return double(hit.t);
|
hit_result ret(*this);
|
||||||
|
ret.m_t = double(hit.t);
|
||||||
|
ret.m_dir = dir;
|
||||||
|
if(!std::isinf(hit.t) && !std::isnan(hit.t)) ret.m_face_id = hit.id;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EigenMesh3D::si_result EigenMesh3D::signed_distance(const Vec3d &p) const {
|
EigenMesh3D::si_result EigenMesh3D::signed_distance(const Vec3d &p) const {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user