diff --git a/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json b/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json index 4ebec9633..310b3b4bc 100644 --- a/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json +++ b/resources/profiles/BBL/machine/fdm_bbl_3dp_001_common.json @@ -111,7 +111,8 @@ "0.08" ], "printable_height": "250", - "extruder_clearance_radius": "32", + "extruder_clearance_radius": "57", + "extruder_clearance_max_radius": "68", "extruder_clearance_height_to_rod": "36", "extruder_clearance_height_to_lid": "140", "nozzle_volume": "118", diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index d9a510a45..09b325365 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -52,6 +52,7 @@ struct ArrangePolygon { //BBS: add locked_plate to indicate whether it is in the locked plate int locked_plate{ -1 }; bool is_virt_object{ false }; + bool is_extrusion_cali_object{ false }; bool is_wipe_tower{false}; //BBS: add row/col for sudoku-style layout int row{0}; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 862f35ad2..9daf935e2 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -759,7 +759,7 @@ static std::vector s_Preset_printer_options { "printer_technology", "printable_area", "bed_exclude_area", "gcode_flavor", "single_extruder_multi_material", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "layer_change_gcode", "change_filament_gcode", - "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", + "printer_model", "printer_variant", "printable_height", "extruder_clearance_radius", "extruder_clearance_max_radius","extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "default_print_profile", "inherits", "silent_mode", // BBS diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 2eadc0cd6..1ab618b65 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -80,6 +80,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid", "extruder_clearance_radius", + "extruder_clearance_max_radius", "extruder_colour", "extruder_offset", "filament_flow_ratio", @@ -389,6 +390,8 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print const PrintInstance *print_instance; BoundingBox bounding_box; Polygon hull_polygon; + int index; + double arrange_score; }; std::vector print_instance_with_bounding_box; { @@ -480,22 +483,71 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print } } - //sort the print instance + // calc sort order + auto bed_points = get_bed_shape(print_config); + float bed_width = bed_points[1].x() - bed_points[0].x(); + // 如果扩大以后的多边形的距离小于这个值,就需要严格保证从左到右的打印顺序,否则会撞工具头右侧 + float unsafe_dist = scale_(print_config.extruder_clearance_max_radius.value - print_config.extruder_clearance_radius.value); + std::vector left_right_pair; // pairs in this vector must strictly obey the left-right order + for (size_t i = 0; i < print_instance_with_bounding_box.size();i++) { + auto &inst = print_instance_with_bounding_box[i]; + inst.index = i; + Point pt = inst.bounding_box.center(); + inst.arrange_score = pt.x() / 2 + pt.y(); // we prefer print row-by-row, so cost on x-direction is smaller + } + for (size_t i = 0; i < print_instance_with_bounding_box.size(); i++) { + auto &inst = print_instance_with_bounding_box[i]; + for (size_t j = 0; j < print_instance_with_bounding_box.size(); j++) { + if (j != i) { + auto &l = print_instance_with_bounding_box[i]; + auto &r = print_instance_with_bounding_box[j]; + auto ly1 = l.bounding_box.min.y(); + auto ly2 = l.bounding_box.max.y(); + auto ry1 = r.bounding_box.min.y(); + auto ry2 = r.bounding_box.max.y(); + auto lx1 = l.bounding_box.min.x(); + auto rx1 = r.bounding_box.min.x(); + auto lx2 = l.bounding_box.max.x(); + auto rx2 = r.bounding_box.max.x(); + auto inter_min = std::max(ly1, ry1); + auto inter_max = std::min(ly2, ry2); + auto inter_y = inter_max - inter_min; + inter_min = std::max(lx1, rx1); + inter_max = std::min(lx2, rx2); + auto inter_x = inter_max - inter_min; + + // 如果y方向有重合,说明两个物体在一行,应该先打左边的物体,即先比较二者的x坐标。 + if (inter_y > 0) { + if (std::max(rx1 - lx2, lx1 - rx2) < unsafe_dist) { + std::string dir = "left"; + if (lx1 > rx1) { + left_right_pair.emplace_back(j, i); + print_instance_with_bounding_box[i].arrange_score = std::max(inst.arrange_score, r.arrange_score + bed_width); + } else { + left_right_pair.emplace_back(i, j); + print_instance_with_bounding_box[j].arrange_score = std::max(r.arrange_score, l.arrange_score + bed_width); + dir = "right"; + } + BOOST_LOG_TRIVIAL(debug) << "print_instance " << inst.print_instance->model_instance->get_object()->name + << ", right=" << r.print_instance->model_instance->get_object()->name << ", l.score: " << l.arrange_score + << ", r.score: " << r.arrange_score << ", dist:" << std::max(rx1 - lx2, lx1 - rx2) << ", dir: " << dir; + } + } + } + } + } + BOOST_LOG_TRIVIAL(debug) << "bed width: " << bed_width << ", unsafe_dist:" << unsafe_dist; + for (auto& inst:print_instance_with_bounding_box) { + BOOST_LOG_TRIVIAL(debug) << "print_instance " << inst.print_instance->model_instance->get_object()->name + << ", score: " << inst.arrange_score; + } + // sort the print instance std::sort(print_instance_with_bounding_box.begin(), print_instance_with_bounding_box.end(), - [](auto &l, auto &r) { - auto ly1 = l.bounding_box.min.y(); - auto ly2 = l.bounding_box.max.y(); - auto ry1 = r.bounding_box.min.y(); - auto ry2 = r.bounding_box.max.y(); - auto inter_min = std::max(ly1, ry1); - auto inter_max = std::min(ly2, ry2); - auto lx = l.bounding_box.min.x(); - auto rx = r.bounding_box.min.x(); - if (inter_max - inter_min > 0) - return (lx < rx) || ((lx == rx) && (ly1 < ry1)); - else - return (ly1 < ry1); - }); + [&left_right_pair](print_instance_info& l, print_instance_info& r) { + if (std::find(left_right_pair.begin(),left_right_pair.end(), Vec2i(l.index, r.index)) != left_right_pair.end()) + return true; + else + return l.arrange_score < r.arrange_score;}); // sequential_print_vertical_clearance_valid { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 31a76b9a8..bfd56bf65 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -992,6 +992,14 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(40)); + def = this->add("extruder_clearance_max_radius", coFloat); + def->label = L("Max Radius"); + def->tooltip = L("Max clearance radius around extruder. Used as input of auto-arranging to avoid collision when printing by object"); + def->sidetext = L("mm"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloat(68)); + def = this->add("extruder_colour", coStrings); def->label = L("Extruder Color"); def->tooltip = L("Only used as a visual help on UI"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b1becfdc8..4734d84bb 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -824,6 +824,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionFloat, extruder_clearance_height_to_rod))//BBs ((ConfigOptionFloat, extruder_clearance_height_to_lid))//BBS ((ConfigOptionFloat, extruder_clearance_radius)) + ((ConfigOptionFloat, extruder_clearance_max_radius)) ((ConfigOptionStrings, extruder_colour)) ((ConfigOptionPoints, extruder_offset)) ((ConfigOptionBools, reduce_fan_stop_start_freq)) diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 077ec4380..d481ee83d 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -503,6 +503,9 @@ void ArrangeJob::process() if (params.is_seq_print) params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius)); + if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer")) + m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); + double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0; double brim_max = 0; std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon ap) { brim_max = std::max(brim_max, ap.brim_width); }); @@ -514,21 +517,26 @@ void ArrangeJob::process() params.bed_shrink_y = settings.bed_shrink_y + params.brim_skirt_distance; // for sequential print, we need to inflate the bed because cleareance_radius is so large if (params.is_seq_print) { - params.bed_shrink_x -= params.cleareance_radius/2; - params.bed_shrink_y -= params.cleareance_radius/2; + float shift_dist = params.cleareance_radius / 2 - 5; + params.bed_shrink_x -= shift_dist; + params.bed_shrink_y -= shift_dist; // dont forget to move the excluded region for (auto& region : m_unselected) { if (region.is_virt_object) - region.poly.translate(-scaled(params.cleareance_radius/2), -scaled(params.cleareance_radius/2)); + region.poly.translate(-scaled(shift_dist), -scaled(shift_dist)); } } // do not inflate brim_width. Objects are allowed to have overlapped brim. std::for_each(m_selected.begin(), m_selected.end(), [&](auto& ap) {ap.inflation = params.min_obj_distance / 2; }); - std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto& ap) {ap.inflation = ap.is_virt_object ? scaled(params.brim_skirt_distance) : params.min_obj_distance / 2; }); + // For occulusion regions, inflation should be larger to prevent genrating brim on them. + // However, extrusion cali regions are exceptional, since we can allow brim overlaps them. + std::for_each(m_unselected.begin(), m_unselected.end(), [&](auto &ap) { + ap.inflation = !ap.is_virt_object ? + params.min_obj_distance / 2 : + (ap.is_extrusion_cali_object ? scaled(params.cleareance_radius / 2) : scaled(params.brim_skirt_distance + params.cleareance_radius / 2)); + }); - if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer")) - m_plater->get_partplate_list().preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); m_plater->get_partplate_list().preprocess_exclude_areas(params.excluded_regions, 1); diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index a3295aa42..1c4194842 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -3461,6 +3461,7 @@ bool PartPlateList::preprocess_nonprefered_areas(arrangement::ArrangePolygons& r ret.translation = Vec2crd(0, 0); ret.rotation = 0.0f; ret.is_virt_object = true; + ret.is_extrusion_cali_object = true; ret.bed_idx = j; ret.height = 1; ret.name = "NonpreferedRegion" + std::to_string(index); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fdbb243b8..665a31e1e 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2001,7 +2001,8 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) //BBS: add bed_exclude_area , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "printable_area", "bed_exclude_area", "print_sequence", - "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance", + "extruder_clearance_radius", "extruder_clearance_max_radius", + "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance", "brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material", "enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume", "extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology",