diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index eb0cd2c6f..8419db726 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -2309,7 +2309,7 @@ int CLI::run(int argc, char **argv) //skip this object due to be not in current plate, treated as locked ap.itemid = locked_aps.size(); locked_aps.emplace_back(std::move(ap)); - BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name; + BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format("arrange: skip locked instance, obj_id %1%, name %2%") % oidx % mo->name; } } } @@ -2331,12 +2331,12 @@ int CLI::run(int argc, char **argv) // slice filaments info invalid std::vector extruders = cur_plate->get_extruders_under_cli(true, m_print_config); filaments_cnt = extruders.size(); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": slice filaments info invalid or need_skip, get from partplate: filament_count %1%")%filaments_cnt; + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange: slice filaments info invalid or need_skip, get from partplate: filament_count %1%")%filaments_cnt; } if (filaments_cnt <= 1) { - BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(": not a multi-color object anymore, drop the wipe tower before arrange."); + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format("arrange: not a multi-color object anymore, drop the wipe tower before arrange."); } else { @@ -2347,7 +2347,7 @@ int CLI::run(int argc, char **argv) float depth = v * (filaments_cnt - 1) / (layer_height * w); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", wipe_tower: x=%1%, y=%2%, width=%3%, depth=%4%, angle=%5%, prime_volume=%6%, filaments_cnt=%7%, layer_height=%8%") + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange wipe_tower: x=%1%, y=%2%, width=%3%, depth=%4%, angle=%5%, prime_volume=%6%, filaments_cnt=%7%, layer_height=%8%") %x %y %w %depth %a %v %filaments_cnt %layer_height; Vec3d plate_origin = cur_plate->get_origin(); @@ -2389,39 +2389,20 @@ int CLI::run(int argc, char **argv) arrange_cfg.cleareance_radius = cleareance_radius; arrange_cfg.printable_height = print_height; - arrange_cfg.bed_shrink_x = 0; - arrange_cfg.bed_shrink_y = 0; - double skirt_distance = m_print_config.opt_float("skirt_distance"); - double brim_width = m_print_config.opt_float("brim_width"); - arrange_cfg.brim_skirt_distance = skirt_distance + brim_width; - BOOST_LOG_TRIVIAL(info) << boost::format("Arrange Params: brim_skirt_distance=%1%, min_obj_distance=%2%, is_seq_print=%3%\n") % arrange_cfg.brim_skirt_distance % arrange_cfg.min_obj_distance % arrange_cfg.is_seq_print; - - // Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt. - // So we can't do max but do adding instead. - arrange_cfg.bed_shrink_x += arrange_cfg.brim_skirt_distance; - arrange_cfg.bed_shrink_y += arrange_cfg.brim_skirt_distance; - - if (arrange_cfg.is_seq_print) - { - arrange_cfg.min_obj_distance = std::max(arrange_cfg.min_obj_distance, scaled(arrange_cfg.cleareance_radius + 0.001)); - float shift_dist = arrange_cfg.cleareance_radius / 2 - 5; - arrange_cfg.bed_shrink_x -= shift_dist; - arrange_cfg.bed_shrink_y -= shift_dist; - } - // shrink bed - beds[0] += Point(scaled(arrange_cfg.bed_shrink_x), scaled(arrange_cfg.bed_shrink_y)); - beds[1] += Point(-scaled(arrange_cfg.bed_shrink_x), scaled(arrange_cfg.bed_shrink_y)); - beds[2] += Point(-scaled(arrange_cfg.bed_shrink_x), -scaled(arrange_cfg.bed_shrink_y)); - beds[3] += Point(scaled(arrange_cfg.bed_shrink_x), -scaled(arrange_cfg.bed_shrink_y)); - - // do not inflate brim_width. Objects are allowed to have overlapped brim. - std::for_each(selected.begin(), selected.end(), [&](auto& ap) {ap.inflation = arrange_cfg.min_obj_distance / 2; }); + arrangement::update_arrange_params(arrange_cfg, m_print_config, selected); + arrangement::update_selected_items_inflation(selected, &m_print_config, arrange_cfg); + arrangement::update_unselected_items_inflation(unselected, &m_print_config, arrange_cfg); + beds=get_shrink_bedpts(&m_print_config, arrange_cfg); { - BOOST_LOG_TRIVIAL(info) << boost::format("items selected before arranging: %1%")%selected.size(); - for (auto selected : selected) - BOOST_LOG_TRIVIAL(trace) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx - << ", trans: " << selected.translation.transpose(); + BOOST_LOG_TRIVIAL(debug)<< "Arrange full params: "<< arrange_cfg.to_json(); + BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%")%selected.size(); + for (auto item : selected) + BOOST_LOG_TRIVIAL(trace) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx + << ", trans: " << item.translation.transpose(); + BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items unselected before arranging: %1%") % unselected.size(); + for (auto item : unselected) + BOOST_LOG_TRIVIAL(trace) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose(); } arrange_cfg.progressind= [](unsigned st, std::string str = "") { //boost::nowide::cout << "st=" << st << ", " << str << std::endl; diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 9b4f493ef..470340152 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -80,6 +80,75 @@ using ItemGroup = std::vector>; const double BIG_ITEM_TRESHOLD = 0.02; #define VITRIFY_TEMP_DIFF_THRSH 15 // bed temp can be higher than vitrify temp, but not higher than this thresh +void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig& print_cfg, const ArrangePolygons& selected) +{ + double skirt_distance = get_real_skirt_dist(print_cfg); + double brim_max = 0; + std::for_each(selected.begin(), selected.end(), [&](const ArrangePolygon& ap) { brim_max = std::max(brim_max, ap.brim_width); }); + // Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt. + // So we can't do max but do adding instead. + params.brim_skirt_distance = skirt_distance + brim_max; + params.bed_shrink_x = params.brim_skirt_distance; + params.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) { + float shift_dist = params.cleareance_radius / 2 - 5; + params.bed_shrink_x -= shift_dist; + params.bed_shrink_y -= shift_dist; + } +} + +void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params) { + // do not inflate brim_width. Objects are allowed to have overlapped brim. + Points bedpts = get_shrink_bedpts(print_cfg, params); + BoundingBox bedbb = Polygon(bedpts).bounding_box(); + std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon& ap) { + ap.inflation = std::max(scaled(ap.brim_width), params.min_obj_distance / 2); + BoundingBox apbb = ap.poly.contour.bounding_box(); + auto diffx = bedbb.size().x() - apbb.size().x() - 5; + auto diffy = bedbb.size().y() - apbb.size().y() - 5; + if (diffx > 0 && diffy > 0) { + auto min_diff = std::min(diffx, diffy); + ap.inflation = std::min(min_diff / 2, ap.inflation); + } + }); +} + +void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params) +{ + if (params.is_seq_print) { + float shift_dist = params.cleareance_radius / 2 - 5; + // dont forget to move the excluded region + for (auto& region : unselected) { + if (region.is_virt_object) region.poly.translate(-scaled(shift_dist), -scaled(shift_dist)); + } + } + // 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. + // 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。 + // 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体, + // 其他物体的膨胀轮廓是可以跟它们重叠的。 + double scaled_exclusion_gap = scale_(1); + std::for_each(unselected.begin(), unselected.end(), + [&](auto& ap) { ap.inflation = !ap.is_virt_object ? std::max(scaled(ap.brim_width), params.min_obj_distance / 2) + : (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); }); +} + +//it will bed accurate after call update_params +Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params) +{ + Points bedpts = get_bed_shape(*print_cfg); + // shrink bed by moving to center by dist + auto shrinkFun = [](Points& bedpts, double dist, int direction) { +#define SGN(x) ((x) >= 0 ? 1 : -1) + Point center = Polygon(bedpts).bounding_box().center(); + for (auto& pt : bedpts) pt[direction] += dist * SGN(center[direction] - pt[direction]); + }; + shrinkFun(bedpts, scaled(params.bed_shrink_x), 0); + shrinkFun(bedpts, scaled(params.bed_shrink_y), 1); + return bedpts; +} + // Fill in the placer algorithm configuration with values carefully chosen for // Slic3r. template diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index a9b7cc484..be3d67e97 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -2,7 +2,7 @@ #define ARRANGE_HPP #include "ExPolygon.hpp" - +#include "PrintConfig.hpp" namespace Slic3r { class BoundingBox; @@ -144,8 +144,37 @@ struct ArrangeParams { ArrangeParams() = default; explicit ArrangeParams(coord_t md) : min_obj_distance(md) {} + // to json format + std::string to_json() const{ + std::string ret = "{"; + ret += "\"min_obj_distance\":" + std::to_string(min_obj_distance) + ","; + ret += "\"accuracy\":" + std::to_string(accuracy) + ","; + ret += "\"parallel\":" + std::to_string(parallel) + ","; + ret += "\"allow_rotations\":" + std::to_string(allow_rotations) + ","; + ret += "\"do_final_align\":" + std::to_string(do_final_align) + ","; + ret += "\"allow_multi_materials_on_same_plate\":" + std::to_string(allow_multi_materials_on_same_plate) + ","; + ret += "\"avoid_extrusion_cali_region\":" + std::to_string(avoid_extrusion_cali_region) + ","; + ret += "\"is_seq_print\":" + std::to_string(is_seq_print) + ","; + ret += "\"bed_shrink_x\":" + std::to_string(bed_shrink_x) + ","; + ret += "\"bed_shrink_y\":" + std::to_string(bed_shrink_y) + ","; + ret += "\"brim_skirt_distance\":" + std::to_string(brim_skirt_distance) + ","; + ret += "\"clearance_height_to_rod\":" + std::to_string(clearance_height_to_rod) + ","; + ret += "\"clearance_height_to_lid\":" + std::to_string(clearance_height_to_lid) + ","; + ret += "\"cleareance_radius\":" + std::to_string(cleareance_radius) + ","; + ret += "\"printable_height\":" + std::to_string(printable_height) + ","; + return ret; + } + }; +void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig& print_cfg, const ArrangePolygons& selected); + +void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params); + +void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params); + +Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params); + /** * \brief Arranges the input polygons. * diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 22f8624f7..0bf5ef62f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5295,6 +5295,17 @@ Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg) if (!tmp.empty()) bed_poly = tmp[0]; return bed_poly; } +bool has_skirt(const DynamicPrintConfig& cfg) +{ + auto opt_skirt_height = cfg.option("skirt_height"); + auto opt_skirt_loops = cfg.option("skirt_loops"); + auto opt_draft_shield = cfg.option("draft_shield"); + return (opt_skirt_height && opt_skirt_height->getInt() > 0 && opt_skirt_loops && opt_skirt_loops->getInt() > 0) + || (opt_draft_shield && opt_draft_shield->getInt() != dsDisabled); +} +float get_real_skirt_dist(const DynamicPrintConfig& cfg) { + return has_skirt(cfg) ? cfg.opt_float("skirt_distance") : 0; +} } // namespace Slic3r #include diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 02f1718c3..3f1fa4a2a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1292,6 +1292,8 @@ Points get_bed_shape(const DynamicPrintConfig &cfg); Points get_bed_shape(const PrintConfig &cfg); Points get_bed_shape(const SLAPrinterConfig &cfg); Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg); +bool has_skirt(const DynamicPrintConfig& cfg); +float get_real_skirt_dist(const DynamicPrintConfig& cfg); // ModelConfig is a wrapper around DynamicPrintConfig with an addition of a timestamp. // Each change of ModelConfig is tracked by assigning a new timestamp from a global counter. diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 528ac10c6..320e8dc03 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -502,10 +502,10 @@ void ArrangeJob::process() partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); update_arrange_params(params, *m_plater, m_selected); - update_selected_items_inflation(m_selected, *m_plater, params); - update_unselected_items_inflation(m_unselected, *m_plater, params); + update_selected_items_inflation(m_selected, m_plater->config(), params); + update_unselected_items_inflation(m_unselected, m_plater->config(), params); - Points bedpts = get_shrink_bedpts(*m_plater,params); + Points bedpts = get_shrink_bedpts(m_plater->config(),params); double scaled_exclusion_gap = scale_(1); partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap); @@ -519,6 +519,7 @@ void ArrangeJob::process() }; { + BOOST_LOG_TRIVIAL(debug)<< "Arrange full params: "<< params.to_json(); BOOST_LOG_TRIVIAL(debug) << "items selected before arrange: "; for (auto selected : m_selected) BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx @@ -758,7 +759,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) return params; } -//after get selected.call this to update bed_shrink +//after get selected call this to update bed_shrink void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, const arrangement::ArrangePolygons &selected) { const GLCanvas3D::ArrangeSettings &settings = static_cast(p.canvas3D())->get_arrange_settings(); @@ -779,55 +780,4 @@ void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, } } -//it will bed accurate after call update_params -Points get_shrink_bedpts(const Plater &plater, const arrangement::ArrangeParams ¶ms) -{ - Points bedpts = get_bed_shape(*plater.config()); - // shrink bed by moving to center by dist - auto shrinkFun = [](Points &bedpts, double dist, int direction) { -#define SGN(x) ((x) >= 0 ? 1 : -1) - Point center = Polygon(bedpts).bounding_box().center(); - for (auto &pt : bedpts) pt[direction] += dist * SGN(center[direction] - pt[direction]); - }; - shrinkFun(bedpts, scaled(params.bed_shrink_x), 0); - shrinkFun(bedpts, scaled(params.bed_shrink_y), 1); - return bedpts; -} - -void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams ¶ms) { - // do not inflate brim_width. Objects are allowed to have overlapped brim. - Points bedpts = get_shrink_bedpts(p, params); - BoundingBox bedbb = Polygon(bedpts).bounding_box(); - std::for_each(selected.begin(), selected.end(), [&](ArrangePolygon &ap) { - ap.inflation = std::max(scaled(ap.brim_width), params.min_obj_distance / 2); - BoundingBox apbb = ap.poly.contour.bounding_box(); - auto diffx = bedbb.size().x() - apbb.size().x() - 5; - auto diffy = bedbb.size().y() - apbb.size().y() - 5; - if (diffx > 0 && diffy > 0) { - auto min_diff = std::min(diffx, diffy); - ap.inflation = std::min(min_diff / 2, ap.inflation); - } - }); -} - -void update_unselected_items_inflation(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::ArrangeParams ¶ms) -{ - if (params.is_seq_print) { - float shift_dist = params.cleareance_radius / 2 - 5; - // dont forget to move the excluded region - for (auto ®ion : unselected) { - if (region.is_virt_object) region.poly.translate(-scaled(shift_dist), -scaled(shift_dist)); - } - } - // 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. - // 屏蔽区域只需要膨胀brim宽度,防止brim长过去;挤出标定区域不需要膨胀,brim可以长过去。 - // 以前我们认为还需要膨胀clearance_radius/2,这其实是不需要的,因为这些区域并不会真的摆放物体, - // 其他物体的膨胀轮廓是可以跟它们重叠的。 - double scaled_exclusion_gap = scale_(1); - std::for_each(unselected.begin(), unselected.end(), - [&](auto &ap) { ap.inflation = !ap.is_virt_object ? std::max(scaled(ap.brim_width), params.min_obj_distance / 2) - : (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); }); -} - }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index e4ec09b5e..ae56866ce 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -80,13 +80,8 @@ arrangement::ArrangeParams get_arrange_params(Plater *p); arrangement::ArrangeParams init_arrange_params(Plater *p); -Points get_shrink_bedpts(const Plater& plater,const arrangement::ArrangeParams& params); - void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, const arrangement::ArrangePolygons &selected); -void update_selected_items_inflation(arrangement::ArrangePolygons &selected, const Plater &p, const arrangement::ArrangeParams ¶ms); - -void update_unselected_items_inflation(arrangement::ArrangePolygons &unselected, const Plater &p, const arrangement::ArrangeParams ¶ms); }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index c00968180..6e53d6183 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -206,7 +206,7 @@ void FillBedJob::process() static_cast(m_plater->canvas3D())->get_arrange_settings(); update_arrange_params(params, *m_plater, m_selected); - m_bedpts = get_shrink_bedpts(*m_plater, params); + m_bedpts = get_shrink_bedpts(m_plater->config(), params); auto &partplate_list = m_plater->get_partplate_list(); auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); @@ -214,8 +214,8 @@ void FillBedJob::process() if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer")) partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); - update_selected_items_inflation(m_selected, *m_plater, params); - update_unselected_items_inflation(m_unselected, *m_plater, params); + update_selected_items_inflation(m_selected, m_plater->config(), params); + update_unselected_items_inflation(m_unselected, m_plater->config(), params); bool do_stop = false; params.stopcondition = [this, &do_stop]() {