Allow rotation of multiple selected items. Disable auto positioning
This commit is contained in:
parent
804758dfed
commit
649dfca8d6
6 changed files with 99 additions and 44 deletions
|
@ -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<const GLCanvas3D*>(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<double>((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<const GLCanvas3D*>(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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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<Vec2d> rot;
|
||||
ObjRot(size_t id): idx{id}, rot{} {}
|
||||
};
|
||||
|
||||
std::vector<ObjRot> m_selected_object_ids;
|
||||
|
||||
protected:
|
||||
|
||||
void prepare() override;
|
||||
|
|
|
@ -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<double>();
|
||||
(*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<double>(),
|
||||
movable[i].rotation);
|
||||
for (auto & m : movable)
|
||||
m.apply();
|
||||
}
|
||||
|
||||
void Plater::priv::split_object()
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue