From 33c69cdb4f89bc952dfca3c633cd5a1295e920e3 Mon Sep 17 00:00:00 2001 From: manch1n Date: Tue, 23 May 2023 17:57:42 +0800 Subject: [PATCH] FIX: make fill in bed arrange parameters same as normal arrange Change-Id: Iec9d4e9c145ea75fc06d096e9c6905b3e412940c --- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 188 +++++++++++++++++------------ src/slic3r/GUI/Jobs/ArrangeJob.hpp | 10 ++ src/slic3r/GUI/Jobs/FillBedJob.cpp | 16 ++- src/slic3r/GUI/Jobs/FillBedJob.hpp | 2 + 4 files changed, 131 insertions(+), 85 deletions(-) diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 50eaf9d40..6cc6b8a6a 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -392,20 +392,7 @@ void ArrangeJob::prepare() NotificationManager::NotificationLevel::RegularNotificationLevel, _u8L("Arranging...")); m_plater->get_notification_manager()->bbl_close_plateinfo_notification(); - { - const GLCanvas3D::ArrangeSettings &settings = static_cast(m_plater->canvas3D())->get_arrange_settings(); - auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); - - params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value; - params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value; - params.cleareance_radius = print.config().extruder_clearance_max_radius.value; - params.printable_height = print.config().printable_height.value; - params.allow_rotations = settings.enable_rotation; - params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate; - params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; - params.is_seq_print = settings.is_seq_print; - params.min_obj_distance = scaled(settings.distance); - } + params = init_arrange_params(*m_plater); //BBS update extruder params and speed table before arranging Plater::setExtruderParams(Model::extruderParamsMap); @@ -510,79 +497,18 @@ void ArrangeJob::process() auto & partplate_list = m_plater->get_partplate_list(); auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); - if (params.is_seq_print) - params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error - if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer")) 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); }); + 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); - // 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 = settings.bed_shrink_x + params.brim_skirt_distance; - 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) { - 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(shift_dist), -scaled(shift_dist)); - } - } - - if (print.full_print_config().opt_bool("enable_support")) { - params.bed_shrink_x = std::max(5.f, params.bed_shrink_x); - params.bed_shrink_y = std::max(5.f, params.bed_shrink_y); - params.min_obj_distance = std::max(scaled(10.0), params.min_obj_distance); - } - - // do not inflate brim_width. Objects are allowed to have overlapped brim. - Points bedpts = get_bed_shape(*m_plater->config()); - BoundingBox bedbb = Polygon(bedpts).bounding_box(); - std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon &ap) { - ap.inflation = 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); - } - }); - // 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,这其实是不需要的,因为这些区域并不会真的摆放物体, - // 其他物体的膨胀轮廓是可以跟它们重叠的。 + Points bedpts = get_shrink_bedpts(*m_plater,params); double scaled_exclusion_gap = scale_(1); - 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 ? 0 : scaled_exclusion_gap); - }); - - partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap); - // 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); - BOOST_LOG_TRIVIAL(debug) << "arrange bed_shrink_x=" << params.bed_shrink_x - << ", brim_max= "<(p.canvas3D())->get_arrange_settings(); + auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); + + params.clearance_height_to_rod = print.config().extruder_clearance_height_to_rod.value; + params.clearance_height_to_lid = print.config().extruder_clearance_height_to_lid.value; + params.cleareance_radius = print.config().extruder_clearance_max_radius.value; + params.printable_height = print.config().printable_height.value; + params.allow_rotations = settings.enable_rotation; + params.allow_multi_materials_on_same_plate = settings.allow_multi_materials_on_same_plate; + params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; + params.is_seq_print = settings.is_seq_print; + params.min_obj_distance = scaled(settings.distance); + params.bed_shrink_x = settings.bed_shrink_x; + params.bed_shrink_y = settings.bed_shrink_y; + + if (params.is_seq_print) + params.min_obj_distance = std::max(params.min_obj_distance, scaled(params.cleareance_radius + 0.001)); // +0.001mm to avoid clearance check fail due to rounding error + return params; +} + +//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(); + auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); + double skirt_distance = print.has_skirt() ? print.config().skirt_distance.value : 0; + 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 = settings.bed_shrink_x + params.brim_skirt_distance; + 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) { + float shift_dist = params.cleareance_radius / 2 - 5; + params.bed_shrink_x -= shift_dist; + params.bed_shrink_y -= shift_dist; + } + + // For by-layer printing, need to shrink bed a little, so the support won't go outside bed. + // We set it to 5mm because that's how much a normal support will grow by default. + // But for by-object printing, it's not needed since the clerance distance is already very large. + if (print.full_print_config().opt_bool("enable_support") && !params.is_seq_print) { + params.bed_shrink_x = std::max(5.f, params.bed_shrink_x); + params.bed_shrink_y = std::max(5.f, params.bed_shrink_y); + params.min_obj_distance = std::max(scaled(10.0), params.min_obj_distance); + } +} + +//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 = 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 ? 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 6e8ebe028..fec716197 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -78,6 +78,16 @@ double bed_stride_y(const Plater* plater); arrangement::ArrangeParams get_arrange_params(Plater *p); +arrangement::ArrangeParams init_arrange_params(const 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 #endif // ARRANGEJOB_HPP diff --git a/src/slic3r/GUI/Jobs/FillBedJob.cpp b/src/slic3r/GUI/Jobs/FillBedJob.cpp index e3613cace..184690911 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.cpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.cpp @@ -23,6 +23,8 @@ void FillBedJob::prepare() m_unselected.clear(); m_bedpts.clear(); + params = init_arrange_params(*m_plater); + m_object_idx = m_plater->get_selected_object_idx(); if (m_object_idx == -1) return; @@ -118,6 +120,8 @@ void FillBedJob::prepare() if (m_selected.empty()) return; //add the virtual object into unselect list if has + double scaled_exclusion_gap = scale_(1); + plate_list.preprocess_exclude_areas(params.excluded_regions, 1, scaled_exclusion_gap); plate_list.preprocess_exclude_areas(m_unselected); m_bedpts = get_bed_shape(*m_plater->config()); @@ -200,16 +204,16 @@ void FillBedJob::process() const GLCanvas3D::ArrangeSettings &settings = static_cast(m_plater->canvas3D())->get_arrange_settings(); - arrangement::ArrangeParams params; - params.allow_rotations = settings.enable_rotation; - params.min_obj_distance = scaled(settings.distance); - params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; + update_arrange_params(params, *m_plater, m_selected); + m_bedpts = get_shrink_bedpts(*m_plater, params); + auto &partplate_list = m_plater->get_partplate_list(); auto &print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); if (params.avoid_extrusion_cali_region && print.full_print_config().opt_bool("scan_first_layer")) partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); - - for (auto &ap : m_selected) { ap.inflation = params.min_obj_distance / 2; } + + update_selected_items_inflation(m_selected, *m_plater, params); + update_unselected_items_inflation(m_unselected, *m_plater, params); bool do_stop = false; params.stopcondition = [this, &do_stop]() { diff --git a/src/slic3r/GUI/Jobs/FillBedJob.hpp b/src/slic3r/GUI/Jobs/FillBedJob.hpp index cd0c32c1b..f78b1f9f2 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.hpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.hpp @@ -21,6 +21,8 @@ class FillBedJob : public PlaterJob Points m_bedpts; + arrangement::ArrangeParams params; + int m_status_range = 0; protected: