mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-15 10:47:50 -06:00
Bugfixes for support generator
* Fix support heads floating in air * Fix failing tests for the bridge mesh intersection * Fix failing assertions WIP refactoring support tree gen, as its a mess.
This commit is contained in:
parent
ed460a3e7e
commit
2ff04e6f68
4 changed files with 371 additions and 271 deletions
|
@ -15,6 +15,119 @@ using libnest2d::opt::StopCriteria;
|
|||
using libnest2d::opt::GeneticOptimizer;
|
||||
using libnest2d::opt::SubplexOptimizer;
|
||||
|
||||
EigenMesh3D::hit_result query_hit(const SupportableMesh &msh, const Head &h)
|
||||
{
|
||||
static const size_t SAMPLES = 8;
|
||||
|
||||
// Move away slightly from the touching point to avoid raycasting on the
|
||||
// inner surface of the mesh.
|
||||
|
||||
const double& sd = msh.cfg.safety_distance_mm;
|
||||
|
||||
auto& m = msh.emesh;
|
||||
using HitResult = EigenMesh3D::hit_result;
|
||||
|
||||
// Hit results
|
||||
std::array<HitResult, SAMPLES> hits;
|
||||
|
||||
Vec3d s1 = h.pos, s2 = h.junction_point();
|
||||
|
||||
struct Rings {
|
||||
double rpin;
|
||||
double rback;
|
||||
Vec3d spin;
|
||||
Vec3d sback;
|
||||
PointRing<SAMPLES> ring;
|
||||
|
||||
Vec3d backring(size_t idx) { return ring.get(idx, sback, rback); }
|
||||
Vec3d pinring(size_t idx) { return ring.get(idx, spin, rpin); }
|
||||
} rings {h.r_pin_mm + sd, h.r_back_mm + sd, s1, s2, h.dir};
|
||||
|
||||
// We will shoot multiple rays from the head pinpoint in the direction
|
||||
// of the pinhead robe (side) surface. The result will be the smallest
|
||||
// hit distance.
|
||||
|
||||
auto hitfn = [&m, &rings, sd](HitResult &hit, size_t i) {
|
||||
// Point on the circle on the pin sphere
|
||||
Vec3d ps = rings.pinring(i);
|
||||
// This is the point on the circle on the back sphere
|
||||
Vec3d p = rings.backring(i);
|
||||
|
||||
// Point ps is not on mesh but can be inside or
|
||||
// outside as well. This would cause many problems
|
||||
// with ray-casting. To detect the position we will
|
||||
// use the ray-casting result (which has an is_inside
|
||||
// predicate).
|
||||
|
||||
Vec3d n = (p - ps).normalized();
|
||||
auto q = m.query_ray_hit(ps + sd * n, n);
|
||||
|
||||
if (q.is_inside()) { // the hit is inside the model
|
||||
if (q.distance() > rings.rpin) {
|
||||
// If we are inside the model and the hit
|
||||
// distance is bigger than our pin circle
|
||||
// diameter, it probably indicates that the
|
||||
// support point was already inside the
|
||||
// model, or there is really no space
|
||||
// around the point. We will assign a zero
|
||||
// hit distance to these cases which will
|
||||
// enforce the function return value to be
|
||||
// an invalid ray with zero hit distance.
|
||||
// (see min_element at the end)
|
||||
hit = HitResult(0.0);
|
||||
} else {
|
||||
// re-cast the ray from the outside of the
|
||||
// object. The starting point has an offset
|
||||
// of 2*safety_distance because the
|
||||
// original ray has also had an offset
|
||||
auto q2 = m.query_ray_hit(ps + (q.distance() + 2 * sd) * n, n);
|
||||
hit = q2;
|
||||
}
|
||||
} else
|
||||
hit = q;
|
||||
};
|
||||
|
||||
ccr::enumerate(hits.begin(), hits.end(), hitfn);
|
||||
|
||||
return min_hit(hits);
|
||||
}
|
||||
|
||||
EigenMesh3D::hit_result query_hit(const SupportableMesh &msh, const Bridge &br, double safety_d)
|
||||
{
|
||||
|
||||
static const size_t SAMPLES = 8;
|
||||
|
||||
Vec3d dir = (br.endp - br.startp).normalized();
|
||||
PointRing<SAMPLES> ring{dir};
|
||||
|
||||
using Hit = EigenMesh3D::hit_result;
|
||||
|
||||
// Hit results
|
||||
std::array<Hit, SAMPLES> hits;
|
||||
|
||||
double sd = std::isnan(safety_d) ? msh.cfg.safety_distance_mm : safety_d;
|
||||
|
||||
auto hitfn = [&msh, &br, &ring, dir, sd] (Hit &hit, size_t i) {
|
||||
|
||||
// Point on the circle on the pin sphere
|
||||
Vec3d p = ring.get(i, br.startp, br.r + sd);
|
||||
|
||||
auto hr = msh.emesh.query_ray_hit(p + br.r * dir, dir);
|
||||
|
||||
if(hr.is_inside()) {
|
||||
if(hr.distance() > 2 * br.r + sd) hit = Hit(0.0);
|
||||
else {
|
||||
// re-cast the ray from the outside of the object
|
||||
hit = msh.emesh.query_ray_hit(p + (hr.distance() + 2 * sd) * dir, dir);
|
||||
}
|
||||
} else hit = hr;
|
||||
};
|
||||
|
||||
ccr::enumerate(hits.begin(), hits.end(), hitfn);
|
||||
|
||||
return min_hit(hits);
|
||||
}
|
||||
|
||||
SupportTreeBuildsteps::SupportTreeBuildsteps(SupportTreeBuilder & builder,
|
||||
const SupportableMesh &sm)
|
||||
: m_cfg(sm.cfg)
|
||||
|
@ -246,7 +359,7 @@ EigenMesh3D::hit_result SupportTreeBuildsteps::pinhead_mesh_intersect(
|
|||
}
|
||||
|
||||
EigenMesh3D::hit_result SupportTreeBuildsteps::bridge_mesh_intersect(
|
||||
const Vec3d &src, const Vec3d &dir, double r, double safety_d)
|
||||
const Vec3d &src, const Vec3d &dir, double r, double sd)
|
||||
{
|
||||
static const size_t SAMPLES = 8;
|
||||
PointRing<SAMPLES> ring{dir};
|
||||
|
@ -255,25 +368,20 @@ EigenMesh3D::hit_result SupportTreeBuildsteps::bridge_mesh_intersect(
|
|||
|
||||
// Hit results
|
||||
std::array<Hit, SAMPLES> hits;
|
||||
|
||||
double sd = std::isnan(safety_d) ? m_cfg.safety_distance_mm : safety_d;
|
||||
sd = sd * r / m_cfg.head_back_radius_mm;
|
||||
|
||||
bool ins_check = sd < m_cfg.safety_distance_mm;
|
||||
|
||||
ccr::enumerate(hits.begin(), hits.end(),
|
||||
[this, r, src, ins_check, &ring, dir, sd] (Hit &hit, size_t i) {
|
||||
[this, r, src, /*ins_check,*/ &ring, dir, sd] (Hit &hit, size_t i) {
|
||||
|
||||
// Point on the circle on the pin sphere
|
||||
Vec3d p = ring.get(i, src, r + sd);
|
||||
|
||||
auto hr = m_mesh.query_ray_hit(p + r * dir, dir);
|
||||
|
||||
if(ins_check && hr.is_inside()) {
|
||||
if(/*ins_check && */hr.is_inside()) {
|
||||
if(hr.distance() > 2 * r + sd) hit = Hit(0.0);
|
||||
else {
|
||||
// re-cast the ray from the outside of the object
|
||||
hit = m_mesh.query_ray_hit(p + (hr.distance() + 2 * sd) * dir, dir);
|
||||
hit = m_mesh.query_ray_hit(p + (hr.distance() + EPSILON) * dir, dir);
|
||||
}
|
||||
} else hit = hr;
|
||||
});
|
||||
|
@ -499,7 +607,7 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &jp,
|
|||
normal_mode = false;
|
||||
|
||||
if (t > m_cfg.max_bridge_length_mm || endp(Z) < gndlvl) {
|
||||
m_builder.add_pillar(head_id, jp, radius);
|
||||
if (head_id >= 0) m_builder.add_pillar(head_id, jp, radius);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -507,7 +615,7 @@ bool SupportTreeBuildsteps::create_ground_pillar(const Vec3d &jp,
|
|||
|
||||
// Check if the deduced route is sane and exit with error if not.
|
||||
if (bridge_mesh_distance(jp, dir, radius) < (endp - jp).norm()) {
|
||||
m_builder.add_pillar(head_id, jp, radius);
|
||||
if (head_id >= 0) m_builder.add_pillar(head_id, jp, radius);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -798,13 +906,16 @@ void SupportTreeBuildsteps::routing_to_ground()
|
|||
cl_centroids.emplace_back(hid);
|
||||
|
||||
Head &h = m_builder.head(hid);
|
||||
h.transform();
|
||||
|
||||
if (!create_ground_pillar(h.junction_point(), h.dir, h.r_back_mm, h.id)) {
|
||||
BOOST_LOG_TRIVIAL(warning)
|
||||
<< "Pillar cannot be created for support point id: " << hid;
|
||||
h.invalidate();
|
||||
m_iheads_onmodel.emplace_back(h.id);
|
||||
// h.invalidate();
|
||||
continue;
|
||||
}
|
||||
|
||||
h.transform();
|
||||
}
|
||||
|
||||
// now we will go through the clusters ones again and connect the
|
||||
|
@ -854,12 +965,14 @@ bool SupportTreeBuildsteps::connect_to_ground(Head &head, const Vec3d &dir)
|
|||
if(!std::isinf(tdown)) return false;
|
||||
|
||||
Vec3d endp = hjp + d * dir;
|
||||
m_builder.add_bridge(head.id, endp);
|
||||
m_builder.add_junction(endp, head.r_back_mm);
|
||||
bool ret = false;
|
||||
|
||||
if ((ret = create_ground_pillar(endp, dir, head.r_back_mm))) {
|
||||
m_builder.add_bridge(head.id, endp);
|
||||
m_builder.add_junction(endp, head.r_back_mm);
|
||||
}
|
||||
|
||||
this->create_ground_pillar(endp, dir, head.r_back_mm);
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SupportTreeBuildsteps::connect_to_ground(Head &head)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue