Adapt find_new_position is WIP. Cleaning up comments.
This commit is contained in:
parent
299e4f74c7
commit
cb3a586deb
@ -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:
|
||||||
|
|
||||||
@ -143,6 +144,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
|
||||||
|
@ -39,6 +39,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
|
||||||
@ -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()) {
|
||||||
|
@ -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,53 +725,73 @@ 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
|
||||||
assert(arrangeable);
|
|
||||||
|
|
||||||
auto arrangeitem = arrangeable->get_arrange_polygon();
|
|
||||||
|
|
||||||
Polygon& p = std::get<0>(arrangeitem);
|
|
||||||
const Vec2crd& offs = std::get<1>(arrangeitem);
|
|
||||||
double rotation = std::get<2>(arrangeitem);
|
|
||||||
|
|
||||||
if (p.is_counter_clockwise()) p.reverse();
|
|
||||||
|
|
||||||
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
|
||||||
|
|
||||||
auto firstp = clpath.Contour.front();
|
|
||||||
clpath.Contour.emplace_back(firstp);
|
|
||||||
|
|
||||||
items.emplace_back(
|
auto process_arrangeable =
|
||||||
|
[](const Arrangeable * arrangeable,
|
||||||
|
std::vector<Item> & outp,
|
||||||
|
std::function<void(const Item &, unsigned)> applyfn)
|
||||||
|
{
|
||||||
|
assert(arrangeable);
|
||||||
|
|
||||||
|
auto arrangeitem = arrangeable->get_arrange_polygon();
|
||||||
|
|
||||||
|
Polygon & p = std::get<0>(arrangeitem);
|
||||||
|
const Vec2crd &offs = std::get<1>(arrangeitem);
|
||||||
|
double rotation = std::get<2>(arrangeitem);
|
||||||
|
|
||||||
|
if (p.is_counter_clockwise()) p.reverse();
|
||||||
|
|
||||||
|
clppr::Polygon clpath(Slic3rMultiPoint_to_ClipperPath(p));
|
||||||
|
|
||||||
|
auto firstp = clpath.Contour.front();
|
||||||
|
clpath.Contour.emplace_back(firstp);
|
||||||
|
|
||||||
|
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
|
||||||
|
@ -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,
|
coord_t min_obj_distance,
|
||||||
// const Slic3r::Polyline& bed,
|
const BedShapeHint& bedhint,
|
||||||
// WipeTowerInfo& wti);
|
std::function<void(unsigned)> progressind,
|
||||||
void find_new_position(Arrangeables &items,
|
std::function<bool(void)> stopcondition);
|
||||||
const Arrangeables &instances_to_add,
|
|
||||||
coord_t min_obj_distance,
|
|
||||||
BedShapeHint bedhint);
|
|
||||||
|
|
||||||
|
|
||||||
} // arr
|
} // arr
|
||||||
} // Slic3r
|
} // Slic3r
|
||||||
|
@ -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"));
|
{
|
||||||
|
|
||||||
// auto &config = plater().config;
|
// TODO
|
||||||
// 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");
|
double mindist = 6.0; // FIXME
|
||||||
|
|
||||||
// assert(bed_shape_opt);
|
if (!was_canceled()) {
|
||||||
|
for(ModelInstance * oi : o->instances) {
|
||||||
// auto & bedpoints = bed_shape_opt->values;
|
oi->set_rotation({r[X], r[Y], r[Z]});
|
||||||
// Polyline bed;
|
|
||||||
// bed.points.reserve(bedpoints.size());
|
|
||||||
// for (auto &v : bedpoints) bed.append(Point::new_scale(v(0), v(1)));
|
|
||||||
|
|
||||||
// double mindist = 6.0; // FIXME
|
|
||||||
|
|
||||||
// if (!was_canceled()) {
|
auto trmatrix = oi->get_transformation().get_matrix();
|
||||||
// for(ModelInstance * oi : o->instances) {
|
Polygon trchull = o->convex_hull_2d(trmatrix);
|
||||||
// oi->set_rotation({r[X], r[Y], r[Z]});
|
|
||||||
|
|
||||||
// auto trmatrix = oi->get_transformation().get_matrix();
|
|
||||||
// Polygon trchull = o->convex_hull_2d(trmatrix);
|
|
||||||
|
|
||||||
// MinAreaBoundigBox rotbb(trchull, MinAreaBoundigBox::pcConvex);
|
MinAreaBoundigBox rotbb(trchull, MinAreaBoundigBox::pcConvex);
|
||||||
// double r = rotbb.angle_to_X();
|
double r = rotbb.angle_to_X();
|
||||||
|
|
||||||
// // The box should be landscape
|
// The box should be landscape
|
||||||
// if(rotbb.width() < rotbb.height()) r += PI / 2;
|
if(rotbb.width() < rotbb.height()) r += PI / 2;
|
||||||
|
|
||||||
// Vec3d rt = oi->get_rotation(); rt(Z) += r;
|
Vec3d rt = oi->get_rotation(); rt(Z) += r;
|
||||||
|
|
||||||
// oi->set_rotation(rt);
|
oi->set_rotation(rt);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// arr::WipeTowerInfo wti; // useless in SLA context
|
find_new_position(plater().model,
|
||||||
// arr::find_new_position(plater().model,
|
o->instances,
|
||||||
// o->instances,
|
scaled(mindist),
|
||||||
// coord_t(mindist / SCALING_FACTOR),
|
plater().get_bed_shape_hint());
|
||||||
// bed,
|
|
||||||
// wti);
|
|
||||||
|
|
||||||
// // Correct the z offset of the object which was corrupted be
|
|
||||||
// // the rotation
|
|
||||||
// o->ensure_on_bed();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// update_status(100,
|
// Correct the z offset of the object which was corrupted be
|
||||||
// was_canceled() ? _(L("Orientation search canceled."))
|
// the rotation
|
||||||
// : _(L("Orientation found.")));
|
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()
|
||||||
|
Loading…
Reference in New Issue
Block a user