diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp index 5c24cd71c..db38a7462 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.cpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.cpp @@ -505,8 +505,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( .speed_override(100); writer.set_initial_position(xy(0.f, 0.f)) // Always move to the starting position - .travel(cleaning_box.ld, 7200) - .set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming. + .travel(cleaning_box.ld, 7200); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(750); // Increase the extruder driver current to allow fast ramming. for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { unsigned int tool = tools[idx_tool]; @@ -533,8 +534,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( // in the output gcode - we should not remember emitting them (we will output them twice in the worst case) // Reset the extruder current to a normal value. - writer.set_extruder_trimpot(550) - .feedrate(6000) + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); + writer.feedrate(6000) .flush_planner_queue() .reset_extruder() .append("; CP PRIMING END\n" @@ -607,7 +609,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo writer.set_initial_position(initial_position, m_wipe_tower_width, m_wipe_tower_depth, m_internal_rotation); // Increase the extruder driver current to allow fast ramming. - writer.set_extruder_trimpot(750); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. if (tool != (unsigned int)-1){ // This is not the last change. @@ -635,8 +638,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo } } - writer.set_extruder_trimpot(550) // Reset the extruder current to a normal value. - .feedrate(6000) + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); // Reset the extruder current to a normal value. + writer.feedrate(6000) .flush_planner_queue() .reset_extruder() .append("; CP TOOLCHANGE END\n" @@ -916,12 +920,10 @@ void WipeTowerPrusaMM::toolchange_Load( .resume_preview(); // Reset the extruder current to the normal value. - writer.set_extruder_trimpot(550); + if (m_set_extruder_trimpot) + writer.set_extruder_trimpot(550); } - - - // Wipe the newly loaded filament until the end of the assigned wipe area. void WipeTowerPrusaMM::toolchange_Wipe( PrusaMultiMaterial::Writer &writer, diff --git a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp index 06625d189..c0aeee3ae 100644 --- a/src/libslic3r/GCode/WipeTowerPrusaMM.hpp +++ b/src/libslic3r/GCode/WipeTowerPrusaMM.hpp @@ -44,7 +44,8 @@ public: // width -- width of wipe tower in mm ( default 60 mm - leave as it is ) // wipe_area -- space available for one toolchange in mm WipeTowerPrusaMM(float x, float y, float width, float rotation_angle, float cooling_tube_retraction, - float cooling_tube_length, float parking_pos_retraction, float extra_loading_move, float bridging, + float cooling_tube_length, float parking_pos_retraction, float extra_loading_move, + float bridging, bool set_extruder_trimpot, const std::vector<std::vector<float>>& wiping_matrix, unsigned int initial_tool) : m_wipe_tower_pos(x, y), m_wipe_tower_width(width), @@ -57,6 +58,7 @@ public: m_parking_pos_retraction(parking_pos_retraction), m_extra_loading_move(extra_loading_move), m_bridging(bridging), + m_set_extruder_trimpot(set_extruder_trimpot), m_current_tool(initial_tool), wipe_volumes(wiping_matrix) {} @@ -212,6 +214,7 @@ private: float m_parking_pos_retraction = 0.f; float m_extra_loading_move = 0.f; float m_bridging = 0.f; + bool m_set_extruder_trimpot = false; bool m_adhesion = true; float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio; // Width of an extrusion line, also a perimeter spacing for 100% infill. diff --git a/src/libslic3r/Line.cpp b/src/libslic3r/Line.cpp index 35cfa2b76..02f1cb7c2 100644 --- a/src/libslic3r/Line.cpp +++ b/src/libslic3r/Line.cpp @@ -34,23 +34,22 @@ bool Line::intersection_infinite(const Line &other, Point* point) const return true; } -/* distance to the closest point of line */ -double Line::distance_to(const Point &point) const +// Distance to the closest point of line. +double Line::distance_to_squared(const Point &point, const Point &a, const Point &b) { - const Line &line = *this; - const Vec2d v = (line.b - line.a).cast<double>(); - const Vec2d va = (point - line.a).cast<double>(); + const Vec2d v = (b - a).cast<double>(); + const Vec2d va = (point - a).cast<double>(); const double l2 = v.squaredNorm(); // avoid a sqrt if (l2 == 0.0) - // line.a == line.b case - return va.norm(); - // Consider the line extending the segment, parameterized as line.a + t (line.b - line.a). + // a == b case + return va.squaredNorm(); + // Consider the line extending the segment, parameterized as a + t (b - a). // We find projection of this point onto the line. - // It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2 + // It falls where t = [(this-a) . (b-a)] / |b-a|^2 const double t = va.dot(v) / l2; - if (t < 0.0) return va.norm(); // beyond the 'a' end of the segment - else if (t > 1.0) return (point - line.b).cast<double>().norm(); // beyond the 'b' end of the segment - return (t * v - va).norm(); + if (t < 0.0) return va.squaredNorm(); // beyond the 'a' end of the segment + else if (t > 1.0) return (point - b).cast<double>().squaredNorm(); // beyond the 'b' end of the segment + return (t * v - va).squaredNorm(); } double Line::perp_distance_to(const Point &point) const diff --git a/src/libslic3r/Line.hpp b/src/libslic3r/Line.hpp index 36e02247c..559ca946a 100644 --- a/src/libslic3r/Line.hpp +++ b/src/libslic3r/Line.hpp @@ -31,7 +31,8 @@ public: Point midpoint() const { return (this->a + this->b) / 2; } bool intersection_infinite(const Line &other, Point* point) const; bool operator==(const Line &rhs) const { return this->a == rhs.a && this->b == rhs.b; } - double distance_to(const Point &point) const; + double distance_to_squared(const Point &point) const { return distance_to_squared(point, this->a, this->b); } + double distance_to(const Point &point) const { return distance_to(point, this->a, this->b); } double perp_distance_to(const Point &point) const; bool parallel_to(double angle) const; bool parallel_to(const Line &line) const { return this->parallel_to(line.direction()); } @@ -43,6 +44,9 @@ public: bool intersection(const Line& line, Point* intersection) const; double ccw(const Point& point) const { return point.ccw(*this); } + static double distance_to_squared(const Point &point, const Point &a, const Point &b); + static double distance_to(const Point &point, const Point &a, const Point &b) { return sqrt(distance_to_squared(point, a, b)); } + Point a; Point b; }; diff --git a/src/libslic3r/MultiPoint.cpp b/src/libslic3r/MultiPoint.cpp index 93c63c4cf..795ee38c2 100644 --- a/src/libslic3r/MultiPoint.cpp +++ b/src/libslic3r/MultiPoint.cpp @@ -162,45 +162,51 @@ bool MultiPoint::first_intersection(const Line& line, Point* intersection) const return found; } -//FIXME This is very inefficient in term of memory use. -// The recursive algorithm shall run in place, not allocating temporary data in each recursion. -Points -MultiPoint::_douglas_peucker(const Points &points, const double tolerance) +std::vector<Point> MultiPoint::_douglas_peucker(const std::vector<Point>& pts, const double tolerance) { - assert(points.size() >= 2); - Points results; - double dmax = 0; - size_t index = 0; - Line full(points.front(), points.back()); - for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { - // we use shortest distance, not perpendicular distance - double d = full.distance_to(*it); - if (d > dmax) { - index = it - points.begin(); - dmax = d; + std::vector<Point> result_pts; + if (! pts.empty()) { + const Point *anchor = &pts.front(); + size_t anchor_idx = 0; + const Point *floater = &pts.back(); + size_t floater_idx = pts.size() - 1; + result_pts.reserve(pts.size()); + result_pts.emplace_back(*anchor); + if (anchor_idx != floater_idx) { + assert(pts.size() > 1); + std::vector<size_t> dpStack; + dpStack.reserve(pts.size()); + dpStack.emplace_back(floater_idx); + for (;;) { + double max_distSq = 0.0; + size_t furthest_idx = anchor_idx; + // find point furthest from line seg created by (anchor, floater) and note it + for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) { + double dist = Line::distance_to_squared(pts[i], *anchor, *floater); + if (dist > max_distSq) { + max_distSq = dist; + furthest_idx = i; + } + } + // remove point if less than tolerance + if (max_distSq <= tolerance) { + result_pts.emplace_back(*floater); + anchor_idx = floater_idx; + anchor = floater; + assert(dpStack.back() == floater_idx); + dpStack.pop_back(); + if (dpStack.empty()) + break; + floater_idx = dpStack.back(); + } else { + floater_idx = furthest_idx; + dpStack.emplace_back(floater_idx); + } + floater = &pts[floater_idx]; + } } } - if (dmax >= tolerance) { - Points dp0; - dp0.reserve(index + 1); - dp0.insert(dp0.end(), points.begin(), points.begin() + index + 1); - // Recursive call. - Points dp1 = MultiPoint::_douglas_peucker(dp0, tolerance); - results.reserve(results.size() + dp1.size() - 1); - results.insert(results.end(), dp1.begin(), dp1.end() - 1); - - dp0.clear(); - dp0.reserve(points.size() - index); - dp0.insert(dp0.end(), points.begin() + index, points.end()); - // Recursive call. - dp1 = MultiPoint::_douglas_peucker(dp0, tolerance); - results.reserve(results.size() + dp1.size()); - results.insert(results.end(), dp1.begin(), dp1.end()); - } else { - results.push_back(points.front()); - results.push_back(points.back()); - } - return results; + return result_pts; } // Visivalingam simplification algorithm https://github.com/slic3r/Slic3r/pull/3825 diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 77cf9c0f6..e3382573c 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -213,6 +213,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option || opt_key == "filament_cooling_final_speed" || opt_key == "filament_ramming_parameters" || opt_key == "gcode_flavor" + || opt_key == "high_current_on_filament_swap" || opt_key == "infill_first" || opt_key == "single_extruder_multi_material" || opt_key == "spiral_vase" @@ -1768,7 +1769,8 @@ void Print::_make_wipe_tower() float(m_config.wipe_tower_width.value), float(m_config.wipe_tower_rotation_angle.value), float(m_config.cooling_tube_retraction.value), float(m_config.cooling_tube_length.value), float(m_config.parking_pos_retraction.value), - float(m_config.extra_loading_move.value), float(m_config.wipe_tower_bridging), wipe_volumes, + float(m_config.extra_loading_move.value), float(m_config.wipe_tower_bridging), + m_config.high_current_on_filament_swap.value, wipe_volumes, m_wipe_tower_data.tool_ordering.first_extruder()); //wipe_tower.set_retract(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8a564b6b5..f24d40fed 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -925,6 +925,15 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->default_value = new ConfigOptionEnum<GCodeFlavor>(gcfRepRap); + def = this->add("high_current_on_filament_swap", coBool); + def->label = L("High extruder current on filament swap"); + def->tooltip = L("It may be beneficial to increase the extruder motor current during the filament exchange" + " sequence to allow for rapid ramming feed rates and to overcome resistance when loading" + " a filament with an ugly shaped tip."); + def->cli = "high-current-on-filament-swap!"; + def->mode = comExpert; + def->default_value = new ConfigOptionBool(0); + def = this->add("infill_acceleration", coFloat); def->label = L("Infill"); def->tooltip = L("This is the acceleration your printer will use for infill. Set zero to disable " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 1949a8ac8..487e35bf2 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -627,6 +627,7 @@ public: ConfigOptionBool variable_layer_height; ConfigOptionFloat cooling_tube_retraction; ConfigOptionFloat cooling_tube_length; + ConfigOptionBool high_current_on_filament_swap; ConfigOptionFloat parking_pos_retraction; ConfigOptionBool remaining_times; ConfigOptionBool silent_mode; @@ -695,6 +696,7 @@ protected: OPT_PTR(variable_layer_height); OPT_PTR(cooling_tube_retraction); OPT_PTR(cooling_tube_length); + OPT_PTR(high_current_on_filament_swap); OPT_PTR(parking_pos_retraction); OPT_PTR(remaining_times); OPT_PTR(silent_mode); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 772d930aa..fdf950ee5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -385,11 +385,13 @@ void PrintObject::generate_support_material() this->_generate_support_material(); m_print->throw_if_canceled(); } else { +#if 0 // Printing without supports. Empty layer means some objects or object parts are levitating, // therefore they cannot be printed without supports. for (const Layer *layer : m_layers) if (layer->empty()) throw std::runtime_error("Levitating objects cannot be printed without supports."); +#endif } this->set_done(posSupportMaterial); } diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 639f70cf7..90372ecd4 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -366,7 +366,8 @@ const std::vector<std::string>& Preset::printer_options() "host_type", "print_host", "printhost_apikey", "printhost_cafile", "single_extruder_multi_material", "start_gcode", "end_gcode", "before_layer_gcode", "layer_gcode", "toolchange_gcode", "between_objects_gcode", "printer_vendor", "printer_model", "printer_variant", "printer_notes", "cooling_tube_retraction", - "cooling_tube_length", "parking_pos_retraction", "extra_loading_move", "max_print_height", "default_print_profile", "inherits", + "cooling_tube_length", "high_current_on_filament_swap", "parking_pos_retraction", "extra_loading_move", "max_print_height", + "default_print_profile", "inherits", "remaining_times", "silent_mode", "machine_max_acceleration_extruding", "machine_max_acceleration_retracting", "machine_max_acceleration_x", "machine_max_acceleration_y", "machine_max_acceleration_z", "machine_max_acceleration_e", "machine_max_feedrate_x", "machine_max_feedrate_y", "machine_max_feedrate_z", "machine_max_feedrate_e", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6372f7321..30d83d845 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2041,6 +2041,7 @@ void TabPrinter::build_extruder_pages() optgroup->append_single_option_line("cooling_tube_length"); optgroup->append_single_option_line("parking_pos_retraction"); optgroup->append_single_option_line("extra_loading_move"); + optgroup->append_single_option_line("high_current_on_filament_swap"); m_pages.insert(m_pages.end() - n_after_single_extruder_MM, page); m_has_single_extruder_MM_page = true; }