diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index 5c213c110..c4f2fcaca 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -192,7 +192,7 @@ public: return Unit(width())*height(); } - static inline _Box infinite(const P ¢er); + static inline _Box infinite(const P ¢er = {TCoord

(0), TCoord

(0)}); }; template struct PointType<_Box> { diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index ab018f3f8..f106ad3d8 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -908,7 +908,8 @@ private: item.removeOffset(); }); - if(stopfn_ && !stopfn_()) { // Ignore results if nesting was stopped. + if(!stopfn_ || (stopfn_ && !stopfn_())) { + // Ignore results if nesting was stopped. const PackGroup& bins = lastResult(); unsigned binidx = 0; for(auto& bin : bins) { diff --git a/src/libslic3r/Arrange.cpp b/src/libslic3r/Arrange.cpp index 84a406fd9..f778a7f75 100644 --- a/src/libslic3r/Arrange.cpp +++ b/src/libslic3r/Arrange.cpp @@ -573,7 +573,7 @@ inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w) // a stop predicate can be also be passed to control the process. bool arrange(ArrangeablePtrs & arrangables, const ArrangeablePtrs & excludes, - coord_t min_obj_distance, + coord_t min_obj_dist, const BedShapeHint & bedhint, std::function progressind, std::function stopcondition) @@ -615,13 +615,14 @@ bool arrange(ArrangeablePtrs & arrangables, arrangeable, items, // callback called by arrange to apply the result on the arrangeable - [arrangeable, &binwidth](const Item &itm, unsigned binidx) { + [arrangeable, &binwidth, &ret](const Item &itm, unsigned binidx) { + ret = !binidx; // Return value false more bed is required clppr::cInt stride = binidx * stride_padding(binwidth); clppr::IntPoint offs = itm.translation(); arrangeable->apply_arrange_result({unscaled(offs.X + stride), unscaled(offs.Y)}, - itm.rotation()); + itm.rotation(), binidx); }); } @@ -629,66 +630,61 @@ bool arrange(ArrangeablePtrs & arrangables, process_arrangeable(fixed, fixeditems, nullptr); // Integer ceiling the min distance from the bed perimeters - coord_t md = min_obj_distance - SCALED_EPSILON; + coord_t md = min_obj_dist - SCALED_EPSILON; md = (md % 2) ? md / 2 + 1 : md / 2; - auto& cfn = stopcondition; + auto &cfn = stopcondition; + auto &pri = progressind; switch (bedhint.type) { -// case BedShapeType::BOX: { -// // Create the arranger for the box shaped bed -// BoundingBox bbb = bedhint.shape.box; -// bbb.min -= Point{md, md}, bbb.max += Point{md, md}; -// Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}}; -// binwidth = coord_t(binbb.width()); + case BedShapeType::BOX: { + // Create the arranger for the box shaped bed + BoundingBox bbb = bedhint.shape.box; + bbb.min -= Point{md, md}, bbb.max += Point{md, md}; + Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}}; + binwidth = coord_t(binbb.width()); -// _arrange(items, fixeditems, binbb, min_obj_distance, progressind, cfn); -// break; -// } -// case BedShapeType::CIRCLE: { -// auto c = bedhint.shape.circ; -// auto cc = to_lnCircle(c); -// binwidth = scaled(c.radius()); + _arrange(items, fixeditems, binbb, min_obj_dist, pri, cfn); + break; + } + case BedShapeType::CIRCLE: { + auto c = bedhint.shape.circ; + auto cc = to_lnCircle(c); + binwidth = scaled(c.radius()); -// _arrange(items, fixeditems, cc, min_obj_distance, progressind, cfn); -// break; -// } -// case BedShapeType::IRREGULAR: { -// auto ctour = Slic3rMultiPoint_to_ClipperPath(bedhint.shape.polygon); -// auto irrbed = sl::create(std::move(ctour)); -// BoundingBox polybb(bedhint.shape.polygon); -// binwidth = (polybb.max(X) - polybb.min(X)); + _arrange(items, fixeditems, cc, min_obj_dist, pri, cfn); + break; + } + case BedShapeType::IRREGULAR: { + auto ctour = Slic3rMultiPoint_to_ClipperPath(bedhint.shape.polygon); + auto irrbed = sl::create(std::move(ctour)); + BoundingBox polybb(bedhint.shape.polygon); + binwidth = (polybb.max(X) - polybb.min(X)); -// _arrange(items, fixeditems, irrbed, min_obj_distance, progressind, cfn); -// break; -// } -// case BedShapeType::INFINITE: { -// const InfiniteBed& nobin = bedhint.shape.infinite; -// Box infbb{{nobin.center.x(), nobin.center.y()}}; + _arrange(items, fixeditems, irrbed, min_obj_dist, pri, cfn); + break; + } + case BedShapeType::INFINITE: { + const InfiniteBed& nobin = bedhint.shape.infinite; + auto infbb = Box::infinite({nobin.center.x(), nobin.center.y()}); -// _arrange(items, fixeditems, infbb, min_obj_distance, progressind, cfn); -// break; -// } -// case BedShapeType::UNKNOWN: { -// // We know nothing about the bed, let it be infinite and zero centered -// _arrange(items, fixeditems, Box{}, min_obj_distance, progressind, cfn); -// break; -// } - default: { - Box infbb = Box::infinite({bedhint.shape.box.center().x(), bedhint.shape.box.center().y()}); - - _arrange(items, fixeditems, infbb, min_obj_distance, progressind, cfn); + _arrange(items, fixeditems, infbb, min_obj_dist, pri, cfn); + break; + } + case BedShapeType::UNKNOWN: { + // We know nothing about the bed, let it be infinite and zero centered + _arrange(items, fixeditems, Box::infinite(), min_obj_dist, pri, cfn); break; } }; - if(stopcondition()) return false; + if(stopcondition && stopcondition()) return false; return ret; } // Arrange, without the fixed items (excludes) -bool arrange(ArrangeablePtrs & inp, +bool arrange(ArrangeablePtrs & inp, coord_t min_d, const BedShapeHint & bedhint, std::function prfn, diff --git a/src/libslic3r/Arrange.hpp b/src/libslic3r/Arrange.hpp index 87514a600..337a7d959 100644 --- a/src/libslic3r/Arrange.hpp +++ b/src/libslic3r/Arrange.hpp @@ -58,7 +58,7 @@ public: virtual ~Arrangeable() = default; /// Apply the result transformation calculated by the arrangement. - virtual void apply_arrange_result(Vec2d offset, double rotation_rads) = 0; + virtual void apply_arrange_result(Vec2d offset, double rotation_rads, unsigned bed_num) = 0; /// Get the 2D silhouette to arrange and an initial offset and rotation virtual std::tuple get_arrange_polygon() const = 0; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 51759640c..d0ed0bc88 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -559,10 +559,10 @@ public: // ///////////////////////////////////////////////////////////////////////// // Getting the input polygon for arrange - virtual std::tuple get_arrange_polygon() const final; + virtual std::tuple get_arrange_polygon() const override; // Apply the arrange result on the ModelInstance - virtual void apply_arrange_result(Vec2d offs, double rot_rads) final + virtual void apply_arrange_result(Vec2d offs, double rot_rads, unsigned /*bed_num*/) override { // write the transformation data into the model instance set_rotation(Z, rot_rads); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4e3093489..e5b2b38f8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5739,7 +5739,7 @@ const SLAPrint* GLCanvas3D::sla_print() const return (m_process == nullptr) ? nullptr : m_process->sla_print(); } -void GLCanvas3D::WipeTowerInfo::apply_arrange_result(Vec2d offset, double rotation_rads) +void GLCanvas3D::WipeTowerInfo::apply_arrange_result(Vec2d offset, double rotation_rads, unsigned /*bed_num*/) { m_pos = offset; m_rotation = rotation_rads; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 524e0c883..8f419a16d 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -624,9 +624,9 @@ public: return !std::isnan(m_pos.x()) && !std::isnan(m_pos.y()); } - virtual void apply_arrange_result(Vec2d offset, double rotation_rads) final; + virtual void apply_arrange_result(Vec2d offset, double rotation_rads, unsigned /*bed_num*/) override; - virtual std::tuple get_arrange_polygon() const final + virtual std::tuple get_arrange_polygon() const override { Polygon p({ {coord_t(0), coord_t(0)}, diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 08c70dbe0..a49b541b5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2482,33 +2482,35 @@ arrangement::BedShapeHint Plater::priv::get_bed_shape_hint() const { return bedshape; } -void Plater::priv::ExclusiveJobGroup::ArrangeJob::process() { - static const auto arrangestr = _(L("Arranging")); - - // FIXME: I don't know how to obtain the minimum distance, it depends - // on printer technology. I guess the following should work but it crashes. - double dist = 6; // PrintConfig::min_object_distance(config); - if (plater().printer_technology == ptFFF) { - dist = PrintConfig::min_object_distance(plater().config); - } - - coord_t min_obj_distance = scaled(dist); +void Plater::priv::ExclusiveJobGroup::ArrangeJob::process() { auto count = unsigned(m_selected.size()); - arrangement::BedShapeHint bedshape = plater().get_bed_shape_hint(); + plater().model.arrange_objects(6.f, nullptr); +// static const auto arrangestr = _(L("Arranging")); - try { - arrangement::arrange(m_selected, m_unselected, min_obj_distance, - bedshape, - [this, count](unsigned st) { - if (st > 0) // will not finalize after last one - update_status(count - st, arrangestr); - }, - [this]() { return was_canceled(); }); - } catch (std::exception & /*e*/) { - GUI::show_error(plater().q, - _(L("Could not arrange model objects! " - "Some geometries may be invalid."))); - } +// // FIXME: I don't know how to obtain the minimum distance, it depends +// // on printer technology. I guess the following should work but it crashes. +// double dist = 6; // PrintConfig::min_object_distance(config); +// if (plater().printer_technology == ptFFF) { +// dist = PrintConfig::min_object_distance(plater().config); +// } + +// coord_t min_obj_distance = scaled(dist); +// auto count = unsigned(m_selected.size()); +// arrangement::BedShapeHint bedshape = plater().get_bed_shape_hint(); + +// try { +// arrangement::arrange(m_selected, m_unselected, min_obj_distance, +// bedshape, +// [this, count](unsigned st) { +// if (st > 0) // will not finalize after last one +// update_status(count - st, arrangestr); +// }, +// [this]() { return was_canceled(); }); +// } catch (std::exception & /*e*/) { +// GUI::show_error(plater().q, +// _(L("Could not arrange model objects! " +// "Some geometries may be invalid."))); +// } // finalize just here. update_status(int(count),