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:
bubnikv 2019-02-20 10:46:49 +01:00
parent 023b788777
commit 5499bbd1da
2 changed files with 54 additions and 34 deletions

View file

@ -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)

View file

@ -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.