ENH: speedup brim generation

Use support_islands for all types of suports to avoid gaps between
support regions of the first layer.

jira: STUDIO-8443
Change-Id: Ic65b47640d8352d406bb11eeff7390532631712b
This commit is contained in:
Arthur 2024-10-14 19:09:13 +08:00 committed by Lane.Wei
parent e85b2fbf6f
commit 20784d845f
6 changed files with 19 additions and 101 deletions

View File

@ -877,6 +877,7 @@ static ExPolygons outer_inner_brim_area(const Print& print,
} }
hole_index = -1; hole_index = -1;
}; };
const float scaled_flow_width = print.brim_flow().scaled_spacing();
for (unsigned int extruderNo : printExtruders) { for (unsigned int extruderNo : printExtruders) {
++extruderNo; ++extruderNo;
for (const auto& objectWithExtruder : objPrintVec) { for (const auto& objectWithExtruder : objPrintVec) {
@ -885,7 +886,6 @@ static ExPolygons outer_inner_brim_area(const Print& print,
float brim_offset = scale_(object->config().brim_object_gap.value); float brim_offset = scale_(object->config().brim_object_gap.value);
double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR; double flowWidth = print.brim_flow().scaled_spacing() * SCALING_FACTOR;
float brim_width = scale_(floor(object->config().brim_width.value / flowWidth / 2) * flowWidth * 2); float brim_width = scale_(floor(object->config().brim_width.value / flowWidth / 2) * flowWidth * 2);
const float scaled_flow_width = print.brim_flow().scaled_spacing();
const float scaled_additional_brim_width = scale_(floor(5 / flowWidth / 2) * flowWidth * 2); const float scaled_additional_brim_width = scale_(floor(5 / flowWidth / 2) * flowWidth * 2);
const float scaled_half_min_adh_length = scale_(1.1); const float scaled_half_min_adh_length = scale_(1.1);
bool has_brim_auto = object->config().brim_type == btAutoBrim; bool has_brim_auto = object->config().brim_type == btAutoBrim;
@ -1031,18 +1031,12 @@ static ExPolygons outer_inner_brim_area(const Print& print,
} }
if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) { if (support_material_extruder == extruderNo && brimToWrite.at(object->id()).sup) {
if (!object->support_layers().empty() && object->support_layers().front()->support_type == stInnerNormal) { if (!object->support_layers().empty()) {
for (const Polygon& support_contour : object->support_layers().front()->support_fills.polygons_covered_by_spacing()) { for (const auto &support_contour : object->support_layers().front()->support_islands) {
no_brim_area_support.emplace_back(support_contour); no_brim_area_support.emplace_back(support_contour);
} }
} }
if (!object->support_layers().empty() && object->support_layers().front()->support_type == stInnerTree) {
for (const ExPolygon& ex_poly : object->support_layers().front()->lslices) {
no_brim_area_support.emplace_back(ex_poly.contour);
}
}
brimToWrite.at(object->id()).sup = false; brimToWrite.at(object->id()).sup = false;
for (const PrintInstance& instance : object->instances()) { for (const PrintInstance& instance : object->instances()) {
if (!brim_area_support.empty()) if (!brim_area_support.empty())
@ -1058,6 +1052,7 @@ static ExPolygons outer_inner_brim_area(const Print& print,
if (!bedExPoly.empty()){ if (!bedExPoly.empty()){
no_brim_area.push_back(bedExPoly.front()); no_brim_area.push_back(bedExPoly.front());
} }
no_brim_area = offset2_ex(no_brim_area, scaled_flow_width, -scaled_flow_width); // connect scattered small areas to prevent generating very small brims
for (const PrintObject* object : print.objects()) { for (const PrintObject* object : print.objects()) {
if (brimAreaMap.find(object->id()) != brimAreaMap.end()) if (brimAreaMap.find(object->id()) != brimAreaMap.end())
{ {
@ -1080,22 +1075,14 @@ static ExPolygons outer_inner_brim_area(const Print& print,
} }
} }
auto tempArea = brimAreaMap[object->id()]; auto& tempAreas = brimAreaMap[object->id()];
brimAreaMap[object->id()].clear(); brim_area.reserve(brim_area.size() + tempAreas.size());
for (auto& tempArea:tempAreas) {
for (int ia = 0; ia != tempArea.size(); ++ia) { auto offsetedTa = offset_ex(tempArea, print.brim_flow().scaled_spacing() * 2, jtRound, SCALED_RESOLUTION);
// find this object's other brim area if (!overlaps(offsetedTa, objectIslands) ||
ExPolygons otherExPoly; !overlaps(offsetedTa, otherExPolys))
for (int iao = 0; iao != tempArea.size(); ++iao) brim_area.push_back(tempArea);
if (iao != ia) otherExPoly.push_back(tempArea[iao]);
auto offsetedTa = offset_ex(tempArea[ia], print.brim_flow().scaled_spacing() * 2, jtRound, SCALED_RESOLUTION);
if (!intersection_ex(offsetedTa, objectIslands).empty() ||
!intersection_ex(offsetedTa, otherExPoly).empty() ||
!intersection_ex(offsetedTa, otherExPolys).empty())
brimAreaMap[object->id()].push_back(tempArea[ia]);
} }
expolygons_append(brim_area, brimAreaMap[object->id()]);
} }
} }
return brim_area; return brim_area;

View File

@ -1088,56 +1088,6 @@ bool GCode::is_BBL_Printer()
//BBS : get the plate model's projection on first layer, contain plate offset,unscaled data //BBS : get the plate model's projection on first layer, contain plate offset,unscaled data
BoundingBoxf GCode::first_layer_projection(const Print& print) const BoundingBoxf GCode::first_layer_projection(const Print& print) const
{ {
// too slow
#if 0
// seperatre points into object for parallel
std::vector<Pointfs>points(print.objects().size());
auto objects = print.objects();
// use parallel for to speed the iterate
tbb::parallel_for(tbb::blocked_range<size_t>(0, points.size()), [&points,&objects](tbb::blocked_range<size_t> r) {
for (auto index = r.begin(); index < r.end(); ++index) {
Polygons obj_islands;
unsigned int estimate_size = (objects[index]->layers().empty() ? 0 : objects[index]->layers().size() * objects[index]->layers().front()->lslices.size());
obj_islands.reserve(estimate_size);
for (auto& layer : objects[index]->layers())
for (auto& expoly : layer->lslices)
obj_islands.emplace_back(expoly.contour);
if (!objects[index]->support_layers().empty()) {
for (auto& layer : objects[index]->support_layers()) {
if (layer->support_type == stInnerNormal)
layer->support_fills.polygons_covered_by_spacing(obj_islands, float(SCALED_EPSILON));
else if (layer->support_type == stInnerTree) {
for (auto& expoly : layer->lslices)
obj_islands.emplace_back(expoly.contour);
}
}
}
// caculate the transform
for (auto& instance : objects[index]->instances()) {
for (Polygon &poly : obj_islands) {
poly.translate(instance.shift);
Pointfs poly_points;
poly_points.reserve(poly.points.size());
for (auto& point : poly.points)
poly_points.emplace_back(unscale(point));
append(points[index], std::move(poly_points));
}
}
}
});
Pointfs total_points;
//consider first layers for skirt,brim,wipe tower
int estimate_size =std::accumulate(points.begin(), points.end(), print.first_layer_convex_hull().size(), [](int sum, const Pointfs& point) {return sum + point.size(); });;
total_points.reserve(estimate_size);
for (const auto& pt : print.first_layer_convex_hull().points)
total_points.emplace_back(unscale(pt.x(),pt.y()));
for (auto& point : points)
append(total_points, std::move(point));
return BoundingBoxf(total_points);
#endif
BoundingBoxf bbox; BoundingBoxf bbox;
for (auto& obj : print.objects()) { for (auto& obj : print.objects()) {
for (auto& instance : obj->instances()) { for (auto& instance : obj->instances()) {
@ -5288,11 +5238,6 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp
for (const ExPolygon& support_island : support_layer->support_islands) for (const ExPolygon& support_island : support_layer->support_islands)
if (support_island.contains(travel)) if (support_island.contains(travel))
return false; return false;
//reduce the retractions in lightning infills for tree support
if (support_layer != NULL && support_layer->support_type==stInnerTree)
for (auto &area : support_layer->base_areas)
if (area.contains(travel))
return false;
} }
//BBS: need retract when long moving to print perimeter to avoid dropping of material //BBS: need retract when long moving to print perimeter to avoid dropping of material
if (!is_perimeter(role) && m_config.reduce_infill_retraction && m_layer != nullptr && if (!is_perimeter(role) && m_config.reduce_infill_retraction && m_layer != nullptr &&

View File

@ -262,11 +262,6 @@ private:
LayerRegionPtrs m_regions; LayerRegionPtrs m_regions;
}; };
enum SupportInnerType {
stInnerNormal,
stInnerTree
};
class SupportLayer : public Layer class SupportLayer : public Layer
{ {
public: public:
@ -275,7 +270,6 @@ public:
ExPolygons support_islands; ExPolygons support_islands;
// Extrusion paths for the support base and for the support interface and contacts. // Extrusion paths for the support base and for the support interface and contacts.
ExtrusionEntityCollection support_fills; ExtrusionEntityCollection support_fills;
SupportInnerType support_type = stInnerNormal;
// for tree supports // for tree supports
ExPolygons base_areas; ExPolygons base_areas;
@ -296,7 +290,7 @@ protected:
// The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower // The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower
// between the raft and the object first layer. // between the raft and the object first layer.
SupportLayer(size_t id, size_t interface_id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) : SupportLayer(size_t id, size_t interface_id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
Layer(id, object, height, print_z, slice_z), m_interface_id(interface_id), support_type(stInnerNormal) {} Layer(id, object, height, print_z, slice_z), m_interface_id(interface_id) {}
virtual ~SupportLayer() = default; virtual ~SupportLayer() = default;
size_t m_interface_id; size_t m_interface_id;

View File

@ -2175,13 +2175,9 @@ Polygons Print::first_layer_islands() const
for (ExPolygon &expoly : object->m_layers.front()->lslices) for (ExPolygon &expoly : object->m_layers.front()->lslices)
object_islands.push_back(expoly.contour); object_islands.push_back(expoly.contour);
if (!object->support_layers().empty()) { if (!object->support_layers().empty()) {
if (object->support_layers().front()->support_type==stInnerNormal) ExPolygons &expolys_first_layer = object->m_support_layers.front()->support_islands;
object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
else if(object->support_layers().front()->support_type==stInnerTree) {
ExPolygons &expolys_first_layer = object->m_support_layers.front()->lslices;
for (ExPolygon &expoly : expolys_first_layer) { object_islands.push_back(expoly.contour); } for (ExPolygon &expoly : expolys_first_layer) { object_islands.push_back(expoly.contour); }
} }
}
islands.reserve(islands.size() + object_islands.size() * object->instances().size()); islands.reserve(islands.size() + object_islands.size() * object->instances().size());
for (const PrintInstance &instance : object->instances()) for (const PrintInstance &instance : object->instances())
for (Polygon &poly : object_islands) { for (Polygon &poly : object_islands) {
@ -2622,7 +2618,6 @@ std::string PrintStatistics::finalize_output_path(const std::string &path_in) co
#define JSON_SUPPORT_LAYER_ISLANDS "support_islands" #define JSON_SUPPORT_LAYER_ISLANDS "support_islands"
#define JSON_SUPPORT_LAYER_FILLS "support_fills" #define JSON_SUPPORT_LAYER_FILLS "support_fills"
#define JSON_SUPPORT_LAYER_INTERFACE_ID "interface_id" #define JSON_SUPPORT_LAYER_INTERFACE_ID "interface_id"
#define JSON_SUPPORT_LAYER_TYPE "support_type"
#define JSON_LAYER_REGION_CONFIG_HASH "config_hash" #define JSON_LAYER_REGION_CONFIG_HASH "config_hash"
#define JSON_LAYER_REGION_SLICES "slices" #define JSON_LAYER_REGION_SLICES "slices"
@ -3284,7 +3279,6 @@ void extract_layer(const json& layer_json, Layer& layer) {
void extract_support_layer(const json& support_layer_json, SupportLayer& support_layer) { void extract_support_layer(const json& support_layer_json, SupportLayer& support_layer) {
extract_layer(support_layer_json, support_layer); extract_layer(support_layer_json, support_layer);
support_layer.support_type = support_layer_json[JSON_SUPPORT_LAYER_TYPE];
//support_islands //support_islands
int islands_count = support_layer_json[JSON_SUPPORT_LAYER_ISLANDS].size(); int islands_count = support_layer_json[JSON_SUPPORT_LAYER_ISLANDS].size();
for (int islands_index = 0; islands_index < islands_count; islands_index++) for (int islands_index = 0; islands_index < islands_count; islands_index++)
@ -3464,7 +3458,6 @@ int Print::export_cached_data(const std::string& directory, bool with_space)
convert_layer_to_json(support_layer_json, support_layer); convert_layer_to_json(support_layer_json, support_layer);
support_layer_json[JSON_SUPPORT_LAYER_INTERFACE_ID] = support_layer->interface_id(); support_layer_json[JSON_SUPPORT_LAYER_INTERFACE_ID] = support_layer->interface_id();
support_layer_json[JSON_SUPPORT_LAYER_TYPE] = support_layer->support_type;
//support_islands //support_islands
for (const ExPolygon& support_island : support_layer->support_islands) { for (const ExPolygon& support_island : support_layer->support_islands) {

View File

@ -659,7 +659,6 @@ std::shared_ptr<TreeSupportData> PrintObject::alloc_tree_support_preview_cache()
SupportLayer* PrintObject::add_tree_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z) SupportLayer* PrintObject::add_tree_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z)
{ {
m_support_layers.emplace_back(new SupportLayer(id, 0, this, height, print_z, slice_z)); m_support_layers.emplace_back(new SupportLayer(id, 0, this, height, print_z, slice_z));
m_support_layers.back()->support_type = stInnerTree;
return m_support_layers.back(); return m_support_layers.back();
} }

View File

@ -2063,7 +2063,7 @@ void TreeSupport::draw_circles()
BOOST_LOG_TRIVIAL(debug) << "circles at layer " << layer_nr << " contact nodes size=" << curr_layer_nodes.size(); BOOST_LOG_TRIVIAL(debug) << "circles at layer " << layer_nr << " contact nodes size=" << curr_layer_nodes.size();
//Draw the support areas and add the roofs appropriately to the support roof instead of normal areas. //Draw the support areas and add the roofs appropriately to the support roof instead of normal areas.
ts_layer->lslices.reserve(curr_layer_nodes.size()); ts_layer->support_islands.reserve(curr_layer_nodes.size());
ExPolygons area_poly; // the polygon node area which will be printed as normal support ExPolygons area_poly; // the polygon node area which will be printed as normal support
for (const SupportNode* p_node : curr_layer_nodes) for (const SupportNode* p_node : curr_layer_nodes)
{ {
@ -2230,14 +2230,14 @@ void TreeSupport::draw_circles()
expoly->holes.end()); expoly->holes.end());
if (layer_nr < brim_skirt_layers) if (layer_nr < brim_skirt_layers)
ts_layer->lslices.emplace_back(*expoly); ts_layer->support_islands.emplace_back(*expoly);
} }
ts_layer->lslices = std::move(union_ex(ts_layer->lslices)); ts_layer->support_islands = std::move(union_ex(ts_layer->support_islands));
//Must update bounding box which is used in avoid crossing perimeter //Must update bounding box which is used in avoid crossing perimeter
ts_layer->lslices_bboxes.clear(); ts_layer->lslices_bboxes.clear();
ts_layer->lslices_bboxes.reserve(ts_layer->lslices.size()); ts_layer->lslices_bboxes.reserve(ts_layer->support_islands.size());
for (const ExPolygon& expoly : ts_layer->lslices) for (const ExPolygon& expoly : ts_layer->support_islands)
ts_layer->lslices_bboxes.emplace_back(get_extents(expoly)); ts_layer->lslices_bboxes.emplace_back(get_extents(expoly));
ts_layer->backup_untyped_slices(); ts_layer->backup_untyped_slices();