mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 16:57:53 -06:00
Fixes for degenerate cases.
This commit is contained in:
parent
c82fd692c3
commit
3b0e0aaed4
4 changed files with 80 additions and 63 deletions
|
@ -239,7 +239,8 @@ void offset(ExPolygon& sh, coord_t distance, bool edgerounding = true) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void offset(Polygon& sh, coord_t distance, bool edgerounding = true) {
|
void offset(Polygon &sh, coord_t distance, bool edgerounding = true)
|
||||||
|
{
|
||||||
using ClipperLib::ClipperOffset;
|
using ClipperLib::ClipperOffset;
|
||||||
using ClipperLib::jtRound;
|
using ClipperLib::jtRound;
|
||||||
using ClipperLib::jtMiter;
|
using ClipperLib::jtMiter;
|
||||||
|
|
|
@ -73,6 +73,7 @@ public:
|
||||||
|
|
||||||
inline double ground_level() const { return m_ground_level + m_gnd_offset; }
|
inline double ground_level() const { return m_ground_level + m_gnd_offset; }
|
||||||
inline void ground_level_offset(double o) { m_gnd_offset = o; }
|
inline void ground_level_offset(double o) { m_gnd_offset = o; }
|
||||||
|
inline double ground_level_offset() const { return m_gnd_offset; }
|
||||||
|
|
||||||
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; }
|
||||||
|
|
|
@ -530,6 +530,7 @@ struct CompactBridge {
|
||||||
const Vec3d& ep,
|
const Vec3d& ep,
|
||||||
const Vec3d& n,
|
const Vec3d& n,
|
||||||
double r,
|
double r,
|
||||||
|
bool endball = true,
|
||||||
size_t steps = 45)
|
size_t steps = 45)
|
||||||
{
|
{
|
||||||
Vec3d startp = sp + r * n;
|
Vec3d startp = sp + r * n;
|
||||||
|
@ -544,11 +545,13 @@ struct CompactBridge {
|
||||||
auto upperball = sphere(r, Portion{PI / 2 - fa, PI}, fa);
|
auto upperball = sphere(r, Portion{PI / 2 - fa, PI}, fa);
|
||||||
for(auto& p : upperball.points) p += startp;
|
for(auto& p : upperball.points) p += startp;
|
||||||
|
|
||||||
|
if(endball) {
|
||||||
auto lowerball = sphere(r, Portion{0, PI/2 + 2*fa}, fa);
|
auto lowerball = sphere(r, Portion{0, PI/2 + 2*fa}, fa);
|
||||||
for(auto& p : lowerball.points) p += endp;
|
for(auto& p : lowerball.points) p += endp;
|
||||||
|
mesh.merge(lowerball);
|
||||||
|
}
|
||||||
|
|
||||||
mesh.merge(upperball);
|
mesh.merge(upperball);
|
||||||
mesh.merge(lowerball);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -594,13 +597,17 @@ struct Pad {
|
||||||
// base silhouette. Create the offsetted version and punch the
|
// base silhouette. Create the offsetted version and punch the
|
||||||
// breaksticks across its perimeter.
|
// breaksticks across its perimeter.
|
||||||
|
|
||||||
ExPolygons modelbase_sticks = modelbase;
|
ExPolygons modelbase_offs = modelbase;
|
||||||
|
|
||||||
if (pcfg.embed_object.object_gap_mm > 0.0)
|
if (pcfg.embed_object.object_gap_mm > 0.0)
|
||||||
modelbase_sticks
|
modelbase_offs
|
||||||
= offset_ex(modelbase_sticks,
|
= offset_ex(modelbase_offs,
|
||||||
float(scaled(pcfg.embed_object.object_gap_mm)));
|
float(scaled(pcfg.embed_object.object_gap_mm)));
|
||||||
|
|
||||||
|
// Create a spatial index of the support silhouette polygons.
|
||||||
|
// This will be used to check for intersections with the model
|
||||||
|
// silhouette polygons. If there is no intersection, then a certain
|
||||||
|
// part of the pad is redundant as it does not host any supports.
|
||||||
BoxIndex bindex;
|
BoxIndex bindex;
|
||||||
{
|
{
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
|
@ -611,14 +618,27 @@ struct Pad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Punching the breaksticks across the offsetted polygon perimeters
|
||||||
ExPolygons pad_stickholes; pad_stickholes.reserve(modelbase.size());
|
ExPolygons pad_stickholes; pad_stickholes.reserve(modelbase.size());
|
||||||
for(auto& poly : modelbase_sticks) {
|
for(auto& poly : modelbase_offs) {
|
||||||
|
|
||||||
if (!bindex.query(poly.contour.bounding_box(),
|
std::vector<BoxIndexEl> qres =
|
||||||
BoxIndex::qtIntersects).empty()) {
|
bindex.query(poly.contour.bounding_box(),
|
||||||
|
BoxIndex::qtIntersects);
|
||||||
|
|
||||||
|
if (!qres.empty()) {
|
||||||
|
|
||||||
|
// The model silhouette polygon 'poly' HAS an intersection
|
||||||
|
// with the support silhouettes. Include this polygon
|
||||||
|
// in the pad holes with the breaksticks and merge the
|
||||||
|
// original (offsetted) version with the rest of the pad
|
||||||
|
// base plate.
|
||||||
|
|
||||||
basep.emplace_back(poly.contour);
|
basep.emplace_back(poly.contour);
|
||||||
|
|
||||||
|
// The holes of 'poly' will become positive parts of the
|
||||||
|
// pad, so they has to be checked for intersections as well
|
||||||
|
// and erased if there is no intersection with the supports
|
||||||
auto it = poly.holes.begin();
|
auto it = poly.holes.begin();
|
||||||
while(it != poly.holes.end()) {
|
while(it != poly.holes.end()) {
|
||||||
if (bindex.query(it->bounding_box(),
|
if (bindex.query(it->bounding_box(),
|
||||||
|
@ -628,6 +648,7 @@ struct Pad {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Punch the breaksticks
|
||||||
sla::breakstick_holes(
|
sla::breakstick_holes(
|
||||||
poly,
|
poly,
|
||||||
pcfg.embed_object.object_gap_mm, // padding
|
pcfg.embed_object.object_gap_mm, // padding
|
||||||
|
@ -1495,12 +1516,13 @@ class SLASupportTree::Algorithm {
|
||||||
Vec3d pgnd = {endp(X), endp(Y), gndlvl};
|
Vec3d pgnd = {endp(X), endp(Y), gndlvl};
|
||||||
can_add_base = result.score > min_dist;
|
can_add_base = result.score > min_dist;
|
||||||
|
|
||||||
|
double gnd_offs = m_mesh.ground_level_offset();
|
||||||
auto abort_in_shame =
|
auto abort_in_shame =
|
||||||
[&normal_mode, &can_add_base, &endp, jp, gndlvl]()
|
[gnd_offs, &normal_mode, &can_add_base, &endp, jp, gndlvl]()
|
||||||
{
|
{
|
||||||
normal_mode = true;
|
normal_mode = true;
|
||||||
can_add_base = false; // Nothing left to do, hope for the best
|
can_add_base = false; // Nothing left to do, hope for the best
|
||||||
endp = {jp(X), jp(Y), gndlvl};
|
endp = {jp(X), jp(Y), gndlvl - gnd_offs };
|
||||||
};
|
};
|
||||||
|
|
||||||
// We have to check if the bridge is feasible.
|
// We have to check if the bridge is feasible.
|
||||||
|
@ -2317,7 +2339,8 @@ public:
|
||||||
double idist = bridge_mesh_intersect(sph, dir, R, true);
|
double idist = bridge_mesh_intersect(sph, dir, R, true);
|
||||||
double dist = ray_mesh_intersect(sj, dir);
|
double dist = ray_mesh_intersect(sj, dir);
|
||||||
if (std::isinf(dist))
|
if (std::isinf(dist))
|
||||||
dist = sph(Z) - m_result.ground_level - HWIDTH_MM;
|
dist = sph(Z) - m_mesh.ground_level()
|
||||||
|
+ m_mesh.ground_level_offset();
|
||||||
|
|
||||||
if(std::isnan(idist) || idist < 2*R ||
|
if(std::isnan(idist) || idist < 2*R ||
|
||||||
std::isnan(dist) || dist < 2*R)
|
std::isnan(dist) || dist < 2*R)
|
||||||
|
@ -2329,7 +2352,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3d ej = sj + (dist + HWIDTH_MM)* dir;
|
Vec3d ej = sj + (dist + HWIDTH_MM)* dir;
|
||||||
m_result.add_compact_bridge(sp, ej, n, R);
|
m_result.add_compact_bridge(sp, ej, n, R, !std::isinf(dist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1084,9 +1084,6 @@ void SLAPrint::process()
|
||||||
using ClipperPolygons = std::vector<ClipperPolygon>;
|
using ClipperPolygons = std::vector<ClipperPolygon>;
|
||||||
namespace sl = libnest2d::shapelike; // For algorithms
|
namespace sl = libnest2d::shapelike; // For algorithms
|
||||||
|
|
||||||
// If the raster has vertical orientation, we will flip the coordinates
|
|
||||||
// bool flpXY = m_printer_config.display_orientation.getInt() == SLADisplayOrientation::sladoPortrait;
|
|
||||||
|
|
||||||
// Set up custom union and diff functions for clipper polygons
|
// Set up custom union and diff functions for clipper polygons
|
||||||
auto polyunion = [] (const ClipperPolygons& subjects)
|
auto polyunion = [] (const ClipperPolygons& subjects)
|
||||||
{
|
{
|
||||||
|
@ -1194,11 +1191,6 @@ void SLAPrint::process()
|
||||||
sl::translate(poly, ClipperPoint{instances[i].shift(X),
|
sl::translate(poly, ClipperPoint{instances[i].shift(X),
|
||||||
instances[i].shift(Y)});
|
instances[i].shift(Y)});
|
||||||
|
|
||||||
// if (flpXY) {
|
|
||||||
// for(auto& p : poly.Contour) std::swap(p.X, p.Y);
|
|
||||||
// for(auto& h : poly.Holes) for(auto& p : h) std::swap(p.X, p.Y);
|
|
||||||
// }
|
|
||||||
|
|
||||||
polygons.emplace_back(std::move(poly));
|
polygons.emplace_back(std::move(poly));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue