diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index 084ac514d6..1c88c36b07 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -2267,7 +2267,7 @@ int CLI::run(int argc, char **argv) Model original_model; std::set> backup_set; bool finished_arrange = false, first_run = true; - Slic3r::GUI::PartPlate* cur_plate; + Slic3r::GUI::PartPlate* cur_plate = nullptr; int low_duplicate_count = 0, up_duplicate_count = duplicate_count, arrange_count = 0; arrange_cfg.is_seq_print = false; @@ -2476,9 +2476,15 @@ int CLI::run(int argc, char **argv) else arrange_cfg.min_obj_distance = scaled(22.0); + if (auto printer_structure_opt = m_print_config.option>("printer_structure")) { + arrange_cfg.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3); + } + 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); + arrangement::update_selected_items_axis_align(selected, &m_print_config, arrange_cfg); + beds=get_shrink_bedpts(&m_print_config, arrange_cfg); { diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 4703401523..e23648bbbb 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -134,6 +134,97 @@ void update_unselected_items_inflation(ArrangePolygons& unselected, const Dynami : (ap.is_extrusion_cali_object ? 0 : scaled_exclusion_gap); }); } +void update_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params) +{ + // now only need to consider "Align to x axis" + if (!params.align_to_y_axis) + return; + + for (ArrangePolygon& ap : selected) { + bool validResult = false; + double angle = 0.0; + { + const auto& pts = ap.transformed_poly().contour; + int lpt = pts.size(); + double a00 = 0, a10 = 0, a01 = 0, a20 = 0, a11 = 0, a02 = 0, a30 = 0, a21 = 0, a12 = 0, a03 = 0; + double xi, yi, xi2, yi2, xi_1, yi_1, xi_12, yi_12, dxy, xii_1, yii_1; + xi_1 = pts.back().x(); + yi_1 = pts.back().y(); + + xi_12 = xi_1 * xi_1; + yi_12 = yi_1 * yi_1; + + for (int i = 0; i < lpt; i++) { + xi = pts[i].x(); + yi = pts[i].y(); + + xi2 = xi * xi; + yi2 = yi * yi; + dxy = xi_1 * yi - xi * yi_1; + xii_1 = xi_1 + xi; + yii_1 = yi_1 + yi; + + a00 += dxy; + a10 += dxy * xii_1; + a01 += dxy * yii_1; + a20 += dxy * (xi_1 * xii_1 + xi2); + a11 += dxy * (xi_1 * (yii_1 + yi_1) + xi * (yii_1 + yi)); + a02 += dxy * (yi_1 * yii_1 + yi2); + a30 += dxy * xii_1 * (xi_12 + xi2); + a03 += dxy * yii_1 * (yi_12 + yi2); + a21 += dxy * (xi_12 * (3 * yi_1 + yi) + 2 * xi * xi_1 * yii_1 + xi2 * (yi_1 + 3 * yi)); + a12 += dxy * (yi_12 * (3 * xi_1 + xi) + 2 * yi * yi_1 * xii_1 + yi2 * (xi_1 + 3 * xi)); + xi_1 = xi; + yi_1 = yi; + xi_12 = xi2; + yi_12 = yi2; + } + + if (std::abs(a00) > EPSILON) { + double db1_2, db1_6, db1_12, db1_24, db1_20, db1_60; + double m00, m10, m01, m20, m11, m02, m30, m21, m12, m03; + if (a00 > 0) { + db1_2 = 0.5; + db1_6 = 0.16666666666666666666666666666667; + db1_12 = 0.083333333333333333333333333333333; + db1_24 = 0.041666666666666666666666666666667; + db1_20 = 0.05; + db1_60 = 0.016666666666666666666666666666667; + } + else { + db1_2 = -0.5; + db1_6 = -0.16666666666666666666666666666667; + db1_12 = -0.083333333333333333333333333333333; + db1_24 = -0.041666666666666666666666666666667; + db1_20 = -0.05; + db1_60 = -0.016666666666666666666666666666667; + } + m00 = a00 * db1_2; + m10 = a10 * db1_6; + m01 = a01 * db1_6; + m20 = a20 * db1_12; + m11 = a11 * db1_24; + m02 = a02 * db1_12; + m30 = a30 * db1_20; + m21 = a21 * db1_60; + m12 = a12 * db1_60; + m03 = a03 * db1_20; + + double cx = m10 / m00; + double cy = m01 / m00; + + double a = m20 / m00 - cx * cx; + double b = m11 / m00 - cx * cy; + double c = m02 / m00 - cy * cy; + + angle = std::atan2(2 * b, (a - c)) / 2; + validResult = true; + } + } + if (validResult) { ap.rotation += (PI / 2 - angle); } + } +} + //it will bed accurate after call update_params Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params) { diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index be3d67e971..523e8baa7b 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -120,6 +120,7 @@ struct ArrangeParams { bool allow_multi_materials_on_same_plate = true; bool avoid_extrusion_cali_region = true; bool is_seq_print = false; + bool align_to_y_axis = false; float bed_shrink_x = 0; float bed_shrink_y = 0; float brim_skirt_distance = 0; @@ -173,6 +174,8 @@ 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_selected_items_axis_align(ArrangePolygons& selected, const DynamicPrintConfig* print_cfg, const ArrangeParams& params); + Points get_shrink_bedpts(const DynamicPrintConfig* print_cfg, const ArrangeParams& params); /** diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ff2d09cd73..f91450a11b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5384,6 +5384,7 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo std::string bed_shrink_x_key = "bed_shrink_x", bed_shrink_y_key = "bed_shrink_y"; std::string multi_material_key = "allow_multi_materials_on_same_plate"; std::string avoid_extrusion_key = "avoid_extrusion_cali_region"; + std::string align_to_y_axis_key = "align_to_y_axis"; std::string postfix; //BBS: bool seq_print = false; @@ -5450,6 +5451,22 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo settings_out.avoid_extrusion_cali_region = false; } + // Align to Y axis. Only enable this option when auto rotation not enabled + { + if (settings_out.enable_rotation) { // do not allow align to Y axis if rotation is enabled + imgui->disabled_begin(true); + settings_out.align_to_y_axis = false; + } + + if (imgui->bbl_checkbox(_L("Align to Y axis"), settings.align_to_y_axis)) { + settings_out.align_to_y_axis = settings.align_to_y_axis; + appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0"); + settings_changed = true; + } + + if (settings_out.enable_rotation == true) { imgui->disabled_end(); } + } + ImGui::Separator(); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(15.0f, 10.0f)); if (imgui->button(_L("Arrange"))) { @@ -5464,8 +5481,16 @@ bool GLCanvas3D::_render_arrange_menu(float left, float right, float bottom, flo settings_out.distance = std::max(dist_min, settings_out.distance); //BBS: add specific arrange settings if (seq_print) settings_out.is_seq_print = true; - appcfg->set("arrange", dist_key.c_str(), float_to_string_decimal_point(settings_out.distance)); - appcfg->set("arrange", rot_key.c_str(), settings_out.enable_rotation? "1" : "0"); + + if (auto printer_structure_opt = wxGetApp().preset_bundle->printers.get_edited_preset().config.option>("printer_structure")) { + settings_out.align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3); + } + else + settings_out.align_to_y_axis = false; + + appcfg->set("arrange", dist_key, float_to_string_decimal_point(settings_out.distance)); + appcfg->set("arrange", rot_key, settings_out.enable_rotation ? "1" : "0"); + appcfg->set("arrange", align_to_y_axis_key, settings_out.align_to_y_axis ? "1" : "0"); settings_changed = true; } ImGui::PopStyleVar(1); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index a58d6f324c..7fff327d6d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -483,6 +483,7 @@ public: bool is_seq_print = false; float bed_shrink_x = 0.f; float bed_shrink_y = 0.f; + bool align_to_y_axis = false; }; struct OrientSettings @@ -626,7 +627,6 @@ private: return *ptr; } - ArrangeSettings &get_arrange_settings() { return get_arrange_settings(this); } //BBS:record key botton frequency @@ -652,6 +652,7 @@ public: } void load_arrange_settings(); + ArrangeSettings& get_arrange_settings() { return get_arrange_settings(this); } class SequentialPrintClearance { diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 13c74c0bc7..8e623dae3b 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -509,6 +509,7 @@ void ArrangeJob::process() update_arrange_params(params, *m_plater, m_selected); update_selected_items_inflation(m_selected, 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); Points bedpts = get_shrink_bedpts(m_plater->config(),params); double scaled_exclusion_gap = scale_(1); @@ -751,6 +752,7 @@ arrangement::ArrangeParams init_arrange_params(Plater *p) 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; int state = p->get_prepare_state(); if (state == Job::JobPrepareState::PREPARE_STATE_MENU) { diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index ae56866cea..d51822296c 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -82,7 +82,6 @@ arrangement::ArrangeParams init_arrange_params(Plater *p); void update_arrange_params(arrangement::ArrangeParams ¶ms, const Plater &p, const arrangement::ArrangePolygons &selected); - }} // namespace Slic3r::GUI #endif // ARRANGEJOB_HPP diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3d4085e017..5d32d3b8ca 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1194,8 +1194,17 @@ void Sidebar::update_presets(Preset::Type preset_type) printer_tab->update(); } - bool isBBL = wxGetApp().preset_bundle->printers.get_edited_preset().is_bbl_vendor_preset(wxGetApp().preset_bundle); + Preset& printer_preset = wxGetApp().preset_bundle->printers.get_edited_preset(); + + bool isBBL = printer_preset.is_bbl_vendor_preset(wxGetApp().preset_bundle); wxGetApp().mainframe->show_calibration_button(!isBBL); + + if (auto printer_structure_opt = printer_preset.config.option>("printer_structure")) { + wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = (printer_structure_opt->value == PrinterStructure::psI3); + } + else + wxGetApp().plater()->get_current_canvas3D()->get_arrange_settings().align_to_y_axis = false; + break; } @@ -5803,7 +5812,7 @@ void Plater::priv::on_select_preset(wxCommandEvent &evt) //! combo->GetString(combo->GetSelection()) //! instead of //! combo->GetStringSelection().ToUTF8().data()); - + std::string preset_name = wxGetApp().preset_bundle->get_preset_name_by_alias(preset_type, Preset::remove_suffix_modified(combo->GetString(selection).ToUTF8().data()));