diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index 775b3e8b42..2545ed2b42 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -2874,6 +2874,55 @@ bool FillRectilinear::fill_surface_by_lines(const Surface *surface, const FillPa traverse_graph_generate_polylines(poly_with_offset, params, segs, this->has_consistent_pattern(), polylines_out); } + // Check if we're in flow calibration mode + bool is_flow_calibration = params.extrusion_role == erTopSolidInfill && + this->print_object_config->has("calib_flowrate_topinfill_special_order") && + this->print_object_config->option("calib_flowrate_topinfill_special_order")->getBool() && + params.monotonic; + + if (is_flow_calibration && !polylines_out.empty()) { + // Get the range of newly added polylines + auto start_it = polylines_out.begin() + n_polylines_out_initial; + auto end_it = polylines_out.end(); + + if (start_it != end_it) { + // 1) For sure sort lines by X of the midpoint so lines are ordered left-to-right across objects. + std::stable_sort(start_it, end_it, [](const Polyline& a, const Polyline& b) { + // Midpoint X as average of endpoints + auto ax = (int64_t) a.points.front().x() + (int64_t) a.points.back().x(); + auto bx = (int64_t) b.points.front().x() + (int64_t) b.points.back().x(); + if (ax == bx) { + // Tiebreaker by midpoint Y, then by start X to stabilize order + auto ay = (int64_t) a.points.front().y() + (int64_t) a.points.back().y(); + auto by = (int64_t) b.points.front().y() + (int64_t) b.points.back().y(); + if (ay == by) + return a.points.front().x() < b.points.front().x(); + return ay < by; + } + return ax < bx; + }); + + // 2) Normalize direction: make every polyline point "up-right". + for (auto it = start_it; it != end_it; ++it) { + if (it->points.empty()) + continue; + const Point& p0 = it->points.front(); + const Point& p1 = it->points.back(); + auto vec = (p1 - p0).template cast(); + double dir = vec.x() + vec.y(); + if (dir < 0.0) { + std::reverse(it->points.begin(), it->points.end()); + } + } + + // 3) Split into halves and reverse order of the 2nd half so it prints towards the 1st half. + size_t total = std::distance(start_it, end_it); + size_t mid = total / 2; + auto mid_it = start_it + mid; + std::reverse(mid_it, end_it); + } + } + #ifdef SLIC3R_DEBUG { { diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index cc67ee11fd..56bdba5d04 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -12443,7 +12443,8 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i auto cur_flowrate = filament_config->option("filament_flow_ratio")->get_at(0); Flow infill_flow = Flow(nozzle_diameter * 1.2f, layer_height, nozzle_diameter); - double filament_max_volumetric_speed = filament_config->option("filament_max_volumetric_speed")->get_at(0); + // for sure, use max volumetric flow of 75% of the current setting to prevent underflow near the limit of the nozzle + double filament_max_volumetric_speed = filament_config->option("filament_max_volumetric_speed")->get_at(0) * 0.75; double max_infill_speed; if (linear) max_infill_speed = filament_max_volumetric_speed / @@ -12453,6 +12454,17 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i double internal_solid_speed = std::floor(std::min(print_config->opt_float("internal_solid_infill_speed"), max_infill_speed)); double top_surface_speed = std::floor(std::min(print_config->opt_float("top_surface_speed"), max_infill_speed)); + // disable z-hop and retract wipe + filament_config->set_key_value("filament_z_hop", new ConfigOptionFloatsNullable{ConfigOptionFloatsNullable::nil_value()}); + filament_config->set_key_value("filament_wipe_distance", new ConfigOptionFloatsNullable{ConfigOptionFloatsNullable::nil_value()}); + filament_config->set_key_value("filament_retract_lift_enforce", new ConfigOptionEnumsGenericNullable{ConfigOptionEnumsGenericNullable::nil_value()}); + filament_config->set_key_value("filament_z_hop_types", new ConfigOptionEnumsGenericNullable{ConfigOptionEnumsGenericNullable::nil_value()}); + + printerConfig->set_key_value("z_hop", new ConfigOptionFloats{0.0f}); + printerConfig->set_key_value("wipe_distance", new ConfigOptionFloats{0.0f}); + printerConfig->set_key_value("retract_lift_enforce", new ConfigOptionEnumsGeneric{RetractLiftEnforceType::rletAllSurfaces}); + printerConfig->set_key_value("z_hop_types", new ConfigOptionEnumsGeneric{ZHopType::zhtNormal}); + // adjust parameters for (auto _obj : objects) { _obj->ensure_on_bed(); @@ -12472,7 +12484,7 @@ void adjust_settings_for_flowrate_calib(ModelObjectPtrs& objects, bool linear, i _obj->config.set_key_value("sparse_infill_pattern", new ConfigOptionEnum(ipRectilinear)); _obj->config.set_key_value("top_surface_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false)); _obj->config.set_key_value("internal_solid_infill_line_width", new ConfigOptionFloatOrPercent(nozzle_diameter * 1.2f, false)); - _obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum(ipArchimedeanChords)); + _obj->config.set_key_value("top_surface_pattern", new ConfigOptionEnum(ipMonotonicLine)); _obj->config.set_key_value("top_solid_infill_flow_ratio", new ConfigOptionFloat(1.0f)); _obj->config.set_key_value("infill_direction", new ConfigOptionFloat(45)); _obj->config.set_key_value("solid_infill_direction", new ConfigOptionFloat(135));