Adapt find_new_position is WIP. Cleaning up comments.

This commit is contained in:
tamasmeszaros 2019-06-28 18:27:15 +02:00
parent 299e4f74c7
commit cb3a586deb
5 changed files with 181 additions and 301 deletions

View File

@ -67,6 +67,7 @@ class _Item {
} bb_cache_; } bb_cache_;
std::function<void(const _Item&, unsigned)> applyfn_; std::function<void(const _Item&, unsigned)> applyfn_;
bool fixed_{false};
public: public:
@ -144,6 +145,9 @@ public:
if (applyfn_) applyfn_(*this, binidx); if (applyfn_) applyfn_(*this, binidx);
} }
inline bool isFixed() const noexcept { return fixed_; }
inline void markAsFixed(bool fixed = true) { fixed_ = fixed; }
/** /**
* @brief Convert the polygon to string representation. The format depends * @brief Convert the polygon to string representation. The format depends
* on the implementation of the polygon. * on the implementation of the polygon.

View File

@ -40,6 +40,15 @@ public:
std::vector<Placer> placers; std::vector<Placer> placers;
placers.reserve(last-first); placers.reserve(last-first);
std::for_each(first, last, [this](Item& itm) {
if(itm.isFixed()) {
if(packed_bins_.empty()) packed_bins_.emplace_back();
packed_bins_.front().emplace_back(itm);
} else {
store_.emplace_back(itm);
}
});
// If the packed_items array is not empty we have to create as many // If the packed_items array is not empty we have to create as many
// placers as there are elements in packed bins and preload each item // placers as there are elements in packed bins and preload each item
// into the appropriate placer // into the appropriate placer
@ -49,8 +58,6 @@ public:
placers.back().preload(ig); placers.back().preload(ig);
} }
std::copy(first, last, std::back_inserter(store_));
auto sortfunc = [](Item& i1, Item& i2) { auto sortfunc = [](Item& i1, Item& i2) {
return i1.area() > i2.area(); return i1.area() > i2.area();
}; };
@ -76,7 +83,6 @@ public:
} }
} }
auto it = store_.begin(); auto it = store_.begin();
while(it != store_.end() && !cancelled()) { while(it != store_.end() && !cancelled()) {

View File

@ -1,5 +1,4 @@
#include "ModelArrange.hpp" #include "ModelArrange.hpp"
//#include "Model.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
#include "SVG.hpp" #include "SVG.hpp"
#include "MTUtils.hpp" #include "MTUtils.hpp"
@ -656,34 +655,35 @@ BedShapeHint bedShape(const Polyline &bed) {
//static const SLIC3R_CONSTEXPR double SIMPLIFY_TOLERANCE_MM = 0.1; //static const SLIC3R_CONSTEXPR double SIMPLIFY_TOLERANCE_MM = 0.1;
//template<class BinT>
//PackGroup _arrange(std::vector<Item> & items,
// const BinT & bin,
// coord_t minobjd,
// std::function<void(unsigned)> prind,
// std::function<bool()> stopfn)
//{
// AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
// return arranger(items.begin(), items.end());
//}
template<class BinT> template<class BinT>
PackGroup _arrange(std::vector<Item> & items, PackGroup _arrange(std::vector<Item> & shapes,
const PackGroup & preshapes,
const BinT & bin, const BinT & bin,
coord_t minobjd, coord_t minobjd,
std::function<void(unsigned)> prind, std::function<void(unsigned)> prind,
std::function<bool()> stopfn) std::function<bool()> stopfn)
{ {
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
return arranger(items.begin(), items.end());
}
//template<class BinT>
//IndexedPackGroup _arrange(std::vector<std::reference_wrapper<Item>> &shapes,
// const PackGroup & preshapes,
// std::vector<ModelInstance *> &minstances,
// const BinT & bin,
// coord_t minobjd)
//{
// auto binbb = sl::boundingBox(bin); // auto binbb = sl::boundingBox(bin);
// AutoArranger<BinT> arranger{bin, minobjd}; AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
// if(!preshapes.front().empty()) { // If there is something on the plate if(!preshapes.front().empty()) { // If there is something on the plate
// arranger.preload(preshapes); arranger.preload(preshapes);
// // Try to put the first item to the center, as the arranger will not // Try to put the first item to the center, as the arranger will not
// // do this for us. // do this for us.
// auto shptrit = minstances.begin(); // auto shptrit = minstances.begin();
// for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit) // for(auto shit = shapes.begin(); shit != shapes.end(); ++shit, ++shptrit)
// { // {
@ -712,10 +712,10 @@ PackGroup _arrange(std::vector<Item> & items,
// break; // break;
// } // }
// } // }
// } }
// return arranger(shapes.begin(), shapes.end()); return arranger(shapes.begin(), shapes.end());
//} }
inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w) inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
{ {
@ -725,19 +725,26 @@ inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
//// The final client function to arrange the Model. A progress indicator and //// The final client function to arrange the Model. A progress indicator and
//// a stop predicate can be also be passed to control the process. //// a stop predicate can be also be passed to control the process.
bool arrange(Arrangeables & arrangables, bool arrange(Arrangeables & arrangables,
const Arrangeables & excludes,
coord_t min_obj_distance, coord_t min_obj_distance,
BedShapeHint bedhint, const BedShapeHint & bedhint,
std::function<void(unsigned)> progressind, std::function<void(unsigned)> progressind,
std::function<bool()> stopcondition) std::function<bool()> stopcondition)
{ {
bool ret = true; bool ret = true;
namespace clppr = ClipperLib; namespace clppr = ClipperLib;
std::vector<Item> items; std::vector<Item> items, excluded_items;
items.reserve(arrangables.size()); items.reserve(arrangables.size());
coord_t binwidth = 0; coord_t binwidth = 0;
for (Arrangeable *arrangeable : arrangables) { PackGroup preshapes{ {} }; // pack group with one initial bin for preloading
auto process_arrangeable =
[](const Arrangeable * arrangeable,
std::vector<Item> & outp,
std::function<void(const Item &, unsigned)> applyfn)
{
assert(arrangeable); assert(arrangeable);
auto arrangeitem = arrangeable->get_arrange_polygon(); auto arrangeitem = arrangeable->get_arrange_polygon();
@ -753,25 +760,38 @@ bool arrange(Arrangeables & arrangables,
auto firstp = clpath.Contour.front(); auto firstp = clpath.Contour.front();
clpath.Contour.emplace_back(firstp); clpath.Contour.emplace_back(firstp);
items.emplace_back( outp.emplace_back(applyfn, std::move(clpath));
outp.front().rotation(rotation);
outp.front().translation({offs.x(), offs.y()});
};
for (Arrangeable *arrangeable : arrangables) {
process_arrangeable(
arrangeable,
items,
// callback called by arrange to apply the result on the arrangeable // callback called by arrange to apply the result on the arrangeable
[arrangeable, &binwidth](const Item &itm, unsigned binidx) { [arrangeable, &binwidth](const Item &itm, unsigned binidx) {
clppr::cInt stride = binidx * stride_padding(binwidth); clppr::cInt stride = binidx * stride_padding(binwidth);
clppr::IntPoint offs = itm.translation(); clppr::IntPoint offs = itm.translation();
arrangeable->apply_arrange_result({unscaled(offs.X + stride), arrangeable->apply_arrange_result({unscaled(offs.X +
stride),
unscaled(offs.Y)}, unscaled(offs.Y)},
itm.rotation()); itm.rotation());
}, });
std::move(clpath));
items.front().rotation(rotation);
items.front().translation({offs.x(), offs.y()});
} }
for (const Arrangeable * fixed: excludes)
process_arrangeable(fixed, excluded_items, nullptr);
for(Item& excl : excluded_items) preshapes.front().emplace_back(excl);
// Integer ceiling the min distance from the bed perimeters // Integer ceiling the min distance from the bed perimeters
coord_t md = min_obj_distance - SCALED_EPSILON; coord_t md = min_obj_distance - SCALED_EPSILON;
md = (md % 2) ? md / 2 + 1 : md / 2; md = (md % 2) ? md / 2 + 1 : md / 2;
auto& cfn = stopcondition;
switch (bedhint.type) { switch (bedhint.type) {
case BedShapeType::BOX: { case BedShapeType::BOX: {
// Create the arranger for the box shaped bed // Create the arranger for the box shaped bed
@ -781,14 +801,14 @@ bool arrange(Arrangeables & arrangables,
Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}}; Box binbb{{bbb.min(X), bbb.min(Y)}, {bbb.max(X), bbb.max(Y)}};
binwidth = coord_t(binbb.width()); binwidth = coord_t(binbb.width());
_arrange(items, binbb, min_obj_distance, progressind, stopcondition); _arrange(items, preshapes, binbb, min_obj_distance, progressind, cfn);
break; break;
} }
case BedShapeType::CIRCLE: { case BedShapeType::CIRCLE: {
auto c = bedhint.shape.circ; auto c = bedhint.shape.circ;
auto cc = to_lnCircle(c); auto cc = to_lnCircle(c);
binwidth = scaled(c.radius()); binwidth = scaled(c.radius());
_arrange(items, cc, min_obj_distance, progressind, stopcondition); _arrange(items, preshapes, cc, min_obj_distance, progressind, cfn);
break; break;
} }
case BedShapeType::IRREGULAR: { case BedShapeType::IRREGULAR: {
@ -796,11 +816,11 @@ bool arrange(Arrangeables & arrangables,
auto irrbed = sl::create<clppr::Polygon>(std::move(ctour)); auto irrbed = sl::create<clppr::Polygon>(std::move(ctour));
BoundingBox polybb(bedhint.shape.polygon); BoundingBox polybb(bedhint.shape.polygon);
binwidth = (polybb.max(X) - polybb.min(X)); binwidth = (polybb.max(X) - polybb.min(X));
_arrange(items, irrbed, min_obj_distance, progressind, stopcondition); _arrange(items, preshapes, irrbed, min_obj_distance, progressind, cfn);
break; break;
} }
case BedShapeType::WHO_KNOWS: { case BedShapeType::WHO_KNOWS: {
_arrange(items, false, min_obj_distance, progressind, stopcondition); _arrange(items, preshapes, false, min_obj_distance, progressind, cfn);
break; break;
} }
}; };
@ -810,99 +830,15 @@ bool arrange(Arrangeables & arrangables,
return ret; return ret;
} }
//void find_new_position(const Model &model, /// Arrange, without the fixed items (excludes)
// ModelInstancePtrs toadd, bool arrange(Arrangeables & inp,
// coord_t min_obj_distance, coord_t min_d,
// const Polyline &bed, const BedShapeHint & bedhint,
// WipeTowerInfo& wti) std::function<void(unsigned)> prfn,
//{ std::function<bool()> stopfn)
// // Get the 2D projected shapes with their 3D model instance pointers {
// auto shapemap = arr::projectModelFromTop(model, wti, SIMPLIFY_TOLERANCE_MM); return arrange(inp, {}, min_d, bedhint, prfn, stopfn);
// // Copy the references for the shapes only, as the arranger expects a
// // sequence of objects convertible to Item or ClipperPolygon
// PackGroup preshapes; preshapes.emplace_back();
// ItemGroup shapes;
// preshapes.front().reserve(shapemap.size());
// std::vector<ModelInstance*> shapes_ptr; shapes_ptr.reserve(toadd.size());
// IndexedPackGroup result;
// // If there is no hint about the shape, we will try to guess
// BedShapeHint bedhint = bedShape(bed);
// BoundingBox bbb(bed);
// // Integer ceiling the min distance from the bed perimeters
// coord_t md = min_obj_distance - SCALED_EPSILON;
// md = (md % 2) ? md / 2 + 1 : md / 2;
// auto binbb = Box({ClipperLib::cInt{bbb.min(0)} - md,
// ClipperLib::cInt{bbb.min(1)} - md},
// {ClipperLib::cInt{bbb.max(0)} + md,
// ClipperLib::cInt{bbb.max(1)} + md});
// for(auto it = shapemap.begin(); it != shapemap.end(); ++it) {
// // `toadd` vector contains the instance pointers which have to be
// // considered by arrange. If `it` points to an ModelInstance, which
// // is NOT in `toadd`, add it to preshapes.
// if(std::find(toadd.begin(), toadd.end(), it->first) == toadd.end()) {
// if(it->second.isInside(binbb)) // just ignore items which are outside
// preshapes.front().emplace_back(std::ref(it->second));
// }
// else {
// shapes_ptr.emplace_back(it->first);
// shapes.emplace_back(std::ref(it->second));
// }
// }
// switch(bedhint.type) {
// case BedShapeType::BOX: {
// // Create the arranger for the box shaped bed
// result = _arrange(shapes, preshapes, shapes_ptr, binbb, min_obj_distance);
// break;
// }
// case BedShapeType::CIRCLE: {
// auto c = bedhint.shape.circ;
// auto cc = to_lnCircle(c);
// result = _arrange(shapes, preshapes, shapes_ptr, cc, min_obj_distance);
// break;
// }
// case BedShapeType::IRREGULAR:
// case BedShapeType::WHO_KNOWS: {
// auto ctour = Slic3rMultiPoint_to_ClipperPath(bed);
// ClipperLib::Polygon irrbed = sl::create<PolygonImpl>(std::move(ctour));
// result = _arrange(shapes, preshapes, shapes_ptr, irrbed, min_obj_distance);
// break;
// }
// };
// // Now we go through the result which will contain the fixed and the moving
// // polygons as well. We will have to search for our item.
// ClipperLib::cInt stride = stride_padding(binbb.width());
// ClipperLib::cInt batch_offset = 0;
// for(auto& group : result) {
// for(auto& r : group) if(r.first < shapes.size()) {
// Item& resultitem = r.second;
// unsigned idx = r.first;
// auto offset = resultitem.translation();
// Radians rot = resultitem.rotation();
// ModelInstance *minst = shapes_ptr[idx];
// Vec3d foffset(unscaled(offset.X + batch_offset),
// unscaled(offset.Y),
// minst->get_offset()(Z));
// // write the transformation data into the model instance
// minst->set_rotation(Z, rot);
// minst->set_offset(foffset);
// }
// batch_offset += stride;
// }
//}
} }
} // namespace arr
} } // namespace Slic3r

View File

@ -1,16 +1,14 @@
#ifndef MODELARRANGE_HPP #ifndef MODELARRANGE_HPP
#define MODELARRANGE_HPP #define MODELARRANGE_HPP
//#include "Model.hpp"
#include "Polygon.hpp" #include "Polygon.hpp"
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
namespace Slic3r { namespace Slic3r {
class Model;
namespace arr { namespace arr {
/// A geometry abstraction for a circular print bed. Similarly to BoundingBox.
class CircleBed { class CircleBed {
Point center_; Point center_;
double radius_; double radius_;
@ -24,6 +22,7 @@ public:
inline operator bool() { return !std::isnan(radius_); } inline operator bool() { return !std::isnan(radius_); }
}; };
/// Types of print bed shapes.
enum class BedShapeType { enum class BedShapeType {
BOX, BOX,
CIRCLE, CIRCLE,
@ -31,6 +30,7 @@ enum class BedShapeType {
WHO_KNOWS WHO_KNOWS
}; };
/// Info about the print bed for the arrange() function.
struct BedShapeHint { struct BedShapeHint {
BedShapeType type = BedShapeType::WHO_KNOWS; BedShapeType type = BedShapeType::WHO_KNOWS;
/*union*/ struct { // I know but who cares... TODO: use variant from cpp17? /*union*/ struct { // I know but who cares... TODO: use variant from cpp17?
@ -40,13 +40,19 @@ struct BedShapeHint {
} shape; } shape;
}; };
/// Get a bed shape hint for arrange() from a naked Polyline.
BedShapeHint bedShape(const Polyline& bed); BedShapeHint bedShape(const Polyline& bed);
/**
* @brief Classes implementing the Arrangeable interface can be used as input
* to the arrange function.
*/
class Arrangeable { class Arrangeable {
public: public:
virtual ~Arrangeable() = default; 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) = 0;
/// Get the 2D silhouette to arrange and an initial offset and rotation /// Get the 2D silhouette to arrange and an initial offset and rotation
@ -58,56 +64,48 @@ using Arrangeables = std::vector<Arrangeable*>;
/** /**
* \brief Arranges the model objects on the screen. * \brief Arranges the model objects on the screen.
* *
* The arrangement considers multiple bins (aka. print beds) for placing all * The arrangement considers multiple bins (aka. print beds) for placing
* the items provided in the model argument. If the items don't fit on one * all the items provided in the model argument. If the items don't fit on
* print bed, the remaining will be placed onto newly created print beds. * one print bed, the remaining will be placed onto newly created print
* The first_bin_only parameter, if set to true, disables this behavior and * beds. The first_bin_only parameter, if set to true, disables this
* makes sure that only one print bed is filled and the remaining items will be * behavior and makes sure that only one print bed is filled and the
* untouched. When set to false, the items which could not fit onto the * remaining items will be untouched. When set to false, the items which
* print bed will be placed next to the print bed so the user should see a * could not fit onto the print bed will be placed next to the print bed so
* pile of items on the print bed and some other piles outside the print * the user should see a pile of items on the print bed and some other
* area that can be dragged later onto the print bed as a group. * piles outside the print area that can be dragged later onto the print
* bed as a group.
*
* \param items Input which are object pointers implementing the
* Arrangeable interface.
*
* \param min_obj_distance The minimum distance which is allowed for any
* pair of items on the print bed in any direction.
*
* \param bedhint Info about the shape and type of the
* bed. remaining items which do not fit onto the print area next to the
* print bed or leave them untouched (let the user arrange them by hand or
* remove them).
*
* \param progressind Progress indicator callback called when
* an object gets packed. The unsigned argument is the number of items
* remaining to pack.
* *
* \param model The model object with the 3D content.
* \param dist The minimum distance which is allowed for any pair of items
* on the print bed in any direction.
* \param bb The bounding box of the print bed. It corresponds to the 'bin'
* for bin packing.
* \param first_bin_only This parameter controls whether to place the
* remaining items which do not fit onto the print area next to the print
* bed or leave them untouched (let the user arrange them by hand or remove
* them).
* \param progressind Progress indicator callback called when an object gets
* packed. The unsigned argument is the number of items remaining to pack.
* \param stopcondition A predicate returning true if abort is needed. * \param stopcondition A predicate returning true if abort is needed.
*/ */
//bool arrange(Model &model,
// WipeTowerInfo& wipe_tower_info,
// coord_t min_obj_distance,
// const Slic3r::Polyline& bed,
// BedShapeHint bedhint,
// bool first_bin_only,
// std::function<void(unsigned)> progressind,
// std::function<bool(void)> stopcondition);
bool arrange(Arrangeables &items, bool arrange(Arrangeables &items,
coord_t min_obj_distance, coord_t min_obj_distance,
BedShapeHint bedhint, const BedShapeHint& bedhint,
std::function<void(unsigned)> progressind, std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcondition); std::function<bool(void)> stopcondition);
/// This will find a suitable position for a new object instance and leave the /// Same as the previous, only that it takes unmovable items as an
/// old items untouched. /// additional argument.
//void find_new_position(const Model& model, bool arrange(Arrangeables &items,
// ModelInstancePtrs instances_to_add, const Arrangeables &excludes,
// coord_t min_obj_distance,
// const Slic3r::Polyline& bed,
// WipeTowerInfo& wti);
void find_new_position(Arrangeables &items,
const Arrangeables &instances_to_add,
coord_t min_obj_distance, coord_t min_obj_distance,
BedShapeHint bedhint); const BedShapeHint& bedhint,
std::function<void(unsigned)> progressind,
std::function<bool(void)> stopcondition);
} // arr } // arr
} // Slic3r } // Slic3r

View File

@ -2461,132 +2461,68 @@ void Plater::priv::ExclusiveJobGroup::ArrangeJob::process() {
update_status(m_count, update_status(m_count,
was_canceled() ? _(L("Arranging canceled.")) was_canceled() ? _(L("Arranging canceled."))
: _(L("Arranging done."))); : _(L("Arranging done.")));
}
// TODO: we should decide whether to allow arrange when the search is void find_new_position(const Model & model,
// running we should probably disable explicit slicing and background ModelInstancePtrs instances,
// processing coord_t min_d,
const arr::BedShapeHint &bedhint)
{
// static const auto arrangestr = _(L("Arranging")); // TODO
// auto &config = plater().config;
// auto &view3D = plater().view3D;
// auto &model = plater().model;
// // 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(config);
// }
// auto min_obj_distance = coord_t(dist / SCALING_FACTOR);
// const auto *bed_shape_opt = config->opt<ConfigOptionPoints>(
// "bed_shape");
// assert(bed_shape_opt);
// auto & bedpoints = bed_shape_opt->values;
// Polyline bed;
// bed.points.reserve(bedpoints.size());
// for (auto &v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
// update_status(0, arrangestr);
// arr::WipeTowerInfo wti = view3D->get_canvas3d()->get_wipe_tower_info();
// try {
// arr::BedShapeHint hint;
// // TODO: from Sasha from GUI or
// hint.type = arr::BedShapeType::WHO_KNOWS;
// arr::arrange(model,
// wti,
// min_obj_distance,
// bed,
// hint,
// false, // create many piles not just one pile
// [this](unsigned st) {
// if (st > 0)
// update_status(count - int(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."));
// }
// update_status(count,
// was_canceled() ? _(L("Arranging canceled."))
// : _(L("Arranging done.")));
// // it remains to move the wipe tower:
// view3D->get_canvas3d()->arrange_wipe_tower(wti);
} }
void Plater::priv::ExclusiveJobGroup::RotoptimizeJob::process() void Plater::priv::ExclusiveJobGroup::RotoptimizeJob::process()
{ {
// int obj_idx = plater().get_selected_object_idx(); int obj_idx = plater().get_selected_object_idx();
// if (obj_idx < 0) { return; } if (obj_idx < 0) { return; }
// ModelObject *o = plater().model.objects[size_t(obj_idx)]; ModelObject *o = plater().model.objects[size_t(obj_idx)];
// auto r = sla::find_best_rotation( auto r = sla::find_best_rotation(
// *o, *o,
// .005f, .005f,
// [this](unsigned s) { [this](unsigned s) {
// if (s < 100) if (s < 100)
// update_status(int(s), update_status(int(s),
// _(L("Searching for optimal orientation"))); _(L("Searching for optimal orientation")));
// }, },
// [this]() { return was_canceled(); }); [this]() { return was_canceled(); });
// const auto *bed_shape_opt =
// plater().config->opt<ConfigOptionPoints>("bed_shape");
// assert(bed_shape_opt); double mindist = 6.0; // FIXME
// auto & bedpoints = bed_shape_opt->values; if (!was_canceled()) {
// Polyline bed; for(ModelInstance * oi : o->instances) {
// bed.points.reserve(bedpoints.size()); oi->set_rotation({r[X], r[Y], r[Z]});
// for (auto &v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
// double mindist = 6.0; // FIXME auto trmatrix = oi->get_transformation().get_matrix();
Polygon trchull = o->convex_hull_2d(trmatrix);
// if (!was_canceled()) { MinAreaBoundigBox rotbb(trchull, MinAreaBoundigBox::pcConvex);
// for(ModelInstance * oi : o->instances) { double r = rotbb.angle_to_X();
// oi->set_rotation({r[X], r[Y], r[Z]});
// auto trmatrix = oi->get_transformation().get_matrix(); // The box should be landscape
// Polygon trchull = o->convex_hull_2d(trmatrix); if(rotbb.width() < rotbb.height()) r += PI / 2;
// MinAreaBoundigBox rotbb(trchull, MinAreaBoundigBox::pcConvex); Vec3d rt = oi->get_rotation(); rt(Z) += r;
// double r = rotbb.angle_to_X();
// // The box should be landscape oi->set_rotation(rt);
// if(rotbb.width() < rotbb.height()) r += PI / 2; }
// Vec3d rt = oi->get_rotation(); rt(Z) += r; find_new_position(plater().model,
o->instances,
scaled(mindist),
plater().get_bed_shape_hint());
// oi->set_rotation(rt); // Correct the z offset of the object which was corrupted be
// } // the rotation
o->ensure_on_bed();
}
// arr::WipeTowerInfo wti; // useless in SLA context update_status(100,
// arr::find_new_position(plater().model, was_canceled() ? _(L("Orientation search canceled."))
// o->instances, : _(L("Orientation found.")));
// coord_t(mindist / SCALING_FACTOR),
// bed,
// wti);
// // Correct the z offset of the object which was corrupted be
// // the rotation
// o->ensure_on_bed();
// }
// update_status(100,
// was_canceled() ? _(L("Orientation search canceled."))
// : _(L("Orientation found.")));
} }
void Plater::priv::split_object() void Plater::priv::split_object()