diff --git a/resources/profiles/BBL/process/fdm_process_bbl_common.json b/resources/profiles/BBL/process/fdm_process_bbl_common.json index 85ff4ac4d..d77980a29 100644 --- a/resources/profiles/BBL/process/fdm_process_bbl_common.json +++ b/resources/profiles/BBL/process/fdm_process_bbl_common.json @@ -70,7 +70,5 @@ "wipe_tower_no_sparse_layers": "0", "prime_tower_width": "35", "wall_generator": "classic", - "z_direction_outwall_speed_continuous": "1", - "layer_time_smoothing": "0", "compatible_printers": [] } \ No newline at end of file diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 312c990e7..e32c6d3c0 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -16,24 +16,6 @@ using ExPolygons = std::vector; class ExtrusionEntityCollection; class Extruder; -struct LoopNode -{ - //store outer wall and mark if it's loop - std::pair exp; - int node_id; - int region_id; - int perimeter_id; - int loop_id = 0; - BoundingBox bbox; - int merged_id = -1; - - //upper loop info - std::vector upper_node_id; - - //lower loop info - std::vector lower_node_id; -}; - // Each ExtrusionRole value identifies a distinct set of { extruder, speed } enum ExtrusionRole : uint8_t { erNone, diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index dec981eb8..413834db2 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -31,12 +31,9 @@ public: ExtrusionEntitiesPtr entities; // we own these entities bool no_sort; - - std::pair loop_node_range; ExtrusionEntityCollection(): no_sort(false) {} - ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), is_reverse(other.is_reverse), loop_node_range(other.loop_node_range) { this->append(other.entities); } - ExtrusionEntityCollection(ExtrusionEntityCollection &&other) - : entities(std::move(other.entities)), no_sort(other.no_sort), is_reverse(other.is_reverse), loop_node_range(other.loop_node_range) {} + ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort), is_reverse(other.is_reverse) { this->append(other.entities); } + ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort), is_reverse(other.is_reverse) {} explicit ExtrusionEntityCollection(const ExtrusionPaths &paths); ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other); ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other) @@ -44,7 +41,6 @@ public: this->entities = std::move(other.entities); this->no_sort = other.no_sort; is_reverse = other.is_reverse; - loop_node_range = other.loop_node_range; return *this; } ~ExtrusionEntityCollection() { clear(); } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 05022fc1f..862af71e2 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -67,7 +67,6 @@ using namespace std::literals::string_view_literals; #endif #include -#include namespace Slic3r { @@ -2417,18 +2416,8 @@ void GCode::process_layers( const std::vector>> &layers_to_print, GCodeOutputStream &output_stream) { - //BBS: get object label id - size_t layer_to_print_idx = 0; - std::vector object_label; - - for (const PrintInstance *instance : print_object_instances_ordering) - object_label.push_back(instance->model_instance->get_labeled_id()); - - SmoothCalculator smooth_calculator(layers_to_print.size(), print.objects().size()); - std::vector> layers_extruder_adjustments; - layers_extruder_adjustments.resize(layers_to_print.size()); - // The pipeline is variable: The vase mode filter is optional. + size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [this, &print, &tool_ordering, &print_object_instances_ordering, &layers_to_print, &layer_to_print_idx](tbb::flow_control& fc) -> GCode::LayerResult { if (layer_to_print_idx == layers_to_print.size()) { @@ -2457,72 +2446,19 @@ void GCode::process_layers( bool last_layer = in.layer_id == layers_to_print.size() - 1; return { spiral_mode.process_layer(std::move(in.gcode), last_layer), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush}; }); - - std::vector layers_results; - layers_results.resize(layers_to_print.size()); - const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer.get(), object_label, &smooth_calculator, &layers_extruder_adjustments, &layers_results](GCode::LayerResult in) { - layers_results[in.layer_id] = in; - std::string out = cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, smooth_calculator, layers_extruder_adjustments[in.layer_id], object_label, in.cooling_buffer_flush, false); - if (in.layer_id == 0) - layers_results[in.layer_id].gcode = out; - return; - }); - - const auto cooling_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [ &cooling_buffer = *this->m_cooling_buffer.get(), object_label, &smooth_calculator, &layers_extruder_adjustments](GCode::LayerResult in) -> std::string { - return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, smooth_calculator, layers_extruder_adjustments[in.layer_id], object_label, in.cooling_buffer_flush, true); - }); - - // BBS: apply new feedrate of outwall and recalculate layer time - int layer_idx = 0; - bool layer_time_smoothing = m_config.layer_time_smoothing; - const auto cooling_smooth= tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [&cooling_buffer = *this->m_cooling_buffer.get(), &layer_idx, object_label, &smooth_calculator, &layers_extruder_adjustments, &layers_to_print, &layers_results, layer_time_smoothing](tbb::flow_control& fc) -> std::string { - if(layer_idx == layers_to_print.size()){ - fc.stop(); - return{}; - }else{ - if (layer_idx > 0) { - const std::pair> &layer = layers_to_print[layer_idx++]; - return cooling_buffer.apply_smooth_layer_time(std::move(layers_results[layer_idx - 1].gcode), smooth_calculator, layers_extruder_adjustments[layer_idx - 1], layer_idx - 1, layer_time_smoothing); - } else { - return layers_results[layer_idx++].gcode; - } - } + const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, + [&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in) -> std::string { + return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); - - const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&output_stream](std::string s) { output_stream.write(s); }); + [&output_stream](std::string s) { output_stream.write(s); } + ); - // BBS: apply cooling // The pipeline elements are joined using const references, thus no copying is performed. if (m_spiral_vase) - tbb::parallel_pipeline(12, generator & spiral_mode & cooling_vase & output); - else if (!(layer_time_smoothing || m_config.z_direction_outwall_speed_continuous)) - tbb::parallel_pipeline(12, generator & cooling_vase & output); - else { - tbb::parallel_pipeline(12, generator & cooling); - - if (m_config.z_direction_outwall_speed_continuous) { - smooth_calculator.smooth_layer_speed(); - - tbb::parallel_for(tbb::blocked_range(0, layers_to_print.size()), [this, &print, &cooling_buffer = *this->m_cooling_buffer.get(), object_label, &smooth_calculator, &layers_extruder_adjustments, &layers_to_print, &layers_results](const tbb::blocked_range &range) { - for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { - print.throw_if_canceled(); - if (layer_idx > 0) { - const std::pair> &layer = layers_to_print[layer_idx]; - cooling_buffer.apply_smooth_speed(smooth_calculator, layers_extruder_adjustments[layer_idx], layer_idx); - } - } - }); - } - //smooth layer time - if (layer_time_smoothing) - smooth_calculator.smooth_layer_time(); - - tbb::parallel_pipeline(12, cooling_smooth & output); - } + tbb::parallel_pipeline(12, generator & spiral_mode & cooling & output); + else + tbb::parallel_pipeline(12, generator & cooling & output); } // Process all layers of a single object instance (sequential mode) with a parallel pipeline: @@ -2537,17 +2473,8 @@ void GCode::process_layers( // BBS const bool prime_extruder) { - // BBS: get object label id - size_t layer_to_print_idx = 0; - std::vector object_label; - for (LayerToPrint layer : layers_to_print) - object_label.push_back(layer.original_object->instances()[single_object_idx].model_instance->get_labeled_id()); - - SmoothCalculator smooth_calculator(layers_to_print.size(), print.objects().size()); - std::vector> layers_extruder_adjustments; - layers_extruder_adjustments.resize(layers_to_print.size()); - // The pipeline is variable: The vase mode filter is optional. + size_t layer_to_print_idx = 0; const auto generator = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [this, &print, &tool_ordering, &layers_to_print, &layer_to_print_idx, single_object_idx, prime_extruder](tbb::flow_control& fc) -> GCode::LayerResult { if (layer_to_print_idx == layers_to_print.size()) { @@ -2573,75 +2500,19 @@ void GCode::process_layers( bool last_layer = in.layer_id == layers_to_print.size() - 1; return { spiral_mode.process_layer(std::move(in.gcode), last_layer), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush }; }); - - //BBS: get objects and nodes info, for better arrange - const ConstPrintObjectPtrsAdaptor &objects = print.objects(); - - std::vector layers_results; - layers_results.resize(layers_to_print.size()); - const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer.get(), &smooth_calculator, &layers_extruder_adjustments, object_label, &layers_results](GCode::LayerResult in) { - layers_results[in.layer_id] = in; - std::string out = cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, smooth_calculator, layers_extruder_adjustments[in.layer_id], object_label, in.cooling_buffer_flush, false); - if (in.layer_id == 0) - layers_results[in.layer_id].gcode = out; - return; - }); - - const auto cooling_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [ &cooling_buffer = *this->m_cooling_buffer.get(), object_label, &smooth_calculator, &layers_extruder_adjustments](GCode::LayerResult in) -> std::string { - return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, smooth_calculator,layers_extruder_adjustments[in.layer_id], object_label, in.cooling_buffer_flush, true); - }); - - // BBS: apply new feedrate of outwall and recalculate layer time - int layer_idx = 0; - bool layer_time_smoothing = m_config.layer_time_smoothing; - const auto cooling_smooth= tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [&cooling_buffer = *this->m_cooling_buffer.get(), &layer_idx, object_label, &layers_to_print, &layers_results, layer_time_smoothing, &smooth_calculator, &layers_extruder_adjustments](tbb::flow_control& fc) -> std::string { - if(layer_idx == layers_to_print.size()){ - fc.stop(); - return{}; - }else{ - if (layer_idx > 0) { - LayerToPrint &layer = layers_to_print[layer_idx++]; - return cooling_buffer.apply_smooth_layer_time(std::move(layers_results[layer_idx - 1].gcode), smooth_calculator, layers_extruder_adjustments[layer_idx - 1], layer_idx - 1, layer_time_smoothing); - } else { - return layers_results[layer_idx++].gcode; - } - } + const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, + [&cooling_buffer = *this->m_cooling_buffer.get()](GCode::LayerResult in)->std::string { + return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); - - const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&output_stream](std::string s) { output_stream.write(s); }); + [&output_stream](std::string s) { output_stream.write(s); } + ); - // BBS: apply cooling // The pipeline elements are joined using const references, thus no copying is performed. if (m_spiral_vase) - tbb::parallel_pipeline(12, generator & spiral_mode & cooling_vase & output); - else if (!(layer_time_smoothing || m_config.z_direction_outwall_speed_continuous)) - tbb::parallel_pipeline(12, generator & cooling_vase & output); - else { - tbb::parallel_pipeline(12, generator & cooling); - - if (m_config.z_direction_outwall_speed_continuous) { - smooth_calculator.smooth_layer_speed(); - - tbb::parallel_for(tbb::blocked_range(0, layers_to_print.size()), [this, &print, &cooling_buffer = *this->m_cooling_buffer.get(), object_label, &smooth_calculator, &layers_extruder_adjustments, &layers_to_print, &layers_results](const tbb::blocked_range &range) { - for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { - print.throw_if_canceled(); - if (layer_idx > 0) { - LayerToPrint &layer = layers_to_print[layer_idx]; - cooling_buffer.apply_smooth_speed(smooth_calculator, layers_extruder_adjustments[layer_idx], layer_idx); - } - } - }); - } - // smooth layer time - if (layer_time_smoothing) - smooth_calculator.smooth_layer_time(); - - tbb::parallel_pipeline(12, cooling_smooth & output); - } + tbb::parallel_pipeline(12, generator & spiral_mode & cooling & output); + else + tbb::parallel_pipeline(12, generator & cooling & output); } std::string GCode::placeholder_parser_process(const std::string &name, const std::string &templ, unsigned int current_extruder_id, const DynamicConfig *config_override) @@ -3504,8 +3375,7 @@ GCode::LayerResult GCode::process_layer( // The process is almost the same for perimeters and infills - we will do it in a cycle that repeats twice: std::vector printing_extruders; for (const ObjectByExtruder::Island::Region::Type entity_type : { ObjectByExtruder::Island::Region::INFILL, ObjectByExtruder::Island::Region::PERIMETERS }) { - bool is_infill = entity_type == ObjectByExtruder::Island::Region::INFILL; - for (const ExtrusionEntity *ee : is_infill ? layerm->fills.entities : layerm->perimeters.entities) { + for (const ExtrusionEntity *ee : (entity_type == ObjectByExtruder::Island::Region::INFILL) ? layerm->fills.entities : layerm->perimeters.entities) { // extrusions represents infill or perimeter extrusions of a single island. assert(dynamic_cast(ee) != nullptr); const auto *extrusions = static_cast(ee); @@ -3558,15 +3428,6 @@ GCode::LayerResult GCode::process_layer( if (islands[island_idx].by_region.empty()) islands[island_idx].by_region.assign(print.num_print_regions(), ObjectByExtruder::Island::Region()); islands[island_idx].by_region[region.print_region_id()].append(entity_type, extrusions, entity_overrides); - int start = extrusions->loop_node_range.first; - int end = extrusions->loop_node_range.second; - //BBS: add merged node infor - if (!is_infill) { - for (; start < end; ++start) { - const LoopNode *node = &layer.loop_nodes[start]; - islands[island_idx].by_region[region.print_region_id()].merged_node.emplace_back(node); - } - } break; } } @@ -3701,8 +3562,6 @@ GCode::LayerResult GCode::process_layer( if (m_config.reduce_crossing_wall) m_avoid_crossing_perimeters.init_layer(*m_layer); - //BBS: label object id, prepare for cooling - gcode += "; OBJECT_ID: " + std::to_string(instance_to_print.label_object_id) + "\n"; std::string temp_start_str; if (m_enable_label_object) { std::string start_str = std::string("; start printing object, unique label id: ") + std::to_string(instance_to_print.label_object_id) + "\n"; @@ -4422,18 +4281,8 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vectorloop_id) { - gcode += "; COOLING_NODE: " + std::to_string(region.merged_node[curr_node]->merged_id) + "\n"; - curr_node++; - } - + for (const ExtrusionEntity* ee : region.perimeters) gcode += this->extrude_entity(*ee, "perimeter", -1.); - } } return gcode; } @@ -5058,29 +4907,26 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } std::string comment; - bool cooling_extrude = false; if (m_enable_cooling_markers) { if (EXTRUDER_CONFIG(enable_overhang_bridge_fan)) { //BBS: Overhang_threshold_none means Overhang_threshold_1_4 and forcing cooling for all external perimeter int overhang_threshold = EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none ? Overhang_threshold_none : EXTRUDER_CONFIG(overhang_fan_threshold) - 1; - if ((EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none && path.role() == erExternalPerimeter) || (path.get_overhang_degree() > overhang_threshold || - is_bridge(path.role()))) { + if ((EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none && path.role() == erExternalPerimeter)) { + gcode += ";_OVERHANG_FAN_START\n"; + } else if (path.get_overhang_degree() > overhang_threshold || + is_bridge(path.role())) gcode += ";_OVERHANG_FAN_START\n"; - } } int overhang_boundary_for_cooling = EXTRUDER_CONFIG(overhang_threshold_participating_cooling); if (!is_bridge(path.role()) && path.get_overhang_degree() <= overhang_boundary_for_cooling) { - cooling_extrude = true; comment = ";_EXTRUDE_SET_SPEED"; } if (path.role() == erExternalPerimeter) comment += ";_EXTERNAL_PERIMETER"; - else if (path.role() == erPerimeter) - comment += ";_PERIMETER"; } // F is mm per minute. @@ -5170,16 +5016,22 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, } } if (m_enable_cooling_markers) { - if (cooling_extrude) - gcode += ";_EXTRUDE_END\n"; - - if ( EXTRUDER_CONFIG(enable_overhang_bridge_fan)) { + if (EXTRUDER_CONFIG(enable_overhang_bridge_fan)) { //BBS: Overhang_threshold_none means Overhang_threshold_1_4 and forcing cooling for all external perimeter int overhang_threshold = EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none ? Overhang_threshold_none : EXTRUDER_CONFIG(overhang_fan_threshold) - 1; - if ((EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none && path.role() == erExternalPerimeter) || (path.get_overhang_degree() > overhang_threshold || - is_bridge(path.role()))) + if ((EXTRUDER_CONFIG(overhang_fan_threshold) == Overhang_threshold_none && path.role() == erExternalPerimeter)) { + gcode += ";_EXTRUDE_END\n"; gcode += ";_OVERHANG_FAN_END\n"; + + } else if (path.get_overhang_degree() > overhang_threshold || + is_bridge(path.role())) + gcode += ";_OVERHANG_FAN_END\n"; + else + gcode += ";_EXTRUDE_END\n"; + } + else { + gcode += ";_EXTRUDE_END\n"; } } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 98b9dedb0..f3096a74b 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -366,7 +366,7 @@ private: ExtrusionEntitiesPtr perimeters; // Non-owned references to LayerRegion::fills::entities ExtrusionEntitiesPtr infills; - std::vector merged_node; + std::vector infills_overrides; std::vector perimeters_overrides; diff --git a/src/libslic3r/GCode/CoolingBuffer.cpp b/src/libslic3r/GCode/CoolingBuffer.cpp index 4d81a4853..1d35b2ec5 100644 --- a/src/libslic3r/GCode/CoolingBuffer.cpp +++ b/src/libslic3r/GCode/CoolingBuffer.cpp @@ -41,6 +41,202 @@ void CoolingBuffer::reset(const Vec3d &position) m_current_fan_speed = -1; } +struct CoolingLine +{ + enum Type { + TYPE_SET_TOOL = 1 << 0, + TYPE_EXTRUDE_END = 1 << 1, + TYPE_OVERHANG_FAN_START = 1 << 2, + TYPE_OVERHANG_FAN_END = 1 << 3, + TYPE_G0 = 1 << 4, + TYPE_G1 = 1 << 5, + TYPE_ADJUSTABLE = 1 << 6, + TYPE_EXTERNAL_PERIMETER = 1 << 7, + // The line sets a feedrate. + TYPE_HAS_F = 1 << 8, + TYPE_WIPE = 1 << 9, + TYPE_G4 = 1 << 10, + TYPE_G92 = 1 << 11, + //BBS: add G2 G3 type + TYPE_G2 = 1 << 12, + TYPE_G3 = 1 << 13, + TYPE_FORCE_RESUME_FAN = 1 << 14, + TYPE_SET_FAN_CHANGING_LAYER = 1 << 15, + }; + + CoolingLine(unsigned int type, size_t line_start, size_t line_end) : + type(type), line_start(line_start), line_end(line_end), + length(0.f), feedrate(0.f), time(0.f), time_max(0.f), slowdown(false) {} + + bool adjustable(bool slowdown_external_perimeters) const { + return (this->type & TYPE_ADJUSTABLE) && + (! (this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) && + this->time < this->time_max; + } + + bool adjustable() const { + return (this->type & TYPE_ADJUSTABLE) && this->time < this->time_max; + } + + size_t type; + // Start of this line at the G-code snippet. + size_t line_start; + // End of this line at the G-code snippet. + size_t line_end; + // XY Euclidian length of this segment. + float length; + // Current feedrate, possibly adjusted. + float feedrate; + // Current duration of this segment. + float time; + // Maximum duration of this segment. + float time_max; + // If marked with the "slowdown" flag, the line has been slowed down. + bool slowdown; +}; + +// Calculate the required per extruder time stretches. +struct PerExtruderAdjustments +{ + // Calculate the total elapsed time per this extruder, adjusted for the slowdown. + float elapsed_time_total() const { + float time_total = 0.f; + for (const CoolingLine &line : lines) + time_total += line.time; + return time_total; + } + // Calculate the total elapsed time when slowing down + // to the minimum extrusion feed rate defined for the current material. + float maximum_time_after_slowdown(bool slowdown_external_perimeters) const { + float time_total = 0.f; + for (const CoolingLine &line : lines) + if (line.adjustable(slowdown_external_perimeters)) { + if (line.time_max == FLT_MAX) + return FLT_MAX; + else + time_total += line.time_max; + } else + time_total += line.time; + return time_total; + } + // Calculate the adjustable part of the total time. + float adjustable_time(bool slowdown_external_perimeters) const { + float time_total = 0.f; + for (const CoolingLine &line : lines) + if (line.adjustable(slowdown_external_perimeters)) + time_total += line.time; + return time_total; + } + // Calculate the non-adjustable part of the total time. + float non_adjustable_time(bool slowdown_external_perimeters) const { + float time_total = 0.f; + for (const CoolingLine &line : lines) + if (! line.adjustable(slowdown_external_perimeters)) + time_total += line.time; + return time_total; + } + // Slow down the adjustable extrusions to the minimum feedrate allowed for the current extruder material. + // Used by both proportional and non-proportional slow down. + float slowdown_to_minimum_feedrate(bool slowdown_external_perimeters) { + float time_total = 0.f; + for (CoolingLine &line : lines) { + if (line.adjustable(slowdown_external_perimeters)) { + assert(line.time_max >= 0.f && line.time_max < FLT_MAX); + line.slowdown = true; + line.time = line.time_max; + line.feedrate = line.length / line.time; + } + time_total += line.time; + } + return time_total; + } + // Slow down each adjustable G-code line proportionally by a factor. + // Used by the proportional slow down. + float slow_down_proportional(float factor, bool slowdown_external_perimeters) { + assert(factor >= 1.f); + float time_total = 0.f; + for (CoolingLine &line : lines) { + if (line.adjustable(slowdown_external_perimeters)) { + line.slowdown = true; + line.time = std::min(line.time_max, line.time * factor); + line.feedrate = line.length / line.time; + } + time_total += line.time; + } + return time_total; + } + + // Sort the lines, adjustable first, higher feedrate first. + // Used by non-proportional slow down. + void sort_lines_by_decreasing_feedrate() { + std::sort(lines.begin(), lines.end(), [](const CoolingLine &l1, const CoolingLine &l2) { + bool adj1 = l1.adjustable(); + bool adj2 = l2.adjustable(); + return (adj1 == adj2) ? l1.feedrate > l2.feedrate : adj1; + }); + for (n_lines_adjustable = 0; + n_lines_adjustable < lines.size() && this->lines[n_lines_adjustable].adjustable(); + ++ n_lines_adjustable); + time_non_adjustable = 0.f; + for (size_t i = n_lines_adjustable; i < lines.size(); ++ i) + time_non_adjustable += lines[i].time; + } + + // Calculate the maximum time stretch when slowing down to min_feedrate. + // Slowdown to min_feedrate shall be allowed for this extruder's material. + // Used by non-proportional slow down. + float time_stretch_when_slowing_down_to_feedrate(float min_feedrate) const { + float time_stretch = 0.f; + assert(this->slow_down_min_speed < min_feedrate + EPSILON); + for (size_t i = 0; i < n_lines_adjustable; ++ i) { + const CoolingLine &line = lines[i]; + if (line.feedrate > min_feedrate) + time_stretch += line.time * (line.feedrate / min_feedrate - 1.f); + } + return time_stretch; + } + + // Slow down all adjustable lines down to min_feedrate. + // Slowdown to min_feedrate shall be allowed for this extruder's material. + // Used by non-proportional slow down. + void slow_down_to_feedrate(float min_feedrate) { + assert(this->slow_down_min_speed < min_feedrate + EPSILON); + for (size_t i = 0; i < n_lines_adjustable; ++ i) { + CoolingLine &line = lines[i]; + if (line.feedrate > min_feedrate) { + line.time *= std::max(1.f, line.feedrate / min_feedrate); + line.feedrate = min_feedrate; + line.slowdown = true; + } + } + } + + // Extruder, for which the G-code will be adjusted. + unsigned int extruder_id = 0; + // Is the cooling slow down logic enabled for this extruder's material? + bool cooling_slow_down_enabled = false; + // Slow down the print down to slow_down_min_speed if the total layer time is below slow_down_layer_time. + float slow_down_layer_time = 0.f; + // Minimum print speed allowed for this extruder. + float slow_down_min_speed = 0.f; + + // Parsed lines. + std::vector lines; + // The following two values are set by sort_lines_by_decreasing_feedrate(): + // Number of adjustable lines, at the start of lines. + size_t n_lines_adjustable = 0; + // Non-adjustable time of lines starting with n_lines_adjustable. + float time_non_adjustable = 0; + // Current total time for this extruder. + float time_total = 0; + // Maximum time for this extruder, when the maximum slow down is applied. + float time_maximum = 0; + + // Temporaries for processing the slow down. Both thresholds go from 0 to n_lines_adjustable. + size_t idx_line_begin = 0; + size_t idx_line_end = 0; +}; + // Calculate a new feedrate when slowing down by time_stretch for segments faster than min_feedrate. // Used by non-proportional slow down. float new_feedrate_to_reach_time_stretch( @@ -98,77 +294,7 @@ finished: return new_feedrate; } -static void exclude_participate_in_speed_slowdown(std::vector> &lines, std::vector &per_extruder_adjustments, CoolingNode &node, bool is_outwall) -{ - for (std::pair line_pos : lines) { - CoolingLine &line = per_extruder_adjustments[line_pos.second].lines[line_pos.first]; - if (line.feedrate > node.filter_feedrate) { - if(is_outwall) - line.feedrate = node.filter_feedrate; - else - line.feedrate *= node.rate; - } - - // not adjust outwal line speed - line.type = line.type & (~CoolingLine::TYPE_ADJUSTABLE); - // update time cost - if (line.feedrate == 0 || line.length == 0) - line.time = 0; - else - line.time = line.length / line.feedrate; - } -} - -//BBS: apply the smooth outwall speed and recalculate the layer time -void CoolingBuffer::apply_smooth_speed(SmoothCalculator &smooth_calculator, std::vector &extruder_adjustments, const int layer_id) -{ - //rewrite feedrate - for (size_t obj_id = 0; obj_id < smooth_calculator.layers_wall_collection[layer_id].size(); ++obj_id) { - for (size_t node_id = 0; node_id < smooth_calculator.layers_wall_collection[layer_id][obj_id].cooling_nodes.size(); ++node_id) { - CoolingNode &node = smooth_calculator.layers_wall_collection[layer_id][obj_id].cooling_nodes[node_id]; - node.rate = node.filter_feedrate / node.max_feedrate; - //set outwall speed - exclude_participate_in_speed_slowdown(node.outwall_line, extruder_adjustments, node, true); - - //set inner wall speed - exclude_participate_in_speed_slowdown(node.innerwall_line, extruder_adjustments, node, false); - } - } - - //recalculate cooling of other paths - smooth_calculator.layers_cooling_time[layer_id] = this->calculate_layer_slowdown(extruder_adjustments); - -} -//BBS: apply new layer time and rewite the gcode feedrate -std::string CoolingBuffer::apply_smooth_layer_time(std::string && gcode, - SmoothCalculator & smooth_calculator, - std::vector &extruder_adjustments, - const int layer_id, - const bool smooth_layer_time) -{ - if (smooth_layer_time) { - // update layer time - for (PerExtruderAdjustments &adj : extruder_adjustments) - if (adj.slow_down_layer_time < smooth_calculator.layers_cooling_time[layer_id]) - adj.slow_down_layer_time = smooth_calculator.layers_cooling_time[layer_id]; - - // recalculate feedrate - smooth_calculator.layers_cooling_time[layer_id] = this->calculate_layer_slowdown(extruder_adjustments); - } - // apply cooling - std::string out; - out = this->apply_layer_cooldown(gcode, layer_id, smooth_calculator.layers_cooling_time[layer_id], extruder_adjustments); - - return out; -} - -std::string CoolingBuffer::process_layer(std::string && gcode, - const size_t layer_id, - SmoothCalculator & smooth_calculator, - std::vector &per_extruder_adjustments, - const std::vector & object_label, - const bool flush, - const bool spiral_vase) +std::string CoolingBuffer::process_layer(std::string &&gcode, size_t layer_id, bool flush) { // Cache the input G-code. if (m_gcode.empty()) @@ -180,96 +306,17 @@ std::string CoolingBuffer::process_layer(std::string && gco if (flush) { // This is either an object layer or the very last print layer. Calculate cool down over the collected support layers // and one object layer. - // initial and arrange node collection seq - if (!spiral_vase && layer_id > 0) - smooth_calculator.init_wall_collection(layer_id, object_label); - - //record parse gcode info - per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos, object_label, spiral_vase, layer_id > 0); - - //adjustments will be sorted on calculate layer slowdown - smooth_calculator.layers_cooling_time[layer_id] = this->calculate_layer_slowdown(per_extruder_adjustments); - if (spiral_vase || layer_id == 0) { - out = this->apply_layer_cooldown(m_gcode, layer_id, smooth_calculator.layers_cooling_time[layer_id], per_extruder_adjustments); - } else if (layer_id > 0) { - //BBS: update outwall feedrate - // update feedrate of outwall after initial cooling process - - for (size_t extruder_idx = 0; extruder_idx < per_extruder_adjustments.size(); ++extruder_idx) { - PerExtruderAdjustments &extruder_adjustments = per_extruder_adjustments[extruder_idx]; - for (size_t line_idx = 0; line_idx < extruder_adjustments.lines.size(); ++line_idx) { - CoolingLine &line = extruder_adjustments.lines[line_idx]; - if (line.outwall_smooth_mark) { - line.slowdown = true; - - // search node id - if (smooth_calculator.layers_wall_collection[layer_id][line.object_id].cooling_nodes.count(line.cooling_node_id) < 0) { - CoolingNode node; - smooth_calculator.layers_wall_collection[layer_id][line.object_id].cooling_nodes.emplace(line.cooling_node_id, node); - } - - CoolingNode &node = smooth_calculator.layers_wall_collection[layer_id][line.object_id].cooling_nodes[line.cooling_node_id]; - if( line.type & CoolingLine::TYPE_EXTERNAL_PERIMETER ) { - node.outwall_line.emplace_back(line_idx, extruder_idx); - if (node.max_feedrate < line.feedrate) { - node.max_feedrate = line.feedrate; - node.filter_feedrate = node.max_feedrate; - } - } else { - node.innerwall_line.emplace_back(line_idx, extruder_idx); - } - - } else { - line.slowdown = false; - line.feedrate = line.origin_feedrate; - // update time cost - if (line.feedrate == 0 || line.length == 0) - line.time = 0; - else - line.time = line.length / line.feedrate; - line.time_max = line.origin_time_max; - } - } - } - } + std::vector per_extruder_adjustments = this->parse_layer_gcode(m_gcode, m_current_pos); + float layer_time_stretched = this->calculate_layer_slowdown(per_extruder_adjustments); + out = this->apply_layer_cooldown(m_gcode, layer_id, layer_time_stretched, per_extruder_adjustments); m_gcode.clear(); } return out; } -static void mark_node_pos(bool &flag, int &line_idx, std::pair &node_pos, const std::vector &object_label, int cooling_node_id, int object_id, PerExtruderAdjustments* adjustment) -{ - for (size_t object_idx = 0; object_idx < object_label.size(); ++object_idx) { - if (object_label[object_idx] == object_id) { - if (cooling_node_id == -1) break; - line_idx = adjustment->lines.size(); - flag = true; - node_pos.first = object_idx; - node_pos.second = cooling_node_id; - break; - } - } -} - -static void record_wall_lines(bool &flag, int &line_idx, PerExtruderAdjustments *adjustment, const std::pair &node_pos) -{ - if (flag && line_idx < adjustment->lines.size()) { - CoolingLine &ptr = adjustment->lines[line_idx]; - ptr.outwall_smooth_mark = true; - ptr.object_id = node_pos.first; - ptr.cooling_node_id = node_pos.second; - flag = false; - } -} - -//native-resource://sandbox_fs/webcontent/resource/assets/img/41ecc25c56.png // Parse the layer G-code for the moves, which could be adjusted. // Return the list of parsed lines, bucketed by an extruder. -std::vector CoolingBuffer::parse_layer_gcode(const std::string & gcode, - std::vector & current_pos, - const std::vector & object_label, - bool spiral_vase, - bool join_z_smooth) const +std::vector CoolingBuffer::parse_layer_gcode(const std::string &gcode, std::vector ¤t_pos) const { std::vector per_extruder_adjustments(m_extruder_ids.size()); std::vector map_extruder_to_per_extruder_adjustment(m_num_extruders, 0); @@ -290,15 +337,7 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: // Index of an existing CoolingLine of the current adjustment, which holds the feedrate setting command // for a sequence of extrusion moves. size_t active_speed_modifier = size_t(-1); - int object_id = -1; - int cooling_node_id = -1; - std::string object_id_string = "; OBJECT_ID: "; - std::string cooling_node_label = "; COOLING_NODE: "; - bool append_wall_ptr = false; - bool append_inner_wall_ptr = false; - std::pair node_pos; - int line_idx = -1; for (; *line_start != 0; line_start = line_end) { while (*line_end != '\n' && *line_end != 0) @@ -319,15 +358,6 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: line.type = CoolingLine::TYPE_G2; else if (boost::starts_with(sline, "G3 ")) line.type = CoolingLine::TYPE_G3; - //BBS: parse object id & node id - else if (boost::starts_with(sline, object_id_string)) { - std::string sub = sline.substr(object_id_string.size()); - object_id = std::stoi(sub); - } else if (boost::starts_with(sline, cooling_node_label)) { - std::string sub = sline.substr(cooling_node_label.size()); - cooling_node_id = std::stoi(sub); - } - if (line.type) { // G0, G1 or G92 // Parse the G-code line. @@ -362,32 +392,14 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: } bool external_perimeter = boost::contains(sline, ";_EXTERNAL_PERIMETER"); bool wipe = boost::contains(sline, ";_WIPE"); - bool inner_perimeter = boost::contains(sline,";_PERIMETER"); - - record_wall_lines(append_inner_wall_ptr, line_idx, adjustment, node_pos); - + if (external_perimeter) + line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER; if (wipe) line.type |= CoolingLine::TYPE_WIPE; if (boost::contains(sline, ";_EXTRUDE_SET_SPEED") && ! wipe) { line.type |= CoolingLine::TYPE_ADJUSTABLE; active_speed_modifier = adjustment->lines.size(); - - if (inner_perimeter && join_z_smooth && !spiral_vase) { - // BBS: collect innerwall info - mark_node_pos(append_inner_wall_ptr, line_idx, node_pos, object_label, cooling_node_id, object_id, adjustment); - } } - - record_wall_lines(append_wall_ptr, line_idx, adjustment, node_pos); - - if (external_perimeter) { - line.type |= CoolingLine::TYPE_EXTERNAL_PERIMETER; - if (line.type & CoolingLine::TYPE_ADJUSTABLE && join_z_smooth && !spiral_vase) { - // BBS: collect outwall info - mark_node_pos(append_wall_ptr, line_idx, node_pos, object_label, cooling_node_id, object_id, adjustment); - } - } - if ((line.type & CoolingLine::TYPE_G92) == 0) { //BBS: G0, G1, G2, G3. Calculate the duration. if (m_config.use_relative_e_distances.value) @@ -417,19 +429,12 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: line.length = std::abs(dif[3]); } line.feedrate = new_pos[4]; - line.origin_feedrate = new_pos[4]; - assert((line.type & CoolingLine::TYPE_ADJUSTABLE) == 0 || line.feedrate > 0.f); if (line.length > 0) line.time = line.length / line.feedrate; - - if (line.feedrate == 0) - line.time = 0; - line.time_max = line.time; if ((line.type & CoolingLine::TYPE_ADJUSTABLE) || active_speed_modifier != size_t(-1)) line.time_max = (adjustment->slow_down_min_speed == 0.f) ? FLT_MAX : std::max(line.time, line.length / adjustment->slow_down_min_speed); - line.origin_time_max = line.time_max; // BBS: add G2 and G3 support if (active_speed_modifier < adjustment->lines.size() && ((line.type & CoolingLine::TYPE_G1) || (line.type & CoolingLine::TYPE_G2) || @@ -445,8 +450,6 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: sm.time_max = FLT_MAX; else sm.time_max += line.time_max; - - sm.origin_time_max = sm.time_max; } // Don't store this line. line.type = 0; @@ -486,7 +489,6 @@ std::vector CoolingBuffer::parse_layer_gcode(const std:: line.time = line.time_max = float( (pos_S > 0) ? atof(sline.c_str() + pos_S + 1) : (pos_P > 0) ? atof(sline.c_str() + pos_P + 1) * 0.001 : 0.); - line.origin_time_max = line.time_max; } else if (boost::starts_with(sline, ";_FORCE_RESUME_FAN_SPEED")) { line.type = CoolingLine::TYPE_FORCE_RESUME_FAN; } else if (boost::starts_with(sline, ";_SET_FAN_SPEED_CHANGING_LAYER")) { diff --git a/src/libslic3r/GCode/CoolingBuffer.hpp b/src/libslic3r/GCode/CoolingBuffer.hpp index 9d35c574d..90c60e5b1 100644 --- a/src/libslic3r/GCode/CoolingBuffer.hpp +++ b/src/libslic3r/GCode/CoolingBuffer.hpp @@ -4,215 +4,13 @@ #include "../libslic3r.h" #include #include -#include namespace Slic3r { class GCode; class Layer; +struct PerExtruderAdjustments; -struct CoolingLine -{ - enum Type { - TYPE_SET_TOOL = 1 << 0, - TYPE_EXTRUDE_END = 1 << 1, - TYPE_OVERHANG_FAN_START = 1 << 2, - TYPE_OVERHANG_FAN_END = 1 << 3, - TYPE_G0 = 1 << 4, - TYPE_G1 = 1 << 5, - TYPE_ADJUSTABLE = 1 << 6, - TYPE_EXTERNAL_PERIMETER = 1 << 7, - // The line sets a feedrate. - TYPE_HAS_F = 1 << 8, - TYPE_WIPE = 1 << 9, - TYPE_G4 = 1 << 10, - TYPE_G92 = 1 << 11, - // BBS: add G2 G3 type - TYPE_G2 = 1 << 12, - TYPE_G3 = 1 << 13, - TYPE_FORCE_RESUME_FAN = 1 << 14, - TYPE_SET_FAN_CHANGING_LAYER = 1 << 15, - }; - - CoolingLine(unsigned int type, size_t line_start, size_t line_end) - : type(type), line_start(line_start), line_end(line_end), length(0.f), feedrate(0.f), origin_feedrate(0.f), time(0.f), time_max(0.f), slowdown(false) - {} - - bool adjustable(bool slowdown_external_perimeters) const - { - return (this->type & TYPE_ADJUSTABLE) && (!(this->type & TYPE_EXTERNAL_PERIMETER) || slowdown_external_perimeters) && this->time < this->time_max; - } - - bool adjustable() const { return (this->type & TYPE_ADJUSTABLE) && this->time < this->time_max; } - - size_t type; - // Start of this line at the G-code snippet. - size_t line_start; - // End of this line at the G-code snippet. - size_t line_end; - // XY Euclidian length of this segment. - float length; - // Current feedrate, possibly adjusted. - float feedrate; - // Current duration of this segment. - float time; - // Maximum duration of this segment. - float time_max; - // If marked with the "slowdown" flag, the line has been slowed down. - bool slowdown; - // Current feedrate, possibly adjusted. - float origin_feedrate = 0; - float origin_time_max = 0; - // Current duration of this segment. - //float origin_time; - bool outwall_smooth_mark = false; - int object_id = -1; - int cooling_node_id = -1; -}; - -struct PerExtruderAdjustments -{ - // Calculate the total elapsed time per this extruder, adjusted for the slowdown. - float elapsed_time_total() const - { - float time_total = 0.f; - for (const CoolingLine &line : lines) time_total += line.time; - return time_total; - } - // Calculate the total elapsed time when slowing down - // to the minimum extrusion feed rate defined for the current material. - float maximum_time_after_slowdown(bool slowdown_external_perimeters) const - { - float time_total = 0.f; - for (const CoolingLine &line : lines) - if (line.adjustable(slowdown_external_perimeters)) { - if (line.time_max == FLT_MAX) - return FLT_MAX; - else - time_total += line.time_max; - } else - time_total += line.time; - return time_total; - } - // Calculate the adjustable part of the total time. - float adjustable_time(bool slowdown_external_perimeters) const - { - float time_total = 0.f; - for (const CoolingLine &line : lines) - if (line.adjustable(slowdown_external_perimeters)) time_total += line.time; - return time_total; - } - // Calculate the non-adjustable part of the total time. - float non_adjustable_time(bool slowdown_external_perimeters) const - { - float time_total = 0.f; - for (const CoolingLine &line : lines) - if (!line.adjustable(slowdown_external_perimeters)) time_total += line.time; - return time_total; - } - // Slow down the adjustable extrusions to the minimum feedrate allowed for the current extruder material. - // Used by both proportional and non-proportional slow down. - float slowdown_to_minimum_feedrate(bool slowdown_external_perimeters) - { - float time_total = 0.f; - for (CoolingLine &line : lines) { - if (line.adjustable(slowdown_external_perimeters)) { - assert(line.time_max >= 0.f && line.time_max < FLT_MAX); - line.slowdown = true; - line.time = line.time_max; - line.feedrate = line.length / line.time; - } - time_total += line.time; - } - return time_total; - } - // Slow down each adjustable G-code line proportionally by a factor. - // Used by the proportional slow down. - float slow_down_proportional(float factor, bool slowdown_external_perimeters) - { - assert(factor >= 1.f); - float time_total = 0.f; - for (CoolingLine &line : lines) { - if (line.adjustable(slowdown_external_perimeters)) { - line.slowdown = true; - line.time = std::min(line.time_max, line.time * factor); - line.feedrate = line.length / line.time; - } - time_total += line.time; - } - return time_total; - } - - // Sort the lines, adjustable first, higher feedrate first. - // Used by non-proportional slow down. - void sort_lines_by_decreasing_feedrate() - { - std::sort(lines.begin(), lines.end(), [](const CoolingLine &l1, const CoolingLine &l2) { - bool adj1 = l1.adjustable(); - bool adj2 = l2.adjustable(); - return (adj1 == adj2) ? l1.feedrate > l2.feedrate : adj1; - }); - for (n_lines_adjustable = 0; n_lines_adjustable < lines.size() && this->lines[n_lines_adjustable].adjustable(); ++n_lines_adjustable) - ; - time_non_adjustable = 0.f; - for (size_t i = n_lines_adjustable; i < lines.size(); ++i) time_non_adjustable += lines[i].time; - } - - // Calculate the maximum time stretch when slowing down to min_feedrate. - // Slowdown to min_feedrate shall be allowed for this extruder's material. - // Used by non-proportional slow down. - float time_stretch_when_slowing_down_to_feedrate(float min_feedrate) const - { - float time_stretch = 0.f; - assert(this->slow_down_min_speed < min_feedrate + EPSILON); - for (size_t i = 0; i < n_lines_adjustable; ++i) { - const CoolingLine &line = lines[i]; - if (line.feedrate > min_feedrate) time_stretch += line.time * (line.feedrate / min_feedrate - 1.f); - } - return time_stretch; - } - - // Slow down all adjustable lines down to min_feedrate. - // Slowdown to min_feedrate shall be allowed for this extruder's material. - // Used by non-proportional slow down. - void slow_down_to_feedrate(float min_feedrate) - { - assert(this->slow_down_min_speed < min_feedrate + EPSILON); - for (size_t i = 0; i < n_lines_adjustable; ++i) { - CoolingLine &line = lines[i]; - if (line.feedrate > min_feedrate) { - line.time *= std::max(1.f, line.feedrate / min_feedrate); - line.feedrate = min_feedrate; - line.slowdown = true; - } - } - } - - // Extruder, for which the G-code will be adjusted. - unsigned int extruder_id = 0; - // Is the cooling slow down logic enabled for this extruder's material? - bool cooling_slow_down_enabled = false; - // Slow down the print down to slow_down_min_speed if the total layer time is below slow_down_layer_time. - float slow_down_layer_time = 0.f; - // Minimum print speed allowed for this extruder. - float slow_down_min_speed = 0.f; - - // Parsed lines. - std::vector lines; - // The following two values are set by sort_lines_by_decreasing_feedrate(): - // Number of adjustable lines, at the start of lines. - size_t n_lines_adjustable = 0; - // Non-adjustable time of lines starting with n_lines_adjustable. - float time_non_adjustable = 0; - // Current total time for this extruder. - float time_total = 0; - // Maximum time for this extruder, when the maximum slow down is applied. - float time_maximum = 0; - - // Temporaries for processing the slow down. Both thresholds go from 0 to n_lines_adjustable. - size_t idx_line_begin = 0; - size_t idx_line_end = 0; -}; // A standalone G-code filter, to control cooling of the print. // The G-code is processed per layer. Once a layer is collected, fan start / stop commands are edited // and the print is modified to stretch over a minimum layer time. @@ -227,29 +25,16 @@ public: CoolingBuffer(GCode &gcodegen); void reset(const Vec3d &position); void set_current_extruder(unsigned int extruder_id) { m_current_extruder = extruder_id; } - std::string process_layer(std::string && gcode, - const size_t layer_id, - SmoothCalculator & smooth_calculator, - std::vector &per_extruder_adjustments, - const std::vector & object_label, - const bool flush, - const bool spiral_vase); - - //BBS: - void apply_smooth_speed(SmoothCalculator &smooth_calculator, std::vector &extruder_adjustments, const int layer_id); - std::string apply_smooth_layer_time(std::string &&gcode, SmoothCalculator &smooth_calculator, std::vector &extruder_adjustments, const int layer_id, const bool smooth_layer_time); + std::string process_layer(std::string &&gcode, size_t layer_id, bool flush); private: CoolingBuffer& operator=(const CoolingBuffer&) = delete; - std::vector parse_layer_gcode(const std::string & gcode, - std::vector & current_pos, - const std::vector & object_label, - bool spiral_vase, - bool join_z_smooth) const; + std::vector parse_layer_gcode(const std::string &gcode, std::vector ¤t_pos) const; float calculate_layer_slowdown(std::vector &per_extruder_adjustments); // Apply slow down over G-code lines stored in per_extruder_adjustments, enable fan if needed. // Returns the adjusted G-code. std::string apply_layer_cooldown(const std::string &gcode, size_t layer_id, float layer_time, std::vector &per_extruder_adjustments); + // G-code snippet cached for the support layers preceding an object layer. std::string m_gcode; // Internal data. diff --git a/src/libslic3r/GCode/Smoothing.hpp b/src/libslic3r/GCode/Smoothing.hpp deleted file mode 100644 index 96e9997bb..000000000 --- a/src/libslic3r/GCode/Smoothing.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef slic3r_Smoothing_hpp_ -#define slic3r_Smoothing_hpp_ -#include "../libslic3r.h" - -#include - -namespace Slic3r { - -static const int guassian_window_size = 11; -static const int guassian_r = 2; -static const int guassian_stop_threshold = 5; -static const float guassian_layer_time_stop_threshold = 3.0; -// if the layer time longer than this threshold, ignore it -static const float layer_time_ignore_threshold = 30.0; -static const int max_steps_count = 1000; - -struct CoolingNode -{ - // extruder pos, line pos; - std::vector> outwall_line; - std::vector> innerwall_line; - float max_feedrate = 0; - float filter_feedrate = 0; - double rate = 1; -}; - -struct OutwallCollection -{ - int object_id; - std::map cooling_nodes; -}; - -class SmoothCalculator -{ - std::vector guassian_filter; - double filter_sum = .0f; - -public: - std::vector> layers_wall_collection; - std::vector layers_cooling_time; - std::vector>> objects_node_range; - - SmoothCalculator(const int print_size, const int objects_size) - { - guassian_filter_generator(); - objects_node_range.resize(objects_size); - layers_wall_collection.resize(print_size); - layers_cooling_time.resize(print_size); - } - - // guassian filter - double guassian_function(double x, double r) { - return exp(-x * x / (2 * r * r)) / (r * sqrt(2 * PI)); - } - - void guassian_filter_generator() { - double r = guassian_r; - int half_win_size = guassian_window_size / 2; - for (int start = -half_win_size; start <= half_win_size; ++start) { - double y = guassian_function(start, r); - filter_sum += y; - guassian_filter.push_back(y); - } - } - - void init_wall_collection(const int layer_id, const std::vector &object_label) - { - for (size_t object_idx = 0; object_idx < object_label.size(); ++object_idx) { - OutwallCollection object_level; - object_level.object_id = object_label[object_idx]; - layers_wall_collection[layer_id].push_back(object_level); - } - } - - void init_object_node_range() { - for (size_t object_id = 0; object_id < objects_node_range.size(); ++object_id) { - - for (size_t layer_id = 1; layer_id < layers_wall_collection.size(); ++layer_id) { - const OutwallCollection &each_object = layers_wall_collection[layer_id][object_id]; - auto it = each_object.cooling_nodes.begin(); - while (it != each_object.cooling_nodes.end()) { - if (objects_node_range[object_id].count(it->first) == 0) { - objects_node_range[object_id].emplace(it->first, std::pair(layer_id, layer_id)); - } else { - objects_node_range[object_id][it->first].second = layer_id; - } - it++; - } - } - } - } - - // filter the data - void layer_speed_filter(const int object_id, const int node_id) - { - int start_pos = guassian_filter.size() / 2; - // first layer don't need to be smoothed - int layer_id = objects_node_range[object_id][node_id].first; - int layer_end = objects_node_range[object_id][node_id].second; - - for (; layer_id <= layer_end; ++layer_id) { - if (layers_wall_collection[layer_id][object_id].cooling_nodes.count(node_id) == 0) - break; - - CoolingNode &node = layers_wall_collection[layer_id][object_id].cooling_nodes[node_id]; - - if (node.outwall_line.empty()) - continue; - - double conv_sum = 0; - for (int filter_pos_idx = 0; filter_pos_idx < guassian_filter.size(); ++filter_pos_idx) { - int remap_data_pos = layer_id - start_pos + filter_pos_idx; - - if (remap_data_pos < 1) - remap_data_pos = 1; - else if (remap_data_pos > layers_wall_collection.size() - 1) - remap_data_pos = layers_wall_collection.size() - 1; - - // some node may not start at layer 1 - double remap_data = node.filter_feedrate; - if (!layers_wall_collection[remap_data_pos][object_id].cooling_nodes[node_id].outwall_line.empty()) - remap_data = layers_wall_collection[remap_data_pos][object_id].cooling_nodes[node_id].filter_feedrate; - - conv_sum += guassian_filter[filter_pos_idx] * remap_data; - } - double filter_res = conv_sum / filter_sum; - if (filter_res < node.filter_feedrate) node.filter_feedrate = filter_res; - } - } - - bool speed_filter_continue(const int object_id, const int node_id) - { - int layer_id = objects_node_range[object_id][node_id].first; - int layer_end = objects_node_range[object_id][node_id].second; - - for (; layer_id < layer_end; ++layer_id) { - if (std::abs(layers_wall_collection[layer_id][object_id].cooling_nodes[node_id].outwall_line.empty())) - continue; - - if (std::abs(layers_wall_collection[layer_id][object_id].cooling_nodes[node_id].filter_feedrate - - layers_wall_collection[layer_id + 1][object_id].cooling_nodes[node_id].filter_feedrate) > - guassian_stop_threshold) - return true; - } - return false; - } - - void smooth_layer_speed() - { - init_object_node_range(); - - for (size_t obj_id = 0; obj_id < objects_node_range.size(); ++obj_id) { - auto it = objects_node_range[obj_id].begin(); - while (it != objects_node_range[obj_id].end()) { - int step_count = 0; - while (step_count < max_steps_count && speed_filter_continue(obj_id, it->first)) { - step_count++; - layer_speed_filter(obj_id, it->first); - } - it++; - } - } - } - - // filter the data - void filter_layer_time() - { - int start_pos = guassian_filter.size() / 2; - // first layer don't need to be smoothed - for (int layer_id = 1; layer_id < layers_cooling_time.size(); ++layer_id) { - if (layers_cooling_time[layer_id] > layer_time_ignore_threshold) - continue; - - double conv_sum = 0; - for (int filter_pos_idx = 0; filter_pos_idx < guassian_filter.size(); ++filter_pos_idx) { - int remap_data_pos = layer_id - start_pos + filter_pos_idx; - - if (remap_data_pos < 1) - remap_data_pos = 1; - else if (remap_data_pos > layers_cooling_time.size() - 1) - remap_data_pos = layers_cooling_time.size() - 1; - - // if the layer time big enough, surface defact will disappear - double data_temp = layers_cooling_time[remap_data_pos] > layer_time_ignore_threshold ? layer_time_ignore_threshold : layers_cooling_time[remap_data_pos]; - - conv_sum += guassian_filter[filter_pos_idx] * data_temp; - } - double filter_res = conv_sum / filter_sum; - filter_res = filter_res > layer_time_ignore_threshold ? layer_time_ignore_threshold : filter_res; - if (filter_res > layers_cooling_time[layer_id]) - layers_cooling_time[layer_id] = filter_res; - } - } - - bool layer_time_filter_continue() - { - for (int layer_id = 1; layer_id < layers_cooling_time.size() - 1; ++layer_id) { - double layer_time = layers_cooling_time[layer_id] > layer_time_ignore_threshold ? layer_time_ignore_threshold : layers_cooling_time[layer_id]; - double layer_time_cmp = layers_cooling_time[layer_id + 1] > layer_time_ignore_threshold ? layer_time_ignore_threshold : layers_cooling_time[layer_id + 1]; - - if (std::abs(layer_time - layer_time_cmp) > guassian_layer_time_stop_threshold) - return true; - } - return false; - } - - void smooth_layer_time() - { - int step_count = 0; - while (step_count < max_steps_count && layer_time_filter_continue()) { - step_count++; - filter_layer_time(); - } - } -}; - -} // namespace Slic3r - -#endif \ No newline at end of file diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index f18afd10e..026530198 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -5,9 +5,8 @@ #include "ShortestPath.hpp" #include "SVG.hpp" #include "BoundingBox.hpp" -#include "libslic3r/AABBTreeLines.hpp" + #include -static const int Continuitious_length = scale_(0.01); namespace Slic3r { @@ -199,7 +198,7 @@ void Layer::make_perimeters() if (layerms.size() == 1) { // optimization (*layerm)->fill_surfaces.surfaces.clear(); - (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons, region_id, this->loop_nodes); + (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces, &(*layerm)->fill_no_overlap_expolygons); (*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces); } else { SurfaceCollection new_slices; @@ -223,7 +222,7 @@ void Layer::make_perimeters() SurfaceCollection fill_surfaces; //BBS ExPolygons fill_no_overlap; - layerm_config->make_perimeters(new_slices, &fill_surfaces, &fill_no_overlap, region_id, this->loop_nodes); + layerm_config->make_perimeters(new_slices, &fill_surfaces, &fill_no_overlap); // assign fill_surfaces to each layer if (!fill_surfaces.surfaces.empty()) { @@ -238,127 +237,9 @@ void Layer::make_perimeters() } } } - BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done"; } -//BBS: use aabbtree to get distance -class ContinuitiousDistancer -{ - std::vector lines; - AABBTreeIndirect::Tree<2, double> tree; - -public: - ContinuitiousDistancer(const std::pair node_expolygon) - { - if (node_expolygon.second) { - for (const auto &line : node_expolygon.first.lines()) - lines.emplace_back(line.a.cast(), line.b.cast()); - } else { - Polyline pl; - pl.append(node_expolygon.first.contour.points); - for (const auto &line : pl.lines()) - lines.emplace_back(line.a.cast(), line.b.cast()); - } - tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines); - } - - float distance_from_perimeter(const Vec2f &point) const - { - Vec2d p = point.cast(); - size_t hit_idx_out{}; - Vec2d hit_point_out = Vec2d::Zero(); - auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out); - if (distance < 0) { - return std::numeric_limits::max(); - } - - distance = sqrt(distance); - const Linef &line = lines[hit_idx_out]; - Vec2d v1 = line.b - line.a; - Vec2d v2 = p - line.a; - if ((v1.x() * v2.y()) - (v1.y() * v2.x()) > 0.0) { distance *= -1; } - return distance; - } -}; - -void Layer::calculate_perimeter_continuity(std::vector &prev_nodes) { - for (size_t node_pos = 0; node_pos < loop_nodes.size(); ++node_pos) { - LoopNode &node=loop_nodes[node_pos]; - double width = scale_(m_regions[node.region_id]->region().config().outer_wall_line_width) * 1.2; - ContinuitiousDistancer node_distancer(node.exp); - for (size_t prev_pos = 0; prev_pos < prev_nodes.size(); ++prev_pos) { - LoopNode &prev_node = prev_nodes[prev_pos]; - - // no overlap or has diff speed - if (!node.bbox.overlap(prev_node.bbox)) - continue; - - //calculate dist, checkout the continuity - Polyline continuitious_pl; - //check start pt - size_t start = 0; - bool conntiouitious_flag = false; - size_t end = prev_node.exp.first.contour.points.size() - 1; - - //if the countor is loop - if (prev_node.exp.second) { - //check first point - Point pt = prev_node.exp.first.contour.points.front(); - float dist = node_distancer.distance_from_perimeter(pt.cast()); - if (dist < width && dist > -width) - continuitious_pl.append_before(pt); - - for (; end >= 0; --end) { - if (continuitious_pl.length() >= Continuitious_length) { - node.lower_node_id.push_back(prev_node.node_id); - prev_node.upper_node_id.push_back(node.node_id); - conntiouitious_flag = true; - break; - } - - Point pt = prev_node.exp.first.contour.points[end]; - float dist = node_distancer.distance_from_perimeter(pt.cast()); - - if (dist < width && dist > -width) - continuitious_pl.append_before(pt); - else - break; - } - - if (conntiouitious_flag) continue; - } - - for (; start < end; ++start) { - Point pt = prev_node.exp.first.contour.points[start]; - float dist = node_distancer.distance_from_perimeter(pt.cast()); - - if (dist < width && dist > -width) { - continuitious_pl.append(pt); - continue; - } - - if (continuitious_pl.empty() || continuitious_pl.length() < Continuitious_length) { - continuitious_pl.clear(); - continue; - } - - node.lower_node_id.push_back(prev_node.node_id); - prev_node.upper_node_id.push_back(node.node_id); - continuitious_pl.clear(); - break; - - } - - if (continuitious_pl.length() >= Continuitious_length) { - node.lower_node_id.push_back(prev_node.node_id); - prev_node.upper_node_id.push_back(node.node_id); - } - } - } - -} - void Layer::export_region_slices_to_svg(const char *path) const { BoundingBox bbox; diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index ee55fb818..811eaf871 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -80,7 +80,7 @@ public: void slices_to_fill_surfaces_clipped(); void prepare_fill_surfaces(); //BBS - void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces, ExPolygons* fill_no_overlap, int region_id, std::vector &loop_nodes); + void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces, ExPolygons* fill_no_overlap); void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered); double infill_area_threshold() const; // Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer. @@ -155,7 +155,6 @@ public: // BBS ExPolygons loverhangs; BoundingBox loverhangs_bbox; - std::vector loop_nodes; size_t region_count() const { return m_regions.size(); } const LayerRegion* get_region(int idx) const { return m_regions[idx]; } LayerRegion* get_region(int idx) { return m_regions[idx]; } @@ -181,9 +180,6 @@ public: return false; } void make_perimeters(); - //BBS - void calculate_perimeter_continuity(std::vector &prev_nodes); - // Phony version of make_fills() without parameters for Perl integration only. void make_fills() { this->make_fills(nullptr, nullptr); } void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator = nullptr); diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index 35d47b9ca..363e1311c 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -64,7 +64,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped() } } -void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection *fill_surfaces, ExPolygons *fill_no_overlap, int region_id, std::vector &loop_nodes) +void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces, ExPolygons* fill_no_overlap) { this->perimeters.clear(); this->thin_fills.clear(); @@ -93,9 +93,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec &this->thin_fills, fill_surfaces, //BBS - fill_no_overlap, - region_id, - &loop_nodes + fill_no_overlap ); if (this->layer()->lower_layer != nullptr) diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 3e1e6a0ad..068fd672c 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -7,7 +7,6 @@ #include "Clipper2Utils.hpp" #include "Arachne/WallToolPaths.hpp" #include "Line.hpp" -#include "Layer.hpp" #include #include #include @@ -1148,7 +1147,6 @@ void PerimeterGenerator::process_classic() ExPolygons gaps; ExPolygons top_fills; ExPolygons fill_clip; - std::vector> outwall; if (loop_number >= 0) { // In case no perimeters are to be generated, loop_number will equal to -1. std::vector contours(loop_number+1); // depth => loops @@ -1274,23 +1272,6 @@ void PerimeterGenerator::process_classic() //BBS: save perimeter loop which use smaller width if (i == 0) { - //store outer wall - - //not loop - for (const ThickPolyline &polyline : thin_walls) { - ExPolygon contour_coll; - contour_coll.contour.append(polyline.points); - outwall.emplace_back(contour_coll, false); - } - - //loop - for (const ExPolygon &expolygon : offsets_with_smaller_width) { - outwall.emplace_back(expolygon, true); - } - for (const ExPolygon &expolygon : offsets) { - outwall.emplace_back(expolygon, true); - } - for (const ExPolygon& expolygon : offsets_with_smaller_width) { contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, fuzzify_contours, true)); if (!expolygon.holes.empty()) { @@ -1467,41 +1448,6 @@ void PerimeterGenerator::process_classic() } entities.entities = std::move( entities_reorder); } - - //BBS: add node for loops - if (!outwall.empty() && this->layer_id > 0) { - entities.loop_node_range.first = this->loop_nodes->size(); - if (outwall.size() == 1) { - LoopNode node; - node.node_id = this->loop_nodes->size(); - node.region_id = region_id; - node.perimeter_id = this->loops->entities.size(); - node.exp = outwall.front(); - node.bbox = get_extents(node.exp.first); - this->loop_nodes->push_back(node); - } else { - int entity_idx = 0; - for (std::pair &exp : outwall) { - LoopNode node; - node.node_id = this->loop_nodes->size(); - node.region_id = region_id; - node.perimeter_id = this->loops->entities.size(); - - for (; entity_idx < entities.entities.size(); ++entity_idx) { - if (exp.first.contains(entities.entities[entity_idx]->first_point())) { - node.loop_id=entity_idx; - node.exp=exp; - node.bbox = get_extents(node.exp.first); - this->loop_nodes->push_back(node); - break; - } - } - } - } - entities.loop_node_range.second = this->loop_nodes->size(); - } - - // append perimeters for this slice as a collection if (! entities.empty()) this->loops->append(entities); diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index c8ac9e1e4..709910a5b 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -40,9 +40,8 @@ public: std::pair m_lower_overhang_dist_boundary; std::pair m_external_overhang_dist_boundary; std::pair m_smaller_external_overhang_dist_boundary; - std::vector *loop_nodes; - int region_id; + PerimeterGenerator( // Input: const SurfaceCollection* slices, @@ -60,20 +59,14 @@ public: // Infills without the gap fills SurfaceCollection* fill_surfaces, //BBS - ExPolygons* fill_no_overlap, - int region_id, - std::vector *loop_nodes) + ExPolygons* fill_no_overlap) : slices(slices), upper_slices(nullptr), lower_slices(nullptr), layer_height(layer_height), layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow), overhang_flow(flow), solid_infill_flow(flow), config(config), object_config(object_config), print_config(print_config), m_spiral_vase(spiral_mode), - m_scaled_resolution(scaled(print_config->resolution.value > EPSILON ? print_config->resolution.value : EPSILON)), loops(loops), - gap_fill(gap_fill), - fill_surfaces(fill_surfaces), - fill_no_overlap(fill_no_overlap), - region_id(region_id), - loop_nodes(loop_nodes), + m_scaled_resolution(scaled(print_config->resolution.value > EPSILON ? print_config->resolution.value : EPSILON)), + loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces), fill_no_overlap(fill_no_overlap), m_ext_mm3_per_mm(-1), m_mm3_per_mm(-1), m_mm3_per_mm_overhang(-1), m_ext_mm3_per_mm_smaller_width(-1) {} diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 08a0355f8..684841755 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -847,8 +847,7 @@ static std::vector s_Preset_print_options { "seam_gap", "wipe_speed", "top_solid_infill_flow_ratio", "initial_layer_flow_ratio", "default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk", "travel_jerk", "filter_out_gap_fill", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", - "small_perimeter_speed", "small_perimeter_threshold", "z_direction_outwall_speed_continuous", - "layer_time_smoothing", + "small_perimeter_speed", "small_perimeter_threshold", // calib "print_flow_ratio", //Orca diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 30fee08bd..2d5168e36 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -505,7 +505,7 @@ private: // BBS SupportNecessaryType is_support_necessary(); - void merge_layer_node(const size_t layer_id, int &max_merged_id, std::map>> &node_record); + // XYZ in scaled coordinates Vec3crd m_size; double m_max_z; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b818cf27a..61f787470 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -573,20 +573,6 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); - def = this->add("z_direction_outwall_speed_continuous", coBool); - def->label = L("Smoothing wall speed in z direction(experimental)"); - def->category = L("Quality"); - def->tooltip = L("Smoothing outwall speed in z direction to get better surface quality. Print time will increases. It only works when the cooling function is turned on."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(true)); - - def = this->add("layer_time_smoothing", coBool); - def->label = L("Layer time smoothing(experimental)"); - def->category = L("Quality"); - def->tooltip = L("Smoothing layer time in z direction to get better surface quality. Print time will increases. It only works when the cooling function is turned on."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); - def = this->add("max_travel_detour_distance", coFloatOrPercent); def->label = L("Avoid crossing wall - Max detour length"); def->category = L("Quality"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 866b70789..7f1a46d7f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -992,8 +992,6 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( //BBS ((ConfigOptionInts, additional_cooling_fan_speed)) ((ConfigOptionBool, reduce_crossing_wall)) - ((ConfigOptionBool, z_direction_outwall_speed_continuous)) - ((ConfigOptionBool, layer_time_smoothing)) ((ConfigOptionFloatOrPercent, max_travel_detour_distance)) ((ConfigOptionPoints, printable_area)) //BBS: add bed_exclude_area diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index df4ce0666..1755d866d 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -129,67 +129,6 @@ std::vector> PrintObject::all_regions( return out; } -void PrintObject::merge_layer_node(const size_t layer_id, int &max_merged_id, std::map>> &node_record) -{ - Layer *this_layer = m_layers[layer_id]; - std::vector &loop_nodes = this_layer->loop_nodes; - for (size_t idx = 0; idx < loop_nodes.size(); ++idx) { - //new cool node - if (loop_nodes[idx].lower_node_id.empty()) { - max_merged_id++; - loop_nodes[idx].merged_id = max_merged_id; - std::vector> node_pos; - node_pos.emplace_back(layer_id, idx); - node_record.emplace(max_merged_id, node_pos); - continue; - } - - //it should finds key in map - if (loop_nodes[idx].lower_node_id.size() == 1) { - loop_nodes[idx].merged_id = m_layers[layer_id - 1]->loop_nodes[loop_nodes[idx].lower_node_id.front()].merged_id; - node_record[loop_nodes[idx].merged_id].emplace_back(layer_id, idx); - continue; - } - - //min index - int min_merged_id = -1; - std::vector appear_id; - for (size_t lower_idx = 0; lower_idx < loop_nodes[idx].lower_node_id.size(); ++lower_idx) { - int id = m_layers[layer_id - 1]->loop_nodes[loop_nodes[idx].lower_node_id[lower_idx]].merged_id; - if (min_merged_id == -1 || min_merged_id > id) - min_merged_id = id; - appear_id.push_back(id); - } - - loop_nodes[idx].merged_id = min_merged_id; - node_record[min_merged_id].emplace_back(layer_id, idx); - - //update other node merged id - for (size_t appear_node_idx = 0; appear_node_idx < appear_id.size(); ++appear_node_idx) { - if (appear_id[appear_node_idx] == min_merged_id) - continue; - - auto it = node_record.find(appear_id[appear_node_idx]); - //protect - if (it == node_record.end()) - continue; - - std::vector> &appear_node_pos = it->second; - - for (size_t node_idx = 0; node_idx < appear_node_pos.size(); ++node_idx) { - int node_layer = appear_node_pos[node_idx].first; - int node_pos = appear_node_pos[node_idx].second; - - LoopNode &node = m_layers[node_layer]->loop_nodes[node_pos]; - - node.merged_id = min_merged_id; - node_record[min_merged_id].emplace_back(node_layer, node_pos); - } - node_record.erase(it); - } - } -} - // 1) Merges typed region slices into stInternal type. // 2) Increases an "extra perimeters" counter at region slices where needed. // 3) Generates perimeters, gap fills and fill regions (fill regions of type stInternal). @@ -297,33 +236,6 @@ void PrintObject::make_perimeters() m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end"; - // BBS: get continuity of nodes - if (this->config().wall_generator == PerimeterGeneratorType::Classic) { - BOOST_LOG_TRIVIAL(debug) << "Calculating perimeters connection in parallel - start"; - tbb::parallel_for(tbb::blocked_range(0, m_layers.size()), [this](const tbb::blocked_range &range) { - for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { - m_print->throw_if_canceled(); - if (layer_idx > 1) { - Layer &prev_layer = *m_layers[layer_idx - 1]; - m_layers[layer_idx]->calculate_perimeter_continuity(m_layers[layer_idx - 1]->loop_nodes); - } - } - }); - - m_print->throw_if_canceled(); - BOOST_LOG_TRIVIAL(debug) << "Calculating perimeters connection in parallel - end"; - - BOOST_LOG_TRIVIAL(debug) << "Calculating cooling nodes - start"; - - int max_merged_id = -1; - std::map>> node_record; - for (size_t layer_idx = 1; layer_idx < m_layers.size(); ++layer_idx) { - m_print->throw_if_canceled(); - merge_layer_node(layer_idx, max_merged_id, node_record); - } - m_print->throw_if_canceled(); - BOOST_LOG_TRIVIAL(debug) << "Calculating cooling nodes - end"; - } this->set_done(posPerimeters); } @@ -1005,9 +917,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "sparse_infill_speed" || opt_key == "inner_wall_speed" || opt_key == "internal_solid_infill_speed" - || opt_key == "top_surface_speed" - || opt_key == "z_direction_outwall_speed_continuous" - || opt_key == "layer_time_smoothing") { + || opt_key == "top_surface_speed") { invalidated |= m_print->invalidate_step(psGCodeExport); } else if ( opt_key == "flush_into_infill" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 27bc1274f..8abea5938 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -312,14 +312,6 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con is_msg_dlg_already_exist = false; } - // arachen not support wall generator - bool have_arachne = config->opt_enum("wall_generator") == PerimeterGeneratorType::Arachne; - if (have_arachne) { - DynamicPrintConfig new_conf = *config; - new_conf.set_key_value("z_direction_outwall_speed_continuous", new ConfigOptionBool(false)); - apply(config, &new_conf); - } - double sparse_infill_density = config->option("sparse_infill_density")->value; auto timelapse_type = config->opt_enum("timelapse_type"); @@ -726,10 +718,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_line(el, has_fuzzy_skin); bool have_arachne = config->opt_enum("wall_generator") == PerimeterGeneratorType::Arachne; - for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "min_feature_size", "min_bead_width", "wall_distribution_count"}) + for (auto el : { "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", + "min_feature_size", "min_bead_width", "wall_distribution_count" }) toggle_line(el, have_arachne); toggle_field("detect_thin_wall", !have_arachne); - toggle_field("z_direction_outwall_speed_continuous", !have_arachne); PresetBundle *preset_bundle = wxGetApp().preset_bundle; // OrcaSlicer diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 10f147e94..09e557581 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1978,8 +1978,6 @@ void TabPrint::build() optgroup->append_single_option_line("smooth_coefficient","parameter/quality-advance-settings"); optgroup->append_single_option_line("reduce_crossing_wall","parameter/quality-advance-settings"); optgroup->append_single_option_line("max_travel_detour_distance","parameter/quality-advance-settings"); - optgroup->append_single_option_line("z_direction_outwall_speed_continuous"); - optgroup->append_single_option_line("layer_time_smoothing"); page = add_options_page(L("Strength"), "empty"); optgroup = page->new_optgroup(L("Walls"), L"param_wall");