FIX: cli arrange failed in some cases

1. set different bed_shrink for seq_print and layered print
2. fix the bug that seq_print arranging may get collision with exclusion
   area.
3. remove unused functions.

Jira: STUDIO-4663

Change-Id: I8b726704cca33fe37bb3cb7c4502963a9ad8d16b
(cherry picked from commit f27d00f81315fe4675bbc55ef932403e31a9264f)
This commit is contained in:
Arthur 2023-10-07 14:23:15 +08:00 committed by Lane.Wei
parent c35ece24fe
commit 04552e4c9b
9 changed files with 40 additions and 80 deletions

View file

@ -2048,7 +2048,6 @@ int CLI::run(int argc, char **argv)
bool user_center_specified = false; bool user_center_specified = false;
Points beds = get_bed_shape(m_print_config); Points beds = get_bed_shape(m_print_config);
ArrangeParams arrange_cfg; ArrangeParams arrange_cfg;
arrange_cfg.min_obj_distance = scaled(min_object_distance(m_print_config));
BOOST_LOG_TRIVIAL(info) << "will start transforms, commands count " << m_transforms.size() << "\n"; BOOST_LOG_TRIVIAL(info) << "will start transforms, commands count " << m_transforms.size() << "\n";
#if defined(__linux__) || defined(__LINUX__) #if defined(__linux__) || defined(__LINUX__)
@ -2445,13 +2444,13 @@ int CLI::run(int argc, char **argv)
Slic3r::GUI::PartPlate* cur_plate = nullptr; Slic3r::GUI::PartPlate* cur_plate = nullptr;
int low_duplicate_count = 0, up_duplicate_count = duplicate_count, arrange_count = 0; int low_duplicate_count = 0, up_duplicate_count = duplicate_count, arrange_count = 0;
arrange_cfg.is_seq_print = false;
if (duplicate_count > 0) { if (duplicate_count > 0) {
original_model = model; original_model = model;
} }
while(!finished_arrange) while(!finished_arrange)
{ {
arrange_cfg = ArrangeParams(); // reset all params
arrange_count++; arrange_count++;
//step-0: duplicate model //step-0: duplicate model
if (duplicate_count > 0) if (duplicate_count > 0)
@ -2666,20 +2665,26 @@ int CLI::run(int argc, char **argv)
arrange_cfg.cleareance_radius = cleareance_radius; arrange_cfg.cleareance_radius = cleareance_radius;
arrange_cfg.printable_height = print_height; arrange_cfg.printable_height = print_height;
arrange_cfg.min_obj_distance = 0; arrange_cfg.min_obj_distance = 0;
if (arrange_cfg.is_seq_print) {
arrange_cfg.bed_shrink_x = BED_SHRINK_SEQ_PRINT;
arrange_cfg.bed_shrink_y = BED_SHRINK_SEQ_PRINT;
}
if (auto printer_structure_opt = m_print_config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) { if (auto printer_structure_opt = m_print_config.option<ConfigOptionEnum<PrinterStructure>>("printer_structure")) {
arrange_cfg.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3); arrange_cfg.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3);
} }
arrangement::update_arrange_params(arrange_cfg, m_print_config, selected); arrangement::update_arrange_params(arrange_cfg, &m_print_config, selected);
arrangement::update_selected_items_inflation(selected, &m_print_config, arrange_cfg); arrangement::update_selected_items_inflation(selected, &m_print_config, arrange_cfg);
arrangement::update_unselected_items_inflation(unselected, &m_print_config, arrange_cfg); arrangement::update_unselected_items_inflation(unselected, &m_print_config, arrange_cfg);
arrangement::update_selected_items_axis_align(selected, &m_print_config, arrange_cfg); arrangement::update_selected_items_axis_align(selected, &m_print_config, arrange_cfg);
beds=get_shrink_bedpts(&m_print_config, arrange_cfg); beds=get_shrink_bedpts(&m_print_config, arrange_cfg);
partplate_list.preprocess_exclude_areas(arrange_cfg.excluded_regions, 1, scale_(1));
{ {
BOOST_LOG_TRIVIAL(debug)<< "Arrange full params: "<< arrange_cfg.to_json(); BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << beds[0].transpose() << ", " << beds[1].transpose() << ", " << beds[2].transpose() << ", " << beds[3].transpose();
BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< arrange_cfg.to_json();
BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%")%selected.size(); BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%")%selected.size();
for (auto item : selected) for (auto item : selected)
BOOST_LOG_TRIVIAL(trace) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx BOOST_LOG_TRIVIAL(trace) << item.name << ", extruder: " << item.extrude_ids.back() << ", bed: " << item.bed_idx

View file

@ -80,19 +80,18 @@ using ItemGroup = std::vector<std::reference_wrapper<Item>>;
const double BIG_ITEM_TRESHOLD = 0.02; 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 #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) void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig* print_cfg, const ArrangePolygons& selected)
{ {
double skirt_distance = get_real_skirt_dist(print_cfg); double skirt_distance = get_real_skirt_dist(*print_cfg);
// Note: skirt_distance is now defined between outermost brim and skirt, not the object and skirt. // 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. // So we can't do max but do adding instead.
params.brim_skirt_distance = skirt_distance; params.brim_skirt_distance = skirt_distance;
params.bed_shrink_x = params.brim_skirt_distance; params.bed_shrink_x += params.brim_skirt_distance;
params.bed_shrink_y = 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 // for sequential print, we need to inflate the bed because cleareance_radius is so large
if (params.is_seq_print) { if (params.is_seq_print) {
float shift_dist = params.cleareance_radius / 2 - 5; params.bed_shrink_x -= params.cleareance_radius / 2;
params.bed_shrink_x -= shift_dist; params.bed_shrink_y -= params.cleareance_radius / 2;
params.bed_shrink_y -= shift_dist;
} }
} }
@ -126,11 +125,13 @@ void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPri
void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params) void update_unselected_items_inflation(ArrangePolygons& unselected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params)
{ {
float exclusion_gap = 1.f;
if (params.is_seq_print) { if (params.is_seq_print) {
float shift_dist = params.cleareance_radius / 2 - 5; // bed_shrink_x is typically (-params.cleareance_radius / 2+5) for seq_print
exclusion_gap = std::max(exclusion_gap, params.cleareance_radius / 2 + params.bed_shrink_x);
// dont forget to move the excluded region // dont forget to move the excluded region
for (auto& region : unselected) { for (auto& region : unselected) {
if (region.is_virt_object) region.poly.translate(-scaled(shift_dist), -scaled(shift_dist)); if (region.is_virt_object) region.poly.translate(scaled(params.bed_shrink_x), scaled(params.bed_shrink_y));
} }
} }
// For occulusion regions, inflation should be larger to prevent genrating brim on them. // For occulusion regions, inflation should be larger to prevent genrating brim on them.
@ -138,10 +139,9 @@ void update_unselected_items_inflation(ArrangePolygons& unselected, const Dynami
// 屏蔽区域只需要膨胀brim宽度防止brim长过去挤出标定区域不需要膨胀brim可以长过去。 // 屏蔽区域只需要膨胀brim宽度防止brim长过去挤出标定区域不需要膨胀brim可以长过去。
// 以前我们认为还需要膨胀clearance_radius/2这其实是不需要的因为这些区域并不会真的摆放物体 // 以前我们认为还需要膨胀clearance_radius/2这其实是不需要的因为这些区域并不会真的摆放物体
// 其他物体的膨胀轮廓是可以跟它们重叠的。 // 其他物体的膨胀轮廓是可以跟它们重叠的。
double scaled_exclusion_gap = scale_(1);
std::for_each(unselected.begin(), unselected.end(), std::for_each(unselected.begin(), unselected.end(),
[&](auto& ap) { ap.inflation = !ap.is_virt_object ? (params.min_obj_distance == 0 ? scaled(ap.brim_width) : params.min_obj_distance / 2) [&](auto& ap) { ap.inflation = !ap.is_virt_object ? (params.min_obj_distance == 0 ? scaled(ap.brim_width) : params.min_obj_distance / 2)
: (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); }); : (ap.is_extrusion_cali_object ? 0 : scale_(exclusion_gap)); });
} }
void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params) void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params)

View file

@ -3,6 +3,9 @@
#include "ExPolygon.hpp" #include "ExPolygon.hpp"
#include "PrintConfig.hpp" #include "PrintConfig.hpp"
#define BED_SHRINK_SEQ_PRINT 5
namespace Slic3r { namespace Slic3r {
class BoundingBox; class BoundingBox;
@ -122,8 +125,8 @@ struct ArrangeParams {
bool avoid_extrusion_cali_region = true; bool avoid_extrusion_cali_region = true;
bool is_seq_print = false; bool is_seq_print = false;
bool align_to_y_axis = false; bool align_to_y_axis = false;
float bed_shrink_x = 0; float bed_shrink_x = 1;
float bed_shrink_y = 0; float bed_shrink_y = 1;
float brim_skirt_distance = 0; float brim_skirt_distance = 0;
float clearance_height_to_rod = 0; float clearance_height_to_rod = 0;
float clearance_height_to_lid = 0; float clearance_height_to_lid = 0;
@ -170,7 +173,7 @@ struct ArrangeParams {
}; };
void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig& print_cfg, const ArrangePolygons& selected); void update_arrange_params(ArrangeParams& params, const DynamicPrintConfig* print_cfg, const ArrangePolygons& selected);
void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, ArrangeParams& params); void update_selected_items_inflation(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, ArrangeParams& params);

View file

@ -533,7 +533,7 @@ StringObjectException Print::sequential_print_clearance_valid(const Print &print
auto tmp = offset(convex_hull_no_offset, auto tmp = offset(convex_hull_no_offset,
// Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects // Shrink the extruder_clearance_radius a tiny bit, so that if the object arrangement algorithm placed the objects
// exactly by satisfying the extruder_clearance_radius, this test will not trigger collision. // exactly by satisfying the extruder_clearance_radius, this test will not trigger collision.
float(scale_(0.5 * print.config().extruder_clearance_max_radius.value - 0.01)), float(scale_(0.5 * print.config().extruder_clearance_max_radius.value - 0.1)),
jtRound, scale_(0.1)); jtRound, scale_(0.1));
if (!tmp.empty()) { // tmp may be empty due to clipper's bug, see STUDIO-2452 if (!tmp.empty()) { // tmp may be empty due to clipper's bug, see STUDIO-2452
convex_hull = tmp.front(); convex_hull = tmp.front();

View file

@ -481,8 +481,6 @@ public:
bool avoid_extrusion_cali_region = true; bool avoid_extrusion_cali_region = true;
//BBS: add more arrangeSettings //BBS: add more arrangeSettings
bool is_seq_print = false; bool is_seq_print = false;
float bed_shrink_x = 0.f;
float bed_shrink_y = 0.f;
bool align_to_y_axis = false; bool align_to_y_axis = false;
}; };

View file

@ -491,23 +491,20 @@ void ArrangeJob::on_exception(const std::exception_ptr &eptr)
void ArrangeJob::process() void ArrangeJob::process()
{ {
const GLCanvas3D::ArrangeSettings &settings =
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
auto & partplate_list = m_plater->get_partplate_list(); auto & partplate_list = m_plater->get_partplate_list();
auto& print = wxGetApp().plater()->get_partplate_list().get_current_fff_print();
const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config(); const Slic3r::DynamicPrintConfig& global_config = wxGetApp().preset_bundle->full_config();
if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer")) if (params.avoid_extrusion_cali_region && global_config.opt_bool("scan_first_layer"))
partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES); partplate_list.preprocess_nonprefered_areas(m_unselected, MAX_NUM_PLATES);
update_arrange_params(params, *m_plater, m_selected); update_arrange_params(params, m_plater->config(), m_selected);
update_selected_items_inflation(m_selected, m_plater->config(), params); update_selected_items_inflation(m_selected, m_plater->config(), params);
update_unselected_items_inflation(m_unselected, m_plater->config(), params); update_unselected_items_inflation(m_unselected, m_plater->config(), params);
update_selected_items_axis_align(m_selected, m_plater->config(), params); update_selected_items_axis_align(m_selected, m_plater->config(), params);
Points bedpts = get_shrink_bedpts(m_plater->config(),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); partplate_list.preprocess_exclude_areas(params.excluded_regions, 1, scale_(1));
BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose(); BOOST_LOG_TRIVIAL(debug) << "arrange bedpts:" << bedpts[0].transpose() << ", " << bedpts[1].transpose() << ", " << bedpts[2].transpose() << ", " << bedpts[3].transpose();
@ -518,8 +515,8 @@ void ArrangeJob::process()
}; };
{ {
BOOST_LOG_TRIVIAL(debug)<< "Arrange full params: "<< params.to_json(); BOOST_LOG_TRIVIAL(warning)<< "Arrange full params: "<< params.to_json();
BOOST_LOG_TRIVIAL(debug) << "items selected before arrange: "; BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items selected before arranging: %1%") % m_selected.size();
for (auto selected : m_selected) for (auto selected : m_selected)
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp; << ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp;
@ -533,7 +530,7 @@ void ArrangeJob::process()
// sort by item id // sort by item id
std::sort(m_selected.begin(), m_selected.end(), [](auto a, auto b) {return a.itemid < b.itemid; }); std::sort(m_selected.begin(), m_selected.end(), [](auto a, auto b) {return a.itemid < b.itemid; });
{ {
BOOST_LOG_TRIVIAL(debug) << "items selected after arrange: "; BOOST_LOG_TRIVIAL(info) << boost::format("arrange: items unselected before arranging: %1%") % m_unselected.size();
for (auto selected : m_selected) for (auto selected : m_selected)
BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx BOOST_LOG_TRIVIAL(debug) << selected.name << ", extruder: " << selected.extrude_ids.back() << ", bed: " << selected.bed_idx
<< ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp << ", bed_temp: " << selected.first_bed_temp << ", print_temp: " << selected.print_temp
@ -707,23 +704,6 @@ double bed_stride_y(const Plater* plater) {
return (1. + LOGICAL_BED_GAP) * beddepth; return (1. + LOGICAL_BED_GAP) * beddepth;
} }
arrangement::ArrangeParams get_arrange_params(Plater *p)
{
const GLCanvas3D::ArrangeSettings &settings =
static_cast<const GLCanvas3D*>(p->canvas3D())->get_arrange_settings();
arrangement::ArrangeParams params;
params.allow_rotations = settings.enable_rotation;
params.min_obj_distance = scaled(settings.distance);
//BBS: add specific params
params.is_seq_print = settings.is_seq_print;
params.bed_shrink_x = settings.bed_shrink_x;
params.bed_shrink_y = settings.bed_shrink_y;
return params;
}
// call before get selected and unselected // call before get selected and unselected
arrangement::ArrangeParams init_arrange_params(Plater *p) arrangement::ArrangeParams init_arrange_params(Plater *p)
{ {
@ -742,8 +722,6 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region; params.avoid_extrusion_cali_region = settings.avoid_extrusion_cali_region;
params.is_seq_print = settings.is_seq_print; params.is_seq_print = settings.is_seq_print;
params.min_obj_distance = scaled(settings.distance); params.min_obj_distance = scaled(settings.distance);
params.bed_shrink_x = settings.bed_shrink_x;
params.bed_shrink_y = settings.bed_shrink_y;
params.align_to_y_axis = settings.align_to_y_axis; params.align_to_y_axis = settings.align_to_y_axis;
int state = p->get_prepare_state(); int state = p->get_prepare_state();
@ -753,28 +731,12 @@ arrangement::ArrangeParams init_arrange_params(Plater *p)
params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject; params.is_seq_print = plate->get_real_print_seq() == PrintSequence::ByObject;
} }
if (params.is_seq_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 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
params.bed_shrink_x = BED_SHRINK_SEQ_PRINT;
params.bed_shrink_y = BED_SHRINK_SEQ_PRINT;
}
return params; return params;
} }
//after get selected call this to update bed_shrink
void update_arrange_params(arrangement::ArrangeParams &params, const Plater &p, const arrangement::ArrangePolygons &selected)
{
const GLCanvas3D::ArrangeSettings &settings = static_cast<const GLCanvas3D *>(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;
// 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;
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;
}
}
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI

View file

@ -75,13 +75,8 @@ static const constexpr double LOGICAL_BED_GAP = 1. / 5.;
double bed_stride_x(const Plater* plater); double bed_stride_x(const Plater* plater);
double bed_stride_y(const Plater* plater); double bed_stride_y(const Plater* plater);
arrangement::ArrangeParams get_arrange_params(Plater *p);
arrangement::ArrangeParams init_arrange_params(Plater *p); arrangement::ArrangeParams init_arrange_params(Plater *p);
void update_arrange_params(arrangement::ArrangeParams &params, const Plater &p, const arrangement::ArrangePolygons &selected);
}} // namespace Slic3r::GUI }} // namespace Slic3r::GUI
#endif // ARRANGEJOB_HPP #endif // ARRANGEJOB_HPP

View file

@ -202,10 +202,7 @@ void FillBedJob::process()
{ {
if (m_object_idx == -1 || m_selected.empty()) return; if (m_object_idx == -1 || m_selected.empty()) return;
const GLCanvas3D::ArrangeSettings &settings = update_arrange_params(params, m_plater->config(), m_selected);
static_cast<const GLCanvas3D*>(m_plater->canvas3D())->get_arrange_settings();
update_arrange_params(params, *m_plater, m_selected);
m_bedpts = get_shrink_bedpts(m_plater->config(), params); m_bedpts = get_shrink_bedpts(m_plater->config(), params);
auto &partplate_list = m_plater->get_partplate_list(); auto &partplate_list = m_plater->get_partplate_list();

View file

@ -4249,7 +4249,7 @@ void Plater::priv::mirror(Axis axis)
void Plater::find_new_position(const ModelInstancePtrs &instances) void Plater::find_new_position(const ModelInstancePtrs &instances)
{ {
arrangement::ArrangePolygons movable, fixed; arrangement::ArrangePolygons movable, fixed;
arrangement::ArrangeParams arr_params = get_arrange_params(this); arrangement::ArrangeParams arr_params = init_arrange_params(this);
for (const ModelObject *mo : p->model.objects) for (const ModelObject *mo : p->model.objects)
for (ModelInstance *inst : mo->instances) { for (ModelInstance *inst : mo->instances) {