diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 3f1207b47..391c1fe28 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -78,7 +78,7 @@ void ArrangeJob::prepare_all() { for (ModelObject *obj: m_plater->model().objects) for (ModelInstance *mi : obj->instances) { ArrangePolygons & cont = mi->printable ? m_selected : m_unprintable; - cont.emplace_back(get_arrange_poly(PtrWrapper{mi}, m_plater)); + cont.emplace_back(get_arrange_poly(mi, m_plater)); } if (auto wti = get_wipe_tower_arrangepoly(*m_plater)) @@ -111,7 +111,7 @@ void ArrangeJob::prepare_selected() { for (size_t i = 0; i < inst_sel.size(); ++i) { ArrangePolygon &&ap = - get_arrange_poly(PtrWrapper{mo->instances[i]}, m_plater); + get_arrange_poly(mo->instances[i], m_plater); ArrangePolygons &cont = mo->instances[i]->printable ? (inst_sel[i] ? m_selected : @@ -161,12 +161,7 @@ void ArrangeJob::process() { static const auto arrangestr = _(L("Arranging")); - 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); + arrangement::ArrangeParams params = get_arrange_params(m_plater); auto count = unsigned(m_selected.size() + m_unprintable.size()); Points bedpts = get_bed_shape(*m_plater->config()); @@ -235,4 +230,23 @@ double bed_stride(const Plater *plater) { return scaled((1. + LOGICAL_BED_GAP) * bedwidth); } +template<> +arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst, + const Plater * plater) +{ + return get_arrange_poly(PtrWrapper{inst}, plater); +} + +arrangement::ArrangeParams get_arrange_params(Plater *p) +{ + const GLCanvas3D::ArrangeSettings &settings = + static_cast(p->canvas3D())->get_arrange_settings(); + + arrangement::ArrangeParams params; + params.allow_rotations = settings.enable_rotation; + params.min_obj_distance = scaled(settings.distance); + + return params; +} + }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index 38aafb52c..7fa4b927e 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -4,7 +4,11 @@ #include "PlaterJob.hpp" #include "libslic3r/Arrange.hpp" -namespace Slic3r { namespace GUI { +namespace Slic3r { + +class ModelInstance; + +namespace GUI { class ArrangeJob : public PlaterJob { @@ -89,6 +93,11 @@ arrangement::ArrangePolygon get_arrange_poly(T obj, const Plater *plater) return ap; } +template<> +arrangement::ArrangePolygon get_arrange_poly(ModelInstance *inst, + const Plater * plater); + +arrangement::ArrangeParams get_arrange_params(Plater *p); }} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/RotoptimizeJob.cpp b/src/slic3r/GUI/Jobs/RotoptimizeJob.cpp index 04144112e..a670affef 100644 --- a/src/slic3r/GUI/Jobs/RotoptimizeJob.cpp +++ b/src/slic3r/GUI/Jobs/RotoptimizeJob.cpp @@ -32,36 +32,59 @@ void RotoptimizeJob::prepare() m_method_id = std::max(size_t(0), std::min(get_methods_count() - 1, m_method_id)); m_default_print_cfg = wxGetApp().preset_bundle->full_config(); + + const auto &sel = m_plater->get_selection().get_content(); + + m_selected_object_ids.clear(); + m_selected_object_ids.reserve(sel.size()); + for (auto &[obj_idx, ignore] : sel) + m_selected_object_ids.emplace_back(obj_idx); } void RotoptimizeJob::process() { - int obj_idx = m_plater->get_selected_object_idx(); - if (obj_idx < 0) - return; - - ModelObject *o = m_plater->model().objects[size_t(obj_idx)]; - - if (!o) return; - + int prev_status = 0; auto params = sla::RotOptimizeParams{} .accuracy(m_accuracy) .print_config(&m_default_print_cfg) - .statucb([this](int s) { + .statucb([this, &prev_status](int s) + { if (s > 0 && s < 100) - update_status(s, _(L("Searching for optimal orientation"))); + update_status(prev_status + s / m_selected_object_ids.size(), + _(L("Searching for optimal orientation"))); return !was_canceled(); }); - Vec2d r = Methods[m_method_id].findfn(*o, params); - double mindist = 6.0; // FIXME + for (ObjRot &objrot : m_selected_object_ids) { + ModelObject *o = m_plater->model().objects[size_t(objrot.idx)]; + if (!o) continue; + + if (Methods[m_method_id].findfn) + objrot.rot = Methods[m_method_id].findfn(*o, params); + + prev_status += 100 / m_selected_object_ids.size(); + + if (was_canceled()) break; + } + + update_status(100, was_canceled() ? _(L("Orientation search canceled.")) : + _(L("Orientation found."))); +} + +void RotoptimizeJob::finalize() +{ + if (was_canceled()) return; + + for (const ObjRot &objrot : m_selected_object_ids) { + ModelObject *o = m_plater->model().objects[size_t(objrot.idx)]; + if (!o) continue; - if (!was_canceled()) { for(ModelInstance * oi : o->instances) { - oi->set_rotation({r[X], r[Y], 0.}); + if (objrot.rot) + oi->set_rotation({objrot.rot->x(), objrot.rot->y(), 0.}); auto trmatrix = oi->get_transformation().get_matrix(); Polygon trchull = o->convex_hull_2d(trmatrix); @@ -77,19 +100,13 @@ void RotoptimizeJob::process() oi->set_rotation(rt); } - m_plater->find_new_position(o->instances, scaled(mindist)); - // Correct the z offset of the object which was corrupted be // the rotation o->ensure_on_bed(); + +// m_plater->find_new_position(o->instances); } - update_status(100, was_canceled() ? _(L("Orientation search canceled.")) : - _(L("Orientation found."))); -} - -void RotoptimizeJob::finalize() -{ if (!was_canceled()) m_plater->update(); diff --git a/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp b/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp index cb9a96b56..1535d0fa6 100644 --- a/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp +++ b/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp @@ -19,7 +19,9 @@ class RotoptimizeJob : public PlaterJob static inline const FindMethod Methods[] = { { L("Best misalignment"), sla::find_best_misalignment_rotation }, - { L("Least supports"), sla::find_least_supports_rotation } + { L("Least supports"), sla::find_least_supports_rotation }, + // Just a min area bounding box that is done for all methods anyway. + { L("Z axis only"), nullptr } }; size_t m_method_id = 0; @@ -27,6 +29,15 @@ class RotoptimizeJob : public PlaterJob DynamicPrintConfig m_default_print_cfg; + struct ObjRot + { + size_t idx; + std::optional rot; + ObjRot(size_t id): idx{id}, rot{} {} + }; + + std::vector m_selected_object_ids; + protected: void prepare() override; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index a640d6e28..e0a5031c2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2669,32 +2669,36 @@ void Plater::priv::mirror(Axis axis) view3D->mirror_selection(axis); } -void Plater::find_new_position(const ModelInstancePtrs &instances, - coord_t min_d) +void Plater::find_new_position(const ModelInstancePtrs &instances) { arrangement::ArrangePolygons movable, fixed; + arrangement::ArrangeParams arr_params = get_arrange_params(this); for (const ModelObject *mo : p->model.objects) - for (const ModelInstance *inst : mo->instances) { + for (ModelInstance *inst : mo->instances) { auto it = std::find(instances.begin(), instances.end(), inst); - auto arrpoly = inst->get_arrange_polygon(); + auto arrpoly = get_arrange_poly(inst, this); if (it == instances.end()) fixed.emplace_back(std::move(arrpoly)); - else + else { + arrpoly.setter = [it](const arrangement::ArrangePolygon &p) { + if (p.is_arranged() && p.bed_idx == 0) { + Vec2d t = p.translation.cast(); + (*it)->apply_arrange_result(t, p.rotation); + } + }; movable.emplace_back(std::move(arrpoly)); + } } if (auto wt = get_wipe_tower_arrangepoly(*this)) fixed.emplace_back(*wt); - arrangement::arrange(movable, fixed, get_bed_shape(*config()), - arrangement::ArrangeParams{min_d}); + arrangement::arrange(movable, fixed, get_bed_shape(*config()), arr_params); - for (size_t i = 0; i < instances.size(); ++i) - if (movable[i].bed_idx == 0) - instances[i]->apply_arrange_result(movable[i].translation.cast(), - movable[i].rotation); + for (auto & m : movable) + m.apply(); } void Plater::priv::split_object() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index ff81dad26..16590ed9b 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -258,7 +258,7 @@ public: BoundingBoxf bed_shape_bb() const; void arrange(); - void find_new_position(const ModelInstancePtrs &instances, coord_t min_d); + void find_new_position(const ModelInstancePtrs &instances); void set_current_canvas_as_dirty(); void unbind_canvas_event_handlers();