mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-10 16:27:54 -06:00
ENH: improve normal support's efficiency
Similar to tree support, make as many steps parallel as possible. Jira: STUDIO-2525 Change-Id: Iee310bbf6911d8d3e4262ee8ed6bd133d09670a9 (cherry picked from commit 3798f1a3ecb85bbfb81925b3702fb4384e18994d)
This commit is contained in:
parent
ef1e4a132d
commit
1ac8013fa5
4 changed files with 179 additions and 133 deletions
|
@ -207,7 +207,18 @@ bool Polygon::intersections(const Line &line, Points *intersections) const
|
||||||
}
|
}
|
||||||
return intersections->size() > intersections_size;
|
return intersections->size() > intersections_size;
|
||||||
}
|
}
|
||||||
|
bool Polygon::overlaps(const Polygons& other) const
|
||||||
|
{
|
||||||
|
if (this->empty() || other.empty())
|
||||||
|
return false;
|
||||||
|
Polylines pl_out = intersection_pl(to_polylines(other), *this);
|
||||||
|
|
||||||
|
// See unit test SCENARIO("Clipper diff with polyline", "[Clipper]")
|
||||||
|
// for in which case the intersection_pl produces any intersection.
|
||||||
|
return !pl_out.empty() ||
|
||||||
|
// If *this is completely inside other, then pl_out is empty, but the expolygons overlap. Test for that situation.
|
||||||
|
std::any_of(other.begin(), other.end(), [this](auto& poly) {return poly.contains(this->points.front()); });
|
||||||
|
}
|
||||||
// Filter points from poly to the output with the help of FilterFn.
|
// Filter points from poly to the output with the help of FilterFn.
|
||||||
// filter function receives two vectors:
|
// filter function receives two vectors:
|
||||||
// v1: this_point - previous_point
|
// v1: this_point - previous_point
|
||||||
|
@ -624,6 +635,15 @@ bool polygons_match(const Polygon &l, const Polygon &r)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool overlaps(const Polygons& polys1, const Polygons& polys2)
|
||||||
|
{
|
||||||
|
for (const Polygon& poly1 : polys1) {
|
||||||
|
if (poly1.overlaps(polys2))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool contains(const Polygon &polygon, const Point &p, bool border_result)
|
bool contains(const Polygon &polygon, const Point &p, bool border_result)
|
||||||
{
|
{
|
||||||
if (const int poly_count_inside = ClipperLib::PointInPolygon(p, polygon.points);
|
if (const int poly_count_inside = ClipperLib::PointInPolygon(p, polygon.points);
|
||||||
|
|
|
@ -75,7 +75,8 @@ public:
|
||||||
|
|
||||||
bool intersection(const Line& line, Point* intersection) const;
|
bool intersection(const Line& line, Point* intersection) const;
|
||||||
bool first_intersection(const Line& line, Point* intersection) const;
|
bool first_intersection(const Line& line, Point* intersection) const;
|
||||||
bool intersections(const Line &line, Points *intersections) const;
|
bool intersections(const Line& line, Points* intersections) const;
|
||||||
|
bool overlaps(const Polygons& other) const;
|
||||||
|
|
||||||
// Considering CCW orientation of this polygon, find all convex resp. concave points
|
// Considering CCW orientation of this polygon, find all convex resp. concave points
|
||||||
// with the angle at the vertex larger than a threshold.
|
// with the angle at the vertex larger than a threshold.
|
||||||
|
@ -265,6 +266,8 @@ inline Polygons to_polygons(std::vector<Points> &&paths)
|
||||||
// Do polygons match? If they match, they must have the same topology,
|
// Do polygons match? If they match, they must have the same topology,
|
||||||
// however their contours may be rotated.
|
// however their contours may be rotated.
|
||||||
bool polygons_match(const Polygon &l, const Polygon &r);
|
bool polygons_match(const Polygon &l, const Polygon &r);
|
||||||
|
|
||||||
|
bool overlaps(const Polygons& polys1, const Polygons& polys2);
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
|
||||||
// start Boost
|
// start Boost
|
||||||
|
|
|
@ -1486,14 +1486,13 @@ static const double sharp_tail_max_support_height = 16.f;
|
||||||
|
|
||||||
// Tuple: overhang_polygons, contact_polygons, enforcer_polygons, no_interface_offset
|
// Tuple: overhang_polygons, contact_polygons, enforcer_polygons, no_interface_offset
|
||||||
// no_interface_offset: minimum of external perimeter widths
|
// no_interface_offset: minimum of external perimeter widths
|
||||||
static inline Polygons detect_overhangs(
|
static inline ExPolygons detect_overhangs(
|
||||||
const Layer &layer,
|
const Layer &layer,
|
||||||
const size_t layer_id,
|
const size_t layer_id,
|
||||||
Polygons &lower_layer_polygons,
|
Polygons &lower_layer_polygons,
|
||||||
const PrintConfig &print_config,
|
const PrintConfig &print_config,
|
||||||
const PrintObjectConfig &object_config,
|
const PrintObjectConfig &object_config,
|
||||||
SupportAnnotations &annotations,
|
SupportAnnotations &annotations,
|
||||||
SlicesMarginCache &slices_margin,
|
|
||||||
const double gap_xy
|
const double gap_xy
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
, size_t iRun
|
, size_t iRun
|
||||||
|
@ -1546,9 +1545,6 @@ static inline Polygons detect_overhangs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ExPolygons& lower_layer_sharptails = lower_layer.sharp_tails;
|
|
||||||
auto& lower_layer_sharptails_height = lower_layer.sharp_tails_height;
|
|
||||||
|
|
||||||
float lower_layer_offset = 0;
|
float lower_layer_offset = 0;
|
||||||
for (LayerRegion *layerm : layer.regions()) {
|
for (LayerRegion *layerm : layer.regions()) {
|
||||||
// Extrusion width accounts for the roundings of the extrudates.
|
// Extrusion width accounts for the roundings of the extrudates.
|
||||||
|
@ -1598,73 +1594,13 @@ static inline Polygons detect_overhangs(
|
||||||
for (ExPolygon& expoly : layerm->raw_slices) {
|
for (ExPolygon& expoly : layerm->raw_slices) {
|
||||||
bool is_sharp_tail = false;
|
bool is_sharp_tail = false;
|
||||||
float accum_height = layer.height;
|
float accum_height = layer.height;
|
||||||
do {
|
|
||||||
if (!g_config_support_sharp_tails) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. nothing below
|
// 1. nothing below
|
||||||
// Check whether this is a sharp tail region.
|
// Check whether this is a sharp tail region.
|
||||||
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
|
// Should use lower_layer_expolys without any offset. Otherwise, it may missing sharp tails near the main body.
|
||||||
if (intersection_ex({ expoly }, lower_layer_expolys).empty()) {
|
if (g_config_support_sharp_tails && overlaps({ expoly }, lower_layer_expolys)) {
|
||||||
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.5*fw).empty();
|
is_sharp_tail = expoly.area() < area_thresh_well_supported && !offset_ex(expoly,-0.5*fw).empty();
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 2. something below
|
|
||||||
// check whether this is above a sharp tail region.
|
|
||||||
|
|
||||||
// 2.1 If no sharp tail below, this is considered as common region.
|
|
||||||
ExPolygons supported_by_lower = intersection_ex({ expoly }, lower_layer_sharptails);
|
|
||||||
if (supported_by_lower.empty()) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.2 If sharp tail below, check whether it support this region enough.
|
|
||||||
float supported_area = 0.f;
|
|
||||||
BoundingBox bbox;
|
|
||||||
for (ExPolygon& temp : supported_by_lower) {
|
|
||||||
supported_area += temp.area();
|
|
||||||
bbox.merge(get_extents(temp));
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
if (supported_area > area_thresh_well_supported) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (bbox.size().x() > length_thresh_well_supported && bbox.size().y() > length_thresh_well_supported) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.3 check whether sharp tail exceed the max height
|
|
||||||
for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
|
||||||
if (!intersection_ex(*lower_sharp_tail_height.first, expoly).empty()) {
|
|
||||||
accum_height += lower_sharp_tail_height.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accum_height >= sharp_tail_max_support_height) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.4 if the area grows fast than threshold, it get connected to other part or
|
|
||||||
// it has a sharp slop and will be auto supported.
|
|
||||||
ExPolygons new_overhang_expolys = diff_ex({ expoly }, lower_layer_sharptails);
|
|
||||||
Point size_diff = get_extents(new_overhang_expolys).size() - get_extents(lower_layer_sharptails).size();
|
|
||||||
if (size_diff.both_comp(Point(scale_(5),scale_(5)),">") || !offset_ex(new_overhang_expolys, -5.0 * fw).empty()) {
|
|
||||||
is_sharp_tail = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.5 mark the expoly as sharptail
|
|
||||||
is_sharp_tail = true;
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
if (is_sharp_tail) {
|
if (is_sharp_tail) {
|
||||||
ExPolygons overhang = diff_ex({ expoly }, lower_layer_polygons);
|
ExPolygons overhang = diff_ex({ expoly }, lower_layer_polygons);
|
||||||
|
@ -1702,8 +1638,7 @@ static inline Polygons detect_overhangs(
|
||||||
} // for each layer.region
|
} // for each layer.region
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBS: hotfix to make sure ccw polygon is before cw polygon
|
return union_ex(overhang_polygons);
|
||||||
return to_polygons(union_ex(overhang_polygons));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tuple: overhang_polygons, contact_polygons, enforcer_polygons, no_interface_offset
|
// Tuple: overhang_polygons, contact_polygons, enforcer_polygons, no_interface_offset
|
||||||
|
@ -2127,27 +2062,27 @@ static void merge_contact_layers(const SlicingParameters &slicing_params, double
|
||||||
|
|
||||||
|
|
||||||
struct OverhangCluster {
|
struct OverhangCluster {
|
||||||
std::map<int, std::vector<Polygon*>> layer_overhangs;
|
std::map<int, std::vector<ExPolygon*>> layer_overhangs;
|
||||||
Polygons merged_overhangs_dilated;
|
ExPolygons merged_overhangs_dilated;
|
||||||
int min_layer = 1e7;
|
int min_layer = 1e7;
|
||||||
int max_layer = 0;
|
int max_layer = 0;
|
||||||
coordf_t offset_scaled = 0;
|
coordf_t offset_scaled = 0;
|
||||||
|
|
||||||
OverhangCluster(Polygon* overhang, int layer_nr, coordf_t offset_scaled) {
|
OverhangCluster(ExPolygon* overhang, int layer_nr, coordf_t offset_scaled) {
|
||||||
this->offset_scaled = offset_scaled;
|
this->offset_scaled = offset_scaled;
|
||||||
insert(overhang, layer_nr);
|
insert(overhang, layer_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(Polygon* overhang_new, int layer_nr) {
|
void insert(ExPolygon* overhang_new, int layer_nr) {
|
||||||
if (layer_overhangs.find(layer_nr) != layer_overhangs.end()) {
|
if (layer_overhangs.find(layer_nr) != layer_overhangs.end()) {
|
||||||
layer_overhangs[layer_nr].push_back(overhang_new);
|
layer_overhangs[layer_nr].push_back(overhang_new);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
layer_overhangs.emplace(layer_nr, std::vector<Polygon*>{ overhang_new });
|
layer_overhangs.emplace(layer_nr, std::vector<ExPolygon*>{ overhang_new });
|
||||||
}
|
}
|
||||||
Polygons overhang_dilated = offset_scaled > EPSILON ? expand(*overhang_new, offset_scaled) : Polygons{ *overhang_new };
|
ExPolygons overhang_dilated = offset_scaled > EPSILON ? offset_ex(*overhang_new, offset_scaled) : ExPolygons{ *overhang_new };
|
||||||
if (!overhang_dilated.empty())
|
if (!overhang_dilated.empty())
|
||||||
merged_overhangs_dilated = union_(merged_overhangs_dilated, overhang_dilated);
|
merged_overhangs_dilated = union_ex(merged_overhangs_dilated, overhang_dilated);
|
||||||
min_layer = std::min(min_layer, layer_nr);
|
min_layer = std::min(min_layer, layer_nr);
|
||||||
max_layer = std::max(max_layer, layer_nr);
|
max_layer = std::max(max_layer, layer_nr);
|
||||||
}
|
}
|
||||||
|
@ -2156,24 +2091,25 @@ struct OverhangCluster {
|
||||||
return max_layer - min_layer + 1;
|
return max_layer - min_layer + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects(const Polygon& overhang_new, int layer_nr) {
|
bool intersects(const ExPolygon& overhang_new, int layer_nr) {
|
||||||
if (layer_nr < 1)
|
if (layer_nr < 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto it = layer_overhangs.find(layer_nr - 1);
|
//auto it = layer_overhangs.find(layer_nr - 1);
|
||||||
if (it == layer_overhangs.end())
|
//if (it == layer_overhangs.end())
|
||||||
|
// return false;
|
||||||
|
//ExPolygons overhangs_lower;
|
||||||
|
//for (ExPolygon* poly : it->second) {
|
||||||
|
// overhangs_lower.push_back(*poly);
|
||||||
|
//}
|
||||||
|
if (layer_nr<min_layer - 1 || layer_nr>max_layer + 1)
|
||||||
return false;
|
return false;
|
||||||
|
const ExPolygons overhang_dilated = offset_ex(overhang_new, offset_scaled);
|
||||||
Polygons overhangs_lower;
|
return overlaps(overhang_dilated, merged_overhangs_dilated);
|
||||||
for (Polygon* poly : it->second) {
|
|
||||||
overhangs_lower.push_back(*poly);
|
|
||||||
}
|
|
||||||
const Polygons overhang_dilated = expand(overhang_new, offset_scaled);
|
|
||||||
return !intersection(overhang_dilated, overhangs_lower).empty();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void add_overhang(std::vector<OverhangCluster>& clusters, Polygon* overhang, int layer_nr, coordf_t offset_scaled) {
|
static void add_overhang(std::vector<OverhangCluster>& clusters, ExPolygon* overhang, int layer_nr, coordf_t offset_scaled) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < clusters.size(); i++) {
|
for (int i = 0; i < clusters.size(); i++) {
|
||||||
auto& cluster = clusters[i];
|
auto& cluster = clusters[i];
|
||||||
|
@ -2224,37 +2160,137 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
contact_out.assign(num_layers * 2, nullptr);
|
contact_out.assign(num_layers * 2, nullptr);
|
||||||
tbb::spin_mutex layer_storage_mutex;
|
tbb::spin_mutex layer_storage_mutex;
|
||||||
|
|
||||||
std::vector<Polygons> overhangs_per_layers(num_layers);
|
std::vector<ExPolygons> overhangs_per_layers(num_layers);
|
||||||
for (size_t layer_id = this->has_raft() ? 0 : 1; layer_id < num_layers; layer_id++) {
|
size_t layer_id_start = this->has_raft() ? 0 : 1;
|
||||||
const Layer& layer = *object.layers()[layer_id];
|
// main part of overhang detection can be parallel
|
||||||
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->lslices);
|
tbb::parallel_for(tbb::blocked_range<size_t>(layer_id_start, num_layers),
|
||||||
SlicesMarginCache slices_margin;
|
[&](const tbb::blocked_range<size_t>& range) {
|
||||||
|
for (size_t layer_id = range.begin(); layer_id < range.end(); layer_id++) {
|
||||||
|
const Layer& layer = *object.layers()[layer_id];
|
||||||
|
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->lslices);
|
||||||
|
|
||||||
Polygons overhang_polygons = detect_overhangs(layer, layer_id, lower_layer_polygons, *m_print_config, *m_object_config, annotations, slices_margin, m_support_params.gap_xy
|
overhangs_per_layers[layer_id] = detect_overhangs(layer, layer_id, lower_layer_polygons, *m_print_config, *m_object_config, annotations, m_support_params.gap_xy
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
, iRun
|
, iRun
|
||||||
#endif // SLIC3R_DEBUG
|
#endif // SLIC3R_DEBUG
|
||||||
);
|
);
|
||||||
|
|
||||||
overhangs_per_layers[layer_id] = std::move(overhang_polygons);
|
if (object.print()->canceled())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
); // end tbb::parallel_for
|
||||||
|
|
||||||
if (object.print()->canceled())
|
if (object.print()->canceled())
|
||||||
return MyLayersPtr();
|
return MyLayersPtr();
|
||||||
|
|
||||||
|
// check if the sharp tails should be extended higher
|
||||||
|
bool detect_first_sharp_tail_only = false;
|
||||||
|
const coordf_t extrusion_width = m_object_config->line_width.value;
|
||||||
|
const coordf_t extrusion_width_scaled = scale_(extrusion_width);
|
||||||
|
if (is_auto(m_object_config->support_type.value) && g_config_support_sharp_tails && !detect_first_sharp_tail_only) {
|
||||||
|
for (size_t layer_nr = 0; layer_nr < object.layer_count(); layer_nr++) {
|
||||||
|
if (object.print()->canceled())
|
||||||
|
break;
|
||||||
|
|
||||||
|
const Layer* layer = object.get_layer(layer_nr);
|
||||||
|
const Layer* lower_layer = layer->lower_layer;
|
||||||
|
// skip if:
|
||||||
|
// 1) if the current layer is already detected as sharp tails
|
||||||
|
// 2) lower layer has no sharp tails
|
||||||
|
if (!lower_layer || layer->sharp_tails.empty() == false || lower_layer->sharp_tails.empty() == true)
|
||||||
|
continue;
|
||||||
|
ExPolygons lower_polys;
|
||||||
|
for (const ExPolygon& expoly : lower_layer->lslices) {
|
||||||
|
if (!offset_ex(expoly, -extrusion_width_scaled / 2).empty()) {
|
||||||
|
lower_polys.emplace_back(expoly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BBS detect sharp tail
|
||||||
|
const ExPolygons& lower_layer_sharptails = lower_layer->sharp_tails;
|
||||||
|
auto& lower_layer_sharptails_height = lower_layer->sharp_tails_height;
|
||||||
|
for (const ExPolygon& expoly : layer->lslices) {
|
||||||
|
bool is_sharp_tail = false;
|
||||||
|
float accum_height = layer->height;
|
||||||
|
do {
|
||||||
|
// 2. something below
|
||||||
|
// check whether this is above a sharp tail region.
|
||||||
|
|
||||||
|
// 2.1 If no sharp tail below, this is considered as common region.
|
||||||
|
ExPolygons supported_by_lower = intersection_ex({ expoly }, lower_layer_sharptails);
|
||||||
|
if (supported_by_lower.empty()) {
|
||||||
|
is_sharp_tail = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.2 If sharp tail below, check whether it support this region enough.
|
||||||
|
#if 0
|
||||||
|
// judge by area isn't reliable, failure cases include 45 degree rotated cube
|
||||||
|
float supported_area = area(supported_by_lower);
|
||||||
|
if (supported_area > area_thresh_well_supported) {
|
||||||
|
is_sharp_tail = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
BoundingBox bbox = get_extents(supported_by_lower);
|
||||||
|
if (bbox.size().x() > length_thresh_well_supported && bbox.size().y() > length_thresh_well_supported) {
|
||||||
|
is_sharp_tail = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.3 check whether sharp tail exceed the max height
|
||||||
|
for (auto& lower_sharp_tail_height : lower_layer_sharptails_height) {
|
||||||
|
if (lower_sharp_tail_height.first->overlaps(expoly)) {
|
||||||
|
accum_height += lower_sharp_tail_height.second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (accum_height >= sharp_tail_max_support_height) {
|
||||||
|
is_sharp_tail = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.4 if the area grows fast than threshold, it get connected to other part or
|
||||||
|
// it has a sharp slop and will be auto supported.
|
||||||
|
ExPolygons new_overhang_expolys = diff_ex({ expoly }, lower_layer_sharptails);
|
||||||
|
Point size_diff = get_extents(new_overhang_expolys).size() - get_extents(lower_layer_sharptails).size();
|
||||||
|
if (size_diff.both_comp(Point(scale_(5), scale_(5)), ">") || !offset_ex(new_overhang_expolys, -5.0 * extrusion_width_scaled).empty()) {
|
||||||
|
is_sharp_tail = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.5 mark the expoly as sharptail
|
||||||
|
is_sharp_tail = true;
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (is_sharp_tail) {
|
||||||
|
ExPolygons overhang = diff_ex({ expoly }, lower_layer->lslices);
|
||||||
|
layer->sharp_tails.push_back(expoly);
|
||||||
|
layer->sharp_tails_height.insert({ &expoly, accum_height });
|
||||||
|
append(overhangs_per_layers[layer_nr], overhang);
|
||||||
|
#ifdef SUPPORT_TREE_DEBUG_TO_SVG
|
||||||
|
SVG svg(get_svg_filename(std::to_string(layer->print_z), "sharp_tail"), object.bounding_box());
|
||||||
|
if (svg.is_opened()) svg.draw(overhang, "yellow");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.print()->canceled())
|
if (object.print()->canceled())
|
||||||
return MyLayersPtr();
|
return MyLayersPtr();
|
||||||
|
|
||||||
// BBS
|
// BBS group overhang clusters
|
||||||
if (g_config_remove_small_overhangs) {
|
if (g_config_remove_small_overhangs) {
|
||||||
std::vector<OverhangCluster> clusters;
|
std::vector<OverhangCluster> clusters;
|
||||||
double fw_scaled = scale_(m_object_config->line_width);
|
double fw_scaled = scale_(m_object_config->line_width);
|
||||||
std::set<Polygon*> removed_overhang;
|
std::set<ExPolygon*> removed_overhang;
|
||||||
|
|
||||||
for (size_t layer_id = this->has_raft() ? 0 : 1; layer_id < num_layers; layer_id++) {
|
for (size_t layer_id = layer_id_start; layer_id < num_layers; layer_id++) {
|
||||||
for (Polygon& overhang : overhangs_per_layers[layer_id]) {
|
for (auto& overhang : overhangs_per_layers[layer_id]) {
|
||||||
if (overhang.is_counter_clockwise())
|
add_overhang(clusters, &overhang, layer_id, fw_scaled);
|
||||||
add_overhang(clusters, &overhang, layer_id, fw_scaled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2276,8 +2312,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
// 3. check whether the small overhang is sharp tail
|
// 3. check whether the small overhang is sharp tail
|
||||||
bool is_sharp_tail = false;
|
bool is_sharp_tail = false;
|
||||||
for (size_t layer_id = cluster.min_layer; layer_id <= cluster.max_layer; layer_id++) {
|
for (size_t layer_id = cluster.min_layer; layer_id <= cluster.max_layer; layer_id++) {
|
||||||
const Layer& layer = *object.layers()[layer_id];
|
const Layer* layer = object.get_layer(layer_id);
|
||||||
if (!intersection_ex(layer.sharp_tails, cluster.merged_overhangs_dilated).empty()) {
|
if (overlaps(layer->sharp_tails, cluster.merged_overhangs_dilated)) {
|
||||||
is_sharp_tail = true;
|
is_sharp_tail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2293,7 +2329,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
double dist_max = 0;
|
double dist_max = 0;
|
||||||
Points cluster_pts;
|
Points cluster_pts;
|
||||||
for (auto& poly : cluster.merged_overhangs_dilated)
|
for (auto& poly : cluster.merged_overhangs_dilated)
|
||||||
append(cluster_pts, poly.points);
|
append(cluster_pts, poly.contour.points);
|
||||||
for (auto& pt : cluster_pts) {
|
for (auto& pt : cluster_pts) {
|
||||||
double dist_pt = std::numeric_limits<double>::max();
|
double dist_pt = std::numeric_limits<double>::max();
|
||||||
for (auto& poly : cluster_boundary) {
|
for (auto& poly : cluster_boundary) {
|
||||||
|
@ -2307,30 +2343,20 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
|
|
||||||
// 5. remove small overhangs
|
// 5. remove small overhangs
|
||||||
for (auto overhangs : cluster.layer_overhangs) {
|
for (auto overhangs : cluster.layer_overhangs) {
|
||||||
for (Polygon* poly : overhangs.second)
|
for (auto* poly : overhangs.second)
|
||||||
removed_overhang.insert(poly);
|
removed_overhang.insert(poly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t layer_id = this->has_raft() ? 0 : 1; layer_id < num_layers; layer_id++) {
|
for (size_t layer_id = layer_id_start; layer_id < num_layers; layer_id++) {
|
||||||
Polygons& layer_overhangs = overhangs_per_layers[layer_id];
|
auto& layer_overhangs = overhangs_per_layers[layer_id];
|
||||||
if (layer_overhangs.empty())
|
if (layer_overhangs.empty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bool remove_hole = false;
|
|
||||||
for (int poly_idx = 0; poly_idx < layer_overhangs.size(); poly_idx++) {
|
for (int poly_idx = 0; poly_idx < layer_overhangs.size(); poly_idx++) {
|
||||||
Polygon* overhang = &layer_overhangs[poly_idx];
|
auto* overhang = &layer_overhangs[poly_idx];
|
||||||
if (overhang->is_counter_clockwise()) {
|
if (removed_overhang.find(overhang) != removed_overhang.end()) {
|
||||||
if (removed_overhang.find(overhang) != removed_overhang.end()) {
|
overhang->clear();
|
||||||
remove_hole = true;
|
|
||||||
overhang->clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
remove_hole = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (remove_hole)
|
|
||||||
overhang->clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2339,9 +2365,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
if (object.print()->canceled())
|
if (object.print()->canceled())
|
||||||
return MyLayersPtr();
|
return MyLayersPtr();
|
||||||
|
|
||||||
for (size_t layer_id = this->has_raft() ? 0 : 1; layer_id < num_layers; layer_id++) {
|
for (size_t layer_id = layer_id_start; layer_id < num_layers; layer_id++) {
|
||||||
const Layer& layer = *object.layers()[layer_id];
|
const Layer& layer = *object.layers()[layer_id];
|
||||||
Polygons overhang_polygons = overhangs_per_layers[layer_id];
|
Polygons overhang_polygons = to_polygons(overhangs_per_layers[layer_id]);
|
||||||
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->lslices);
|
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->lslices);
|
||||||
SlicesMarginCache slices_margin;
|
SlicesMarginCache slices_margin;
|
||||||
|
|
||||||
|
|
|
@ -925,9 +925,6 @@ void TreeSupport::detect_overhangs(bool detect_first_sharp_tail_only)
|
||||||
if (!offset_ex(poly, -0.1 * extrusion_width_scaled).empty())
|
if (!offset_ex(poly, -0.1 * extrusion_width_scaled).empty())
|
||||||
ts_layer->overhang_areas.emplace_back(poly);
|
ts_layer->overhang_areas.emplace_back(poly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
); // end tbb::parallel_for
|
); // end tbb::parallel_for
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue