From 8d74732348e9ba47faaffb2a1a5186707599a586 Mon Sep 17 00:00:00 2001 From: Arthur Date: Sun, 8 Oct 2023 19:54:21 +0800 Subject: [PATCH] FIX: auto arrange estimates wrong wipe tower Jira: STUDIO-4678 Change-Id: Iff2273b464db939a2b5e19f8791bd2a4d67ce8c1 (cherry picked from commit fe4b1f79faeade42300622367fb23d7bd1079785) --- src/libslic3r/libslic3r.h | 1 + src/slic3r/GUI/GLCanvas3D.cpp | 49 +++---------------------- src/slic3r/GUI/GLCanvas3D.hpp | 3 -- src/slic3r/GUI/Jobs/ArrangeJob.cpp | 40 ++++++++++++++++++--- src/slic3r/GUI/PartPlate.cpp | 58 ++++++++++++++++++++++++++++-- src/slic3r/GUI/PartPlate.hpp | 6 +++- src/slic3r/GUI/Selection.cpp | 2 +- 7 files changed, 103 insertions(+), 56 deletions(-) diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 1bbfec886..37545b761 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -73,6 +73,7 @@ static constexpr double INSET_OVERLAP_TOLERANCE = 0.4; //FIXME This is quite a lot. static constexpr double EXTERNAL_INFILL_MARGIN = 3; static constexpr double BRIDGE_INFILL_MARGIN = 1; +static constexpr double WIPE_TOWER_MARGIN = 15.; //FIXME Better to use an inline function with an explicit return type. //inline coord_t scale_(coordf_t v) { return coord_t(floor(v / SCALING_FACTOR + 0.5f)); } #define scale_(val) ((val) / SCALING_FACTOR) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a5eea065d..b8848c5be 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1737,45 +1737,6 @@ bool GLCanvas3D::make_current_for_postinit() { return _set_current(); } -Points GLCanvas3D::estimate_wipe_tower_points(int plate_index, bool global) const -{ - PartPlateList & ppl = wxGetApp().plater()->get_partplate_list(); - DynamicPrintConfig &proj_cfg = wxGetApp().preset_bundle->project_config; - auto & print = wxGetApp().plater()->get_partplate_list().get_current_fff_print(); - int plate_count = ppl.get_plate_count(); - float x = dynamic_cast(proj_cfg.option("wipe_tower_x"))->get_at(plate_index); - float y = dynamic_cast(proj_cfg.option("wipe_tower_y"))->get_at(plate_index); - if (plate_index >= plate_count) { plate_index = 0; } - float w = dynamic_cast(m_config->option("prime_tower_width"))->value; - float v = dynamic_cast(m_config->option("prime_volume"))->value; - const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; - Vec3d wipe_tower_size = ppl.get_plate(plate_index)->estimate_wipe_tower_size(print_cfg, w, v); - - if (wipe_tower_size(1) == 0) { - // when depth is unavailable (no items on this plate), we have to estimate the depth using the extruder number of all plates - std::set extruder_ids; - if (global) { - auto objs = wxGetApp().obj_list()->objects(); - for (ModelObject *obj : *objs) { - for (ModelVolume *volume : obj->volumes) { - std::vector es = volume->get_extruders(); - extruder_ids.insert(es.begin(), es.end()); - } - } - } else { - PartPlate* pl = ppl.get_plate(plate_index); - std::vector es = pl->get_extruders(); - extruder_ids.insert(es.begin(), es.end()); - } - int extruder_size = extruder_ids.size(); - wipe_tower_size(1) = extruder_size * print.wipe_tower_data(extruder_size).depth + 2 * print.wipe_tower_data().brim_width; - } - Vec3d plate_origin = ppl.get_plate(plate_index)->get_origin(); - Point wt_min_corner{scale_(x), scale_(y)}; - Point wt_max_corner(scale_(x + wipe_tower_size(0)), scale_(y + wipe_tower_size(1))); - return {wt_min_corner, {wt_max_corner.x(), wt_min_corner.y()}, wt_max_corner, {wt_min_corner.x(), wt_max_corner.y()}}; -} - void GLCanvas3D::render(bool only_init) { if (m_in_render) { @@ -2639,7 +2600,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config; Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, v); - const float margin = 15.f; + const float margin = WIPE_TOWER_MARGIN; BoundingBoxf3 plate_bbox = wxGetApp().plater()->get_partplate_list().get_plate(plate_id)->get_bounding_box(); coordf_t plate_bbox_x_max_local_coord = plate_bbox.max(0) - plate_origin(0); coordf_t plate_bbox_y_max_local_coord = plate_bbox.max(1) - plate_origin(1); @@ -4913,10 +4874,10 @@ GLCanvas3D::WipeTowerInfo GLCanvas3D::get_wipe_tower_info(int plate_idx) const wti.m_bb.offset((brim_width)); // BBS: the wipe tower pos might be outside bed - PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_curr_plate(); - BoundingBoxf3 build_volume = plate->get_build_volume(); - wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, build_volume.max.x() - wti.m_bb.size().x()); - wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, build_volume.max.y() - wti.m_bb.size().y()); + PartPlate* plate = wxGetApp().plater()->get_partplate_list().get_plate(plate_idx); + Vec2d plate_size = plate->get_size(); + wti.m_pos.x() = std::clamp(wti.m_pos.x(), 0.0, plate_size(0) - wti.m_bb.size().x()); + wti.m_pos.y() = std::clamp(wti.m_pos.y(), 0.0, plate_size(1) - wti.m_bb.size().y()); // BBS: add partplate logic wti.m_plate_idx = plate_idx; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 0a5a8ba24..074a4906e 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -1083,9 +1083,6 @@ public: bool make_current_for_postinit(); - //BBS - Points estimate_wipe_tower_points(int plate_index, bool global = true) const; - private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index c9f3dc3d9..75b6120b4 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -57,7 +57,7 @@ public: ret.is_wipe_tower = true; ++ret.priority; - BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose(); + BOOST_LOG_TRIVIAL(debug) << " arrange: wipe tower info:" << m_bb << ", m_pos: " << m_pos.transpose(); return ret; } @@ -240,6 +240,21 @@ void ArrangeJob::prepare_all() { plate_list.preprocess_exclude_areas(m_unselected, MAX_NUM_PLATES); } +arrangement::ArrangePolygon estimate_wipe_tower_info(int plate_index, std::set& extruder_ids) +{ + PartPlateList& ppl = wxGetApp().plater()->get_partplate_list(); + const auto& full_config = wxGetApp().preset_bundle->full_config(); + int plate_count = ppl.get_plate_count(); + int plate_index_valid = std::min(plate_index, plate_count - 1); + + // we have to estimate the depth using the extruder number of all plates + int extruder_size = extruder_ids.size(); + + auto arrange_poly = ppl.get_plate(plate_index_valid)->estimate_wipe_tower_polygon(full_config, plate_index, extruder_size); + arrange_poly.bed_idx = plate_index; + return arrange_poly; +} + // 准备料塔。逻辑如下: // 1. 以下几种情况不需要料塔: // 1)料塔被禁用, @@ -299,6 +314,14 @@ void ArrangeJob::prepare_wipe_tower() wipe_tower_ap.is_virt_object = true; wipe_tower_ap.is_wipe_tower = true; const GLCanvas3D* canvas3D = static_cast(m_plater->canvas3D()); + + std::set extruder_ids; + PartPlateList& ppl = wxGetApp().plater()->get_partplate_list(); + int plate_count = ppl.get_plate_count(); + if (!only_on_partplate) { + extruder_ids = ppl.get_extruders(true); + } + for (int bedid = 0; bedid < MAX_NUM_PLATES; bedid++) { if (auto wti = get_wipe_tower(*m_plater, bedid)) { // wipe tower is already there @@ -307,8 +330,14 @@ void ArrangeJob::prepare_wipe_tower() m_unselected.emplace_back(wipe_tower_ap); } else if (need_wipe_tower) { - wipe_tower_ap.translation = { 0, 0 }; - wipe_tower_ap.poly.contour.points = canvas3D->estimate_wipe_tower_points(bedid, !only_on_partplate); + if (only_on_partplate) { + int plate_index_valid = std::min(bedid, plate_count - 1); + PartPlate* pl = ppl.get_plate(plate_index_valid); + auto plate_extruders = pl->get_extruders(true); + extruder_ids.clear(); + extruder_ids.insert(plate_extruders.begin(), plate_extruders.end()); + } + wipe_tower_ap = estimate_wipe_tower_info(bedid, extruder_ids); wipe_tower_ap.bed_idx = bedid; m_unselected.emplace_back(wipe_tower_ap); } @@ -365,7 +394,7 @@ void ArrangeJob::prepare_partplate() { //skip this object due to be not in current plate, treated as locked ap.itemid = m_locked.size(); m_locked.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(": skip locked instance, obj_id %1%, name %2%") % oidx % mo->name; } } } @@ -523,7 +552,8 @@ void ArrangeJob::process() } BOOST_LOG_TRIVIAL(debug) << "items unselected before arrange: "; for (auto item : m_unselected) - BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose(); + BOOST_LOG_TRIVIAL(debug) << item.name << ", bed: " << item.bed_idx << ", trans: " << item.translation.transpose() + <<", bbox:"<(config.option("wipe_tower_x"))->get_at(plate_index); + float y = dynamic_cast(config.option("wipe_tower_y"))->get_at(plate_index); + float w = dynamic_cast(config.option("prime_tower_width"))->value; + //float a = dynamic_cast(config.option("wipe_tower_rotation_angle"))->value; + float v = dynamic_cast(config.option("prime_volume"))->value; + Vec3d wipe_tower_size = estimate_wipe_tower_size(config, w, v, plate_extruder_size); + int plate_width=m_width, plate_depth=m_depth; + float depth = wipe_tower_size(1); + float margin = WIPE_TOWER_MARGIN, wp_brim_width = 0.f; + const ConfigOption* wipe_tower_brim_width_opt = config.option("prime_tower_brim_width"); + if (wipe_tower_brim_width_opt) { + wp_brim_width = wipe_tower_brim_width_opt->getFloat(); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("arrange wipe_tower: wp_brim_width %1%") % wp_brim_width; + } + + x = std::clamp(x, margin, (float)plate_width - w - margin - wp_brim_width); + y = std::clamp(y, margin, (float)plate_depth - depth - margin - wp_brim_width); + + arrangement::ArrangePolygon wipe_tower_ap; + Polygon ap({ + {scaled(x - wp_brim_width), scaled(y - wp_brim_width)}, + {scaled(x + w + wp_brim_width), scaled(y - wp_brim_width)}, + {scaled(x + w + wp_brim_width), scaled(y + depth + wp_brim_width)}, + {scaled(x - wp_brim_width), scaled(y + depth + wp_brim_width)} + }); + wipe_tower_ap.bed_idx = plate_index; + wipe_tower_ap.setter = NULL; // do not move wipe tower + + wipe_tower_ap.poly.contour = std::move(ap); + wipe_tower_ap.translation = { scaled(0.f), scaled(0.f) }; + //wipe_tower_ap.rotation = a; + wipe_tower_ap.name = "WipeTower"; + wipe_tower_ap.is_virt_object = true; + wipe_tower_ap.is_wipe_tower = true; + + return wipe_tower_ap; +} + bool PartPlate::operator<(PartPlate& plate) const { int index = plate.get_index(); @@ -3702,6 +3742,20 @@ std::vector PartPlateList::get_nonempty_plates_slic return nonempty_plates_slice_result; } +std::set PartPlateList::get_extruders(bool conside_custom_gcode) const +{ + int plate_count = get_plate_count(); + std::set extruder_ids; + + for (size_t i = 0; i < plate_count; i++) { + auto plate_extruders = m_plate_list[i]->get_extruders(conside_custom_gcode); + extruder_ids.insert(plate_extruders.begin(), plate_extruders.end()); + } + + return extruder_ids; +} + + //select plate int PartPlateList::select_plate(int index) { @@ -3795,7 +3849,7 @@ double PartPlateList::plate_stride_y() } //get the plate counts, not including the invalid plate -int PartPlateList::get_plate_count() +int PartPlateList::get_plate_count() const { int ret = 0; @@ -4353,7 +4407,7 @@ bool PartPlateList::preprocess_arrange_polygon_other_locked(int obj_index, int i arrange_polygon.col = i % m_plate_cols; arrange_polygon.translation(X) -= scaled(plate_stride_x() * arrange_polygon.col); arrange_polygon.translation(Y) += scaled(plate_stride_y() * arrange_polygon.row); - BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col; + //BOOST_LOG_TRIVIAL(debug) << __FUNCTION__ << boost::format(": obj_id %1% instance_id %2% in plate %3%, locked %4%, row %5%, col %6%\n") % obj_index % instance_index % i % locked % arrange_polygon.row % arrange_polygon.col; return locked; } } diff --git a/src/slic3r/GUI/PartPlate.hpp b/src/slic3r/GUI/PartPlate.hpp index 0cbe5ce51..0d0b05465 100644 --- a/src/slic3r/GUI/PartPlate.hpp +++ b/src/slic3r/GUI/PartPlate.hpp @@ -288,11 +288,13 @@ public: void set_pos_and_size(Vec3d& origin, int width, int depth, int height, bool with_instance_move); // BBS + Vec2d get_size() const { return Vec2d(m_width, m_depth); } ModelObjectPtrs get_objects() { return m_model->objects; } ModelInstance* get_instance(int obj_id, int instance_id); Vec3d get_origin() { return m_origin; } Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int plate_extruder_size = 0) const; + arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, int plate_extruder_size = 0) const; std::vector get_extruders(bool conside_custom_gcode = false) const; std::vector get_extruders_under_cli(bool conside_custom_gcode, DynamicPrintConfig& full_config) const; std::vector get_extruders_without_support(bool conside_custom_gcode = false) const; @@ -687,11 +689,13 @@ public: Vec2d get_current_shape_position() { return compute_shape_position(m_current_plate, m_plate_cols); } Pointfs get_exclude_area() { return m_exclude_areas; } + std::set get_extruders(bool conside_custom_gcode = false) const; + //select plate int select_plate(int index); //get the plate counts, not including the invalid plate - int get_plate_count(); + int get_plate_count() const; //update the plate cols due to plate count change void update_plate_cols(); diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index cd8d41400..5c8b62deb 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -899,7 +899,7 @@ void Selection::translate(const Vec3d& displacement, bool local) Vec3d tower_size = v.bounding_box().size(); Vec3d tower_origin = m_cache.volumes_data[i].get_volume_position(); Vec3d actual_displacement = displacement; - const double margin = 15.f; + const double margin = WIPE_TOWER_MARGIN; if (!local) actual_displacement = (m_cache.volumes_data[i].get_instance_rotation_matrix() * m_cache.volumes_data[i].get_instance_scale_matrix() * m_cache.volumes_data[i].get_instance_mirror_matrix()).inverse() * displacement;