mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-22 14:13:57 -06:00
SLA auto supports: Improved distribution of the support forces
in the up direction by taking into account island overlap areas.
This commit is contained in:
parent
023b788777
commit
5499bbd1da
2 changed files with 54 additions and 34 deletions
|
@ -146,11 +146,13 @@ static std::vector<SLAAutoSupports::MyLayer> make_layers(
|
||||||
const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle)));
|
const float between_layers_offset = float(scale_(layer_height / std::tan(safe_angle)));
|
||||||
//FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands.
|
//FIXME This has a quadratic time complexity, it will be excessively slow for many tiny islands.
|
||||||
for (SLAAutoSupports::Structure &top : layer_above.islands) {
|
for (SLAAutoSupports::Structure &top : layer_above.islands) {
|
||||||
for (SLAAutoSupports::Structure &bottom : layer_below.islands)
|
for (SLAAutoSupports::Structure &bottom : layer_below.islands) {
|
||||||
if (top.overlaps(bottom)) {
|
float overlap_area = top.overlap_area(bottom);
|
||||||
top.islands_below.emplace_back(&bottom);
|
if (overlap_area > 0) {
|
||||||
bottom.islands_above.emplace_back(&top);
|
top.islands_below.emplace_back(&bottom, overlap_area);
|
||||||
|
bottom.islands_above.emplace_back(&top, overlap_area);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (! top.islands_below.empty()) {
|
if (! top.islands_below.empty()) {
|
||||||
Polygons top_polygons = to_polygons(*top.polygon);
|
Polygons top_polygons = to_polygons(*top.polygon);
|
||||||
Polygons bottom_polygons = top.polygons_below();
|
Polygons bottom_polygons = top.polygons_below();
|
||||||
|
@ -202,26 +204,27 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
||||||
support_force_bottom[i] = layer_bottom->islands[i].supports_force_total();
|
support_force_bottom[i] = layer_bottom->islands[i].supports_force_total();
|
||||||
}
|
}
|
||||||
for (Structure &top : layer_top->islands)
|
for (Structure &top : layer_top->islands)
|
||||||
for (Structure *bottom : top.islands_below) {
|
for (Structure::Link &bottom_link : top.islands_below) {
|
||||||
float centroids_dist = (bottom->centroid - top.centroid).norm();
|
Structure &bottom = *bottom_link.island;
|
||||||
|
float centroids_dist = (bottom.centroid - top.centroid).norm();
|
||||||
// Penalization resulting from centroid offset:
|
// Penalization resulting from centroid offset:
|
||||||
// bottom.supports_force *= std::min(1.f, 1.f - std::min(1.f, (1600.f * layer_height) * centroids_dist * centroids_dist / bottom.area));
|
// bottom.supports_force *= std::min(1.f, 1.f - std::min(1.f, (1600.f * layer_height) * centroids_dist * centroids_dist / bottom.area));
|
||||||
float &support_force = support_force_bottom[bottom - layer_bottom->islands.data()];
|
float &support_force = support_force_bottom[&bottom - layer_bottom->islands.data()];
|
||||||
//FIXME this condition does not reflect a bifurcation into a one large island and one tiny island well, it incorrectly resets the support force to zero.
|
//FIXME this condition does not reflect a bifurcation into a one large island and one tiny island well, it incorrectly resets the support force to zero.
|
||||||
// One should rather work with the overlap area vs overhang area.
|
// One should rather work with the overlap area vs overhang area.
|
||||||
// support_force *= std::min(1.f, 1.f - std::min(1.f, 0.1f * centroids_dist * centroids_dist / bottom->area));
|
// support_force *= std::min(1.f, 1.f - std::min(1.f, 0.1f * centroids_dist * centroids_dist / bottom.area));
|
||||||
// Penalization resulting from increasing polygon area:
|
// Penalization resulting from increasing polygon area:
|
||||||
support_force *= std::min(1.f, 20.f * bottom->area / top.area);
|
support_force *= std::min(1.f, 20.f * bottom.area / top.area);
|
||||||
}
|
}
|
||||||
// Let's assign proper support force to each of them:
|
// Let's assign proper support force to each of them:
|
||||||
if (layer_id > 0) {
|
if (layer_id > 0) {
|
||||||
for (Structure &below : layer_bottom->islands) {
|
for (Structure &below : layer_bottom->islands) {
|
||||||
float below_support_force = support_force_bottom[&below - layer_bottom->islands.data()];
|
float below_support_force = support_force_bottom[&below - layer_bottom->islands.data()];
|
||||||
float above_area = 0.f;
|
float above_overlap_area = 0.f;
|
||||||
for (Structure *above : below.islands_above)
|
for (Structure::Link &above_link : below.islands_above)
|
||||||
above_area += above->area;
|
above_overlap_area += above_link.overlap_area;
|
||||||
for (Structure *above : below.islands_above)
|
for (Structure::Link &above_link : below.islands_above)
|
||||||
above->supports_force_inherited += below_support_force * above->area / above_area;
|
above_link.island->supports_force_inherited += below_support_force * above_link.overlap_area / above_overlap_area;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Now iterate over all polygons and append new points if needed.
|
// Now iterate over all polygons and append new points if needed.
|
||||||
|
@ -231,9 +234,9 @@ void SLAAutoSupports::process(const std::vector<ExPolygons>& slices, const std::
|
||||||
s.supports_force_inherited /= std::max(1.f, 0.17f * (s.overhangs_area) / s.area);
|
s.supports_force_inherited /= std::max(1.f, 0.17f * (s.overhangs_area) / s.area);
|
||||||
|
|
||||||
float force_deficit = s.support_force_deficit(m_config.tear_pressure);
|
float force_deficit = s.support_force_deficit(m_config.tear_pressure);
|
||||||
if (s.islands_below.empty()) // completely new island - needs support no doubt
|
if (s.islands_below.empty()) { // completely new island - needs support no doubt
|
||||||
uniformly_cover({ *s.polygon }, s, point_grid, true);
|
uniformly_cover({ *s.polygon }, s, point_grid, true);
|
||||||
else if (! s.dangling_areas.empty()) {
|
} else if (! s.dangling_areas.empty()) {
|
||||||
// Let's see if there's anything that overlaps enough to need supports:
|
// Let's see if there's anything that overlaps enough to need supports:
|
||||||
// What we now have in polygons needs support, regardless of what the forces are, so we can add them.
|
// What we now have in polygons needs support, regardless of what the forces are, so we can add them.
|
||||||
//FIXME is it an island point or not? Vojtech thinks it is.
|
//FIXME is it an island point or not? Vojtech thinks it is.
|
||||||
|
@ -474,7 +477,7 @@ void SLAAutoSupports::uniformly_cover(const ExPolygons& islands, Structure& stru
|
||||||
#ifdef SLA_AUTOSUPPORTS_DEBUG
|
#ifdef SLA_AUTOSUPPORTS_DEBUG
|
||||||
{
|
{
|
||||||
static int irun = 0;
|
static int irun = 0;
|
||||||
Slic3r::SVG svg(debug_out_path("SLA_supports-uniformly_cover-%d.svg", irun ++), get_extents(island));
|
Slic3r::SVG svg(debug_out_path("SLA_supports-uniformly_cover-%d.svg", irun ++), get_extents(islands));
|
||||||
for (const ExPolygon &island : islands)
|
for (const ExPolygon &island : islands)
|
||||||
svg.draw(island);
|
svg.draw(island);
|
||||||
for (const Vec2f &pt : raw_samples)
|
for (const Vec2f &pt : raw_samples)
|
||||||
|
|
|
@ -51,43 +51,60 @@ public:
|
||||||
std::chrono::milliseconds unique_id;
|
std::chrono::milliseconds unique_id;
|
||||||
#endif /* SLA_AUTOSUPPORTS_DEBUG */
|
#endif /* SLA_AUTOSUPPORTS_DEBUG */
|
||||||
|
|
||||||
|
struct Link {
|
||||||
|
Link(Structure *island, float overlap_area) : island(island), overlap_area(overlap_area) {}
|
||||||
|
Structure *island;
|
||||||
|
float overlap_area;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
// In release mode, use the optimized container.
|
// In release mode, use the optimized container.
|
||||||
boost::container::small_vector<Structure*, 4> islands_above;
|
boost::container::small_vector<Link, 4> islands_above;
|
||||||
boost::container::small_vector<Structure*, 4> islands_below;
|
boost::container::small_vector<Link, 4> islands_below;
|
||||||
#else
|
#else
|
||||||
// In debug mode, use the standard vector, which is well handled by debugger visualizer.
|
// In debug mode, use the standard vector, which is well handled by debugger visualizer.
|
||||||
std::vector<Structure*> islands_above;
|
std::vector<Link> islands_above;
|
||||||
std::vector<Structure*> islands_below;
|
std::vector<Link> islands_below;
|
||||||
#endif
|
#endif
|
||||||
ExPolygons dangling_areas;
|
ExPolygons dangling_areas;
|
||||||
ExPolygons overhangs;
|
ExPolygons overhangs;
|
||||||
float overhangs_area;
|
float overhangs_area;
|
||||||
|
|
||||||
bool overlaps(const Structure &rhs) const { return this->bbox.overlap(rhs.bbox) && (this->polygon->overlaps(*rhs.polygon) || rhs.polygon->overlaps(*this->polygon)); }
|
bool overlaps(const Structure &rhs) const {
|
||||||
|
return this->bbox.overlap(rhs.bbox) && (this->polygon->overlaps(*rhs.polygon) || rhs.polygon->overlaps(*this->polygon));
|
||||||
|
}
|
||||||
|
float overlap_area(const Structure &rhs) const {
|
||||||
|
double out = 0.;
|
||||||
|
if (this->bbox.overlap(rhs.bbox)) {
|
||||||
|
Polygons polys = intersection(to_polygons(*this->polygon), to_polygons(*rhs.polygon), false);
|
||||||
|
for (const Polygon &poly : polys)
|
||||||
|
out += poly.area();
|
||||||
|
}
|
||||||
|
return float(out);
|
||||||
|
}
|
||||||
float area_below() const {
|
float area_below() const {
|
||||||
float area = 0.f;
|
float area = 0.f;
|
||||||
for (const Structure *below : this->islands_below)
|
for (const Link &below : this->islands_below)
|
||||||
area += below->area;
|
area += below.island->area;
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
Polygons polygons_below() const {
|
Polygons polygons_below() const {
|
||||||
size_t cnt = 0;
|
size_t cnt = 0;
|
||||||
for (const Structure *below : this->islands_below)
|
for (const Link &below : this->islands_below)
|
||||||
cnt += 1 + below->polygon->holes.size();
|
cnt += 1 + below.island->polygon->holes.size();
|
||||||
Polygons out;
|
Polygons out;
|
||||||
out.reserve(cnt);
|
out.reserve(cnt);
|
||||||
for (const Structure *below : this->islands_below) {
|
for (const Link &below : this->islands_below) {
|
||||||
out.emplace_back(below->polygon->contour);
|
out.emplace_back(below.island->polygon->contour);
|
||||||
append(out, below->polygon->holes);
|
append(out, below.island->polygon->holes);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
ExPolygons expolygons_below() const {
|
ExPolygons expolygons_below() const {
|
||||||
ExPolygons out;
|
ExPolygons out;
|
||||||
out.reserve(this->islands_below.size());
|
out.reserve(this->islands_below.size());
|
||||||
for (const Structure *below : this->islands_below)
|
for (const Link &below : this->islands_below)
|
||||||
out.emplace_back(*below->polygon);
|
out.emplace_back(*below.island->polygon);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
// Positive deficit of the supports. If negative, this area is well supported. If positive, more supports need to be added.
|
// Positive deficit of the supports. If negative, this area is well supported. If positive, more supports need to be added.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue