Partial arrange starts to work again.
This commit is contained in:
parent
914bf63228
commit
87c5e9bbaa
4 changed files with 123 additions and 278 deletions
|
@ -875,6 +875,28 @@ inline _Box<TPoint<S>> boundingBox(const S& sh)
|
|||
return boundingBox(sh, Tag<S>() );
|
||||
}
|
||||
|
||||
template<class P> _Box<P> boundingBox(const _Box<P>& bb1, const _Box<P>& bb2 )
|
||||
{
|
||||
auto& pminc = bb1.minCorner();
|
||||
auto& pmaxc = bb1.maxCorner();
|
||||
auto& iminc = bb2.minCorner();
|
||||
auto& imaxc = bb2.maxCorner();
|
||||
P minc, maxc;
|
||||
|
||||
setX(minc, std::min(getX(pminc), getX(iminc)));
|
||||
setY(minc, std::min(getY(pminc), getY(iminc)));
|
||||
|
||||
setX(maxc, std::max(getX(pmaxc), getX(imaxc)));
|
||||
setY(maxc, std::max(getY(pmaxc), getY(imaxc)));
|
||||
return _Box<P>(minc, maxc);
|
||||
}
|
||||
|
||||
template<class S1, class S2>
|
||||
_Box<TPoint<S1>> boundingBox(const S1 &s1, const S2 &s2)
|
||||
{
|
||||
return boundingBox(boundingBox(s1), boundingBox(s2));
|
||||
}
|
||||
|
||||
template<class Box>
|
||||
inline double area(const Box& box, const BoxTag& )
|
||||
{
|
||||
|
@ -1060,8 +1082,8 @@ template<class TB, class TC>
|
|||
inline bool isInside(const TB& box, const TC& circ,
|
||||
const BoxTag&, const CircleTag&)
|
||||
{
|
||||
return isInside(box.minCorner(), circ, BoxTag(), CircleTag()) &&
|
||||
isInside(box.maxCorner(), circ, BoxTag(), CircleTag());
|
||||
return isInside(box.minCorner(), circ, PointTag(), CircleTag()) &&
|
||||
isInside(box.maxCorner(), circ, PointTag(), CircleTag());
|
||||
}
|
||||
|
||||
template<class TBGuest, class TBHost>
|
||||
|
|
|
@ -895,7 +895,10 @@ private:
|
|||
template<class TIter> inline void __execute(TIter from, TIter to)
|
||||
{
|
||||
if(min_obj_distance_ > 0) std::for_each(from, to, [this](Item& item) {
|
||||
item.addOffset(static_cast<Coord>(std::ceil(min_obj_distance_/2.0)));
|
||||
auto offs = min_obj_distance_;
|
||||
if (item.isFixed()) offs *= 0.99;
|
||||
|
||||
item.addOffset(static_cast<Coord>(std::ceil(offs/2.0)));
|
||||
});
|
||||
|
||||
selector_.template packItems<PlacementStrategy>(
|
||||
|
|
|
@ -801,7 +801,6 @@ private:
|
|||
// optimize
|
||||
config_.object_function = prev_func;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Optimum {
|
||||
|
@ -816,29 +815,14 @@ private:
|
|||
|
||||
class Optimizer: public opt::TOptimizer<opt::Method::L_SUBPLEX> {
|
||||
public:
|
||||
Optimizer() {
|
||||
Optimizer(float accuracy = 1.f) {
|
||||
opt::StopCriteria stopcr;
|
||||
stopcr.max_iterations = 200;
|
||||
stopcr.max_iterations = unsigned(std::floor(1000 * accuracy));
|
||||
stopcr.relative_score_difference = 1e-20;
|
||||
this->stopcr_ = stopcr;
|
||||
}
|
||||
};
|
||||
|
||||
static Box boundingBox(const Box& pilebb, const Box& ibb ) {
|
||||
auto& pminc = pilebb.minCorner();
|
||||
auto& pmaxc = pilebb.maxCorner();
|
||||
auto& iminc = ibb.minCorner();
|
||||
auto& imaxc = ibb.maxCorner();
|
||||
Vertex minc, maxc;
|
||||
|
||||
setX(minc, std::min(getX(pminc), getX(iminc)));
|
||||
setY(minc, std::min(getY(pminc), getY(iminc)));
|
||||
|
||||
setX(maxc, std::max(getX(pmaxc), getX(imaxc)));
|
||||
setY(maxc, std::max(getY(pmaxc), getY(imaxc)));
|
||||
return Box(minc, maxc);
|
||||
}
|
||||
|
||||
using Edges = EdgeCache<RawShape>;
|
||||
|
||||
template<class Range = ConstItemRange<typename Base::DefaultIter>>
|
||||
|
@ -935,7 +919,7 @@ private:
|
|||
_objfunc = [norm, binbb, pbb, ins_check](const Item& item)
|
||||
{
|
||||
auto ibb = item.boundingBox();
|
||||
auto fullbb = boundingBox(pbb, ibb);
|
||||
auto fullbb = sl::boundingBox(pbb, ibb);
|
||||
|
||||
double score = pl::distance(ibb.center(),
|
||||
binbb.center());
|
||||
|
@ -1005,14 +989,15 @@ private:
|
|||
|
||||
auto& rofn = rawobjfunc;
|
||||
auto& nfpoint = getNfpPoint;
|
||||
float accuracy = config_.accuracy;
|
||||
|
||||
__parallel::enumerate(
|
||||
cache.corners().begin(),
|
||||
cache.corners().end(),
|
||||
[&results, &item, &rofn, &nfpoint, ch]
|
||||
[&results, &item, &rofn, &nfpoint, ch, accuracy]
|
||||
(double pos, size_t n)
|
||||
{
|
||||
Optimizer solver;
|
||||
Optimizer solver(accuracy);
|
||||
|
||||
Item itemcpy = item;
|
||||
auto contour_ofn = [&rofn, &nfpoint, ch, &itemcpy]
|
||||
|
@ -1059,10 +1044,10 @@ private:
|
|||
__parallel::enumerate(cache.corners(hidx).begin(),
|
||||
cache.corners(hidx).end(),
|
||||
[&results, &item, &nfpoint,
|
||||
&rofn, ch, hidx]
|
||||
&rofn, ch, hidx, accuracy]
|
||||
(double pos, size_t n)
|
||||
{
|
||||
Optimizer solver;
|
||||
Optimizer solver(accuracy);
|
||||
|
||||
Item itmcpy = item;
|
||||
auto hole_ofn =
|
||||
|
|
|
@ -65,89 +65,6 @@ using Segment = _Segment<clppr::IntPoint>;
|
|||
using MultiPolygon = TMultiShape<clppr::Polygon>;
|
||||
using PackGroup = _PackGroup<clppr::Polygon>;
|
||||
|
||||
// Only for debugging. Prints the model object vertices on stdout.
|
||||
//std::string toString(const Model& model, bool holes = true) {
|
||||
// std::stringstream ss;
|
||||
|
||||
// ss << "{\n";
|
||||
|
||||
// for(auto objptr : model.objects) {
|
||||
// if(!objptr) continue;
|
||||
|
||||
// auto rmesh = objptr->raw_mesh();
|
||||
|
||||
// for(auto objinst : objptr->instances) {
|
||||
// if(!objinst) continue;
|
||||
|
||||
// Slic3r::TriangleMesh tmpmesh = rmesh;
|
||||
// // CHECK_ME -> Is the following correct ?
|
||||
// tmpmesh.scale(objinst->get_scaling_factor());
|
||||
// objinst->transform_mesh(&tmpmesh);
|
||||
// ExPolygons expolys = tmpmesh.horizontal_projection();
|
||||
// for(auto& expoly_complex : expolys) {
|
||||
|
||||
// ExPolygons tmp = expoly_complex.simplify(scaled<double>(1.));
|
||||
// if(tmp.empty()) continue;
|
||||
// ExPolygon expoly = tmp.front();
|
||||
// expoly.contour.make_clockwise();
|
||||
// for(auto& h : expoly.holes) h.make_counter_clockwise();
|
||||
|
||||
// ss << "\t{\n";
|
||||
// ss << "\t\t{\n";
|
||||
|
||||
// for(auto v : expoly.contour.points) ss << "\t\t\t{"
|
||||
// << v(0) << ", "
|
||||
// << v(1) << "},\n";
|
||||
// {
|
||||
// auto v = expoly.contour.points.front();
|
||||
// ss << "\t\t\t{" << v(0) << ", " << v(1) << "},\n";
|
||||
// }
|
||||
// ss << "\t\t},\n";
|
||||
|
||||
// // Holes:
|
||||
// ss << "\t\t{\n";
|
||||
// if(holes) for(auto h : expoly.holes) {
|
||||
// ss << "\t\t\t{\n";
|
||||
// for(auto v : h.points) ss << "\t\t\t\t{"
|
||||
// << v(0) << ", "
|
||||
// << v(1) << "},\n";
|
||||
// {
|
||||
// auto v = h.points.front();
|
||||
// ss << "\t\t\t\t{" << v(0) << ", " << v(1) << "},\n";
|
||||
// }
|
||||
// ss << "\t\t\t},\n";
|
||||
// }
|
||||
// ss << "\t\t},\n";
|
||||
|
||||
// ss << "\t},\n";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// ss << "}\n";
|
||||
|
||||
// return ss.str();
|
||||
//}
|
||||
|
||||
// Debugging: Save model to svg file.
|
||||
//void toSVG(SVG& svg, const Model& model) {
|
||||
// for(auto objptr : model.objects) {
|
||||
// if(!objptr) continue;
|
||||
|
||||
// auto rmesh = objptr->raw_mesh();
|
||||
|
||||
// for(auto objinst : objptr->instances) {
|
||||
// if(!objinst) continue;
|
||||
|
||||
// Slic3r::TriangleMesh tmpmesh = rmesh;
|
||||
// tmpmesh.scale(objinst->get_scaling_factor());
|
||||
// objinst->transform_mesh(&tmpmesh);
|
||||
// ExPolygons expolys = tmpmesh.horizontal_projection();
|
||||
// svg.draw(expolys);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
namespace bgi = boost::geometry::index;
|
||||
|
||||
using SpatElement = std::pair<Box, unsigned>;
|
||||
|
@ -156,21 +73,6 @@ using ItemGroup = std::vector<std::reference_wrapper<Item>>;
|
|||
|
||||
const double BIG_ITEM_TRESHOLD = 0.02;
|
||||
|
||||
Box boundingBox(const Box& pilebb, const Box& ibb ) {
|
||||
auto& pminc = pilebb.minCorner();
|
||||
auto& pmaxc = pilebb.maxCorner();
|
||||
auto& iminc = ibb.minCorner();
|
||||
auto& imaxc = ibb.maxCorner();
|
||||
PointImpl minc, maxc;
|
||||
|
||||
setX(minc, std::min(getX(pminc), getX(iminc)));
|
||||
setY(minc, std::min(getY(pminc), getY(iminc)));
|
||||
|
||||
setX(maxc, std::max(getX(pmaxc), getX(imaxc)));
|
||||
setY(maxc, std::max(getY(pmaxc), getY(imaxc)));
|
||||
return Box(minc, maxc);
|
||||
}
|
||||
|
||||
// Fill in the placer algorithm configuration with values carefully chosen for
|
||||
// Slic3r.
|
||||
template<class PConf>
|
||||
|
@ -194,13 +96,18 @@ void fillConfig(PConf& pcfg) {
|
|||
pcfg.parallel = true;
|
||||
}
|
||||
|
||||
// Type trait for an arranger class for different bin types (box, circle,
|
||||
// polygon, etc...)
|
||||
//template<class TBin>
|
||||
//class AutoArranger {};
|
||||
|
||||
template<class Bin> clppr::IntPoint center(const Bin& bin) { return bin.center(); }
|
||||
template<> clppr::IntPoint center(const clppr::Polygon &bin) { return sl::boundingBox(bin).center(); }
|
||||
// Apply penality to object function result. This is used only when alignment
|
||||
// after arrange is explicitly disabled (PConfig::Alignment::DONT_ALIGN)
|
||||
double fixed_overfit(const std::tuple<double, Box>& result, const Box &binbb)
|
||||
{
|
||||
double score = std::get<0>(result);
|
||||
Box pilebb = std::get<1>(result);
|
||||
Box fullbb = sl::boundingBox(pilebb, binbb);
|
||||
double diff = fullbb.area() - binbb.area();
|
||||
if(diff > 0) score += diff;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
// A class encapsulating the libnest2d Nester class and extending it with other
|
||||
// management and spatial index structures for acceleration.
|
||||
|
@ -218,8 +125,7 @@ protected:
|
|||
Packer m_pck;
|
||||
PConfig m_pconf; // Placement configuration
|
||||
TBin m_bin;
|
||||
double m_bin_area; // caching
|
||||
PointImpl m_bincenter; // caching
|
||||
double m_bin_area;
|
||||
SpatIndex m_rtree; // spatial index for the normal (bigger) objects
|
||||
SpatIndex m_smallsrtree; // spatial index for only the smaller items
|
||||
double m_norm; // A coefficient to scale distances
|
||||
|
@ -234,7 +140,7 @@ protected:
|
|||
// as it possibly can be but at the same time, it has to provide
|
||||
// reasonable results.
|
||||
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
|
||||
objfunc(const Item &item )
|
||||
objfunc(const Item &item, const clppr::IntPoint &bincenter)
|
||||
{
|
||||
const double bin_area = m_bin_area;
|
||||
const SpatIndex& spatindex = m_rtree;
|
||||
|
@ -250,7 +156,7 @@ protected:
|
|||
auto ibb = sl::boundingBox(item.transformedShape());
|
||||
|
||||
// Calculate the full bounding box of the pile with the candidate item
|
||||
auto fullbb = boundingBox(m_pilebb, ibb);
|
||||
auto fullbb = sl::boundingBox(m_pilebb, ibb);
|
||||
|
||||
// The bounding box of the big items (they will accumulate in the center
|
||||
// of the pile
|
||||
|
@ -286,7 +192,7 @@ protected:
|
|||
|
||||
// The smalles distance from the arranged pile center:
|
||||
double dist = *(std::min_element(dists.begin(), dists.end())) / m_norm;
|
||||
double bindist = pl::distance(ibb.center(), m_bincenter) / m_norm;
|
||||
double bindist = pl::distance(ibb.center(), bincenter) / m_norm;
|
||||
dist = 0.8*dist + 0.2*bindist;
|
||||
|
||||
// Density is the pack density: how big is the arranged pile
|
||||
|
@ -334,7 +240,7 @@ protected:
|
|||
Item& p = m_items[idx];
|
||||
auto parea = p.area();
|
||||
if(std::abs(1.0 - parea/item.area()) < 1e-6) {
|
||||
auto bb = boundingBox(p.boundingBox(), ibb);
|
||||
auto bb = sl::boundingBox(p.boundingBox(), ibb);
|
||||
auto bbarea = bb.area();
|
||||
auto ascore = 1.0 - (item.area() + parea)/bbarea;
|
||||
|
||||
|
@ -370,9 +276,7 @@ public:
|
|||
std::function<bool(void)> stopcond)
|
||||
: m_pck(bin, dist)
|
||||
, m_bin(bin)
|
||||
, m_bin_area(sl::area(bin))
|
||||
, m_bincenter(center(bin))
|
||||
, m_norm(std::sqrt(m_bin_area))
|
||||
, m_norm(std::sqrt(sl::area(bin)))
|
||||
{
|
||||
fillConfig(m_pconf);
|
||||
|
||||
|
@ -391,10 +295,10 @@ public:
|
|||
|
||||
m_rtree.clear();
|
||||
m_smallsrtree.clear();
|
||||
|
||||
|
||||
// We will treat big items (compared to the print bed) differently
|
||||
auto isBig = [this](double a) {
|
||||
return a/m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||
return a / m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||
};
|
||||
|
||||
for(unsigned idx = 0; idx < items.size(); ++idx) {
|
||||
|
@ -419,8 +323,11 @@ public:
|
|||
|
||||
inline void preload(std::vector<Item>& fixeditems) {
|
||||
m_pconf.alignment = PConfig::Alignment::DONT_ALIGN;
|
||||
// m_pconf.object_function = nullptr; // drop the special objectfunction
|
||||
// m_pck.preload(pg);
|
||||
auto bb = sl::boundingBox(m_bin);
|
||||
auto bbcenter = bb.center();
|
||||
m_pconf.object_function = [this, bb, bbcenter](const Item &item) {
|
||||
return fixed_overfit(objfunc(item, bbcenter), bb);
|
||||
};
|
||||
|
||||
// Build the rtree for queries to work
|
||||
|
||||
|
@ -442,34 +349,39 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<> std::function<double(const Item&)> AutoArranger<Box>::get_objfn()
|
||||
{
|
||||
return [this](const Item &itm) {
|
||||
auto result = objfunc(itm);
|
||||
auto bincenter = m_bin.center();
|
||||
|
||||
return [this, bincenter](const Item &itm) {
|
||||
auto result = objfunc(itm, bincenter);
|
||||
|
||||
double score = std::get<0>(result);
|
||||
auto& fullbb = std::get<1>(result);
|
||||
|
||||
|
||||
double miss = Placer::overfit(fullbb, m_bin);
|
||||
miss = miss > 0? miss : 0;
|
||||
score += miss*miss;
|
||||
|
||||
|
||||
return score;
|
||||
};
|
||||
}
|
||||
|
||||
template<> std::function<double(const Item&)> AutoArranger<Circle>::get_objfn()
|
||||
{
|
||||
return [this](const Item &item) {
|
||||
auto bincenter = m_bin.center();
|
||||
return [this, bincenter](const Item &item) {
|
||||
|
||||
auto result = objfunc(item, bincenter);
|
||||
|
||||
auto result = objfunc(item);
|
||||
|
||||
double score = std::get<0>(result);
|
||||
|
||||
|
||||
auto isBig = [this](const Item& itm) {
|
||||
return itm.area()/m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||
return itm.area() / m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||
};
|
||||
|
||||
|
||||
if(isBig(item)) {
|
||||
auto mp = m_merged_pile;
|
||||
mp.push_back(item.transformedShape());
|
||||
|
@ -478,109 +390,26 @@ template<> std::function<double(const Item&)> AutoArranger<Circle>::get_objfn()
|
|||
if(miss < 0) miss = 0;
|
||||
score += miss*miss;
|
||||
}
|
||||
|
||||
|
||||
return score;
|
||||
};
|
||||
}
|
||||
|
||||
template<> std::function<double(const Item&)> AutoArranger<clppr::Polygon>::get_objfn()
|
||||
// Specialization for a generalized polygon.
|
||||
// Warning: this is unfinished business. It may or may not work.
|
||||
template<>
|
||||
std::function<double(const Item &)> AutoArranger<clppr::Polygon>::get_objfn()
|
||||
{
|
||||
return [this] (const Item &item) { return std::get<0>(objfunc(item)); };
|
||||
auto bincenter = sl::boundingBox(m_bin).center();
|
||||
return [this, bincenter](const Item &item) {
|
||||
return std::get<0>(objfunc(item, bincenter));
|
||||
};
|
||||
}
|
||||
|
||||
// Arranger specialization for a Box shaped bin.
|
||||
//template<> class AutoArranger<Box>: public _ArrBase<Box> {
|
||||
//public:
|
||||
|
||||
// AutoArranger(const Box& bin, Distance dist,
|
||||
// std::function<void(unsigned)> progressind = [](unsigned){},
|
||||
// std::function<bool(void)> stopcond = [](){return false;}):
|
||||
// _ArrBase<Box>(bin, dist, progressind, stopcond)
|
||||
// {
|
||||
|
||||
// // Here we set up the actual object function that calls the common
|
||||
// // object function for all bin shapes than does an additional inside
|
||||
// // check for the arranged pile.
|
||||
// m_pconf.object_function = [this, bin](const Item &item) {
|
||||
|
||||
// auto result = objfunc(bin.center(), item);
|
||||
|
||||
// double score = std::get<0>(result);
|
||||
// auto& fullbb = std::get<1>(result);
|
||||
|
||||
// double miss = Placer::overfit(fullbb, bin);
|
||||
// miss = miss > 0? miss : 0;
|
||||
// score += miss*miss;
|
||||
|
||||
// return score;
|
||||
// };
|
||||
|
||||
// m_pck.configure(m_pconf);
|
||||
// }
|
||||
//};
|
||||
|
||||
inline Circle to_lnCircle(const CircleBed& circ) {
|
||||
return Circle({circ.center()(0), circ.center()(1)}, circ.radius());
|
||||
}
|
||||
|
||||
//// Arranger specialization for circle shaped bin.
|
||||
//template<> class AutoArranger<Circle>: public _ArrBase<Circle> {
|
||||
//public:
|
||||
|
||||
// AutoArranger(const Circle& bin, Distance dist,
|
||||
// std::function<void(unsigned)> progressind = [](unsigned){},
|
||||
// std::function<bool(void)> stopcond = [](){return false;}):
|
||||
// _ArrBase<Circle>(bin, dist, progressind, stopcond) {
|
||||
|
||||
// // As with the box, only the inside check is different.
|
||||
// m_pconf.object_function = [this, &bin](const Item &item) {
|
||||
|
||||
// auto result = objfunc(bin.center(), item);
|
||||
|
||||
// double score = std::get<0>(result);
|
||||
|
||||
// auto isBig = [this](const Item& itm) {
|
||||
// return itm.area()/m_bin_area > BIG_ITEM_TRESHOLD ;
|
||||
// };
|
||||
|
||||
// if(isBig(item)) {
|
||||
// auto mp = m_merged_pile;
|
||||
// mp.push_back(item.transformedShape());
|
||||
// auto chull = sl::convexHull(mp);
|
||||
// double miss = Placer::overfit(chull, bin);
|
||||
// if(miss < 0) miss = 0;
|
||||
// score += miss*miss;
|
||||
// }
|
||||
|
||||
// return score;
|
||||
// };
|
||||
|
||||
// m_pck.configure(m_pconf);
|
||||
// }
|
||||
//};
|
||||
|
||||
// Arranger specialization for a generalized polygon.
|
||||
// Warning: this is unfinished business. It may or may not work.
|
||||
//template<> class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
|
||||
//public:
|
||||
// AutoArranger(const PolygonImpl& bin, Distance dist,
|
||||
// std::function<void(unsigned)> progressind = [](unsigned){},
|
||||
// std::function<bool(void)> stopcond = [](){return false;}):
|
||||
// _ArrBase<PolygonImpl>(bin, dist, progressind, stopcond)
|
||||
// {
|
||||
// m_pconf.object_function = [this, &bin] (const Item &item) {
|
||||
|
||||
// auto binbb = sl::boundingBox(bin);
|
||||
// auto result = objfunc(binbb.center(), item);
|
||||
// double score = std::get<0>(result);
|
||||
|
||||
// return score;
|
||||
// };
|
||||
|
||||
// m_pck.configure(m_pconf);
|
||||
// }
|
||||
//};
|
||||
|
||||
// Get the type of bed geometry from a simple vector of points.
|
||||
BedShapeHint bedShape(const Polyline &bed) {
|
||||
BedShapeHint ret;
|
||||
|
@ -670,40 +499,46 @@ PackGroup _arrange(std::vector<Item> & shapes,
|
|||
{
|
||||
AutoArranger<BinT> arranger{bin, minobjd, prind, stopfn};
|
||||
|
||||
for(auto it = excludes.begin(); it != excludes.end(); ++it)
|
||||
if (!sl::isInside(it->transformedShape(), bin))
|
||||
it = excludes.erase(it);
|
||||
|
||||
// If there is something on the plate
|
||||
if(!excludes.empty()) {
|
||||
// arranger.preload(preshapes);
|
||||
auto binbb = sl::boundingBox(bin);
|
||||
|
||||
// Try to put the first item to the center, as the arranger will not
|
||||
// do this for us.
|
||||
for (auto it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
Item &itm = *it;
|
||||
auto ibb = itm.boundingBox();
|
||||
auto d = binbb.center() - ibb.center();
|
||||
itm.translate(d);
|
||||
auto it = excludes.begin();
|
||||
while (it != excludes.end())
|
||||
sl::isInside(it->transformedShape(), bin) ?
|
||||
++it : it = excludes.erase(it);
|
||||
|
||||
if (!arranger.is_colliding(itm)) {
|
||||
itm.markAsFixed();
|
||||
// arranger.preload({{itm}});
|
||||
|
||||
// Write the transformation data into the item. The callback
|
||||
// was set on the instantiation of Item and calls the
|
||||
// Arrangeable interface.
|
||||
it->callApplyFunction(0);
|
||||
|
||||
// Remove this item, as it is arranged now
|
||||
it = shapes.erase(it);
|
||||
break;
|
||||
// If there is something on the plate
|
||||
if(!excludes.empty())
|
||||
{
|
||||
arranger.preload(excludes);
|
||||
auto binbb = sl::boundingBox(bin);
|
||||
|
||||
// Try to put the first item to the center, as the arranger
|
||||
// will not do this for us.
|
||||
for (auto it = shapes.begin(); it != shapes.end(); ++it) {
|
||||
Item &itm = *it;
|
||||
auto ibb = itm.boundingBox();
|
||||
auto d = binbb.center() - ibb.center();
|
||||
itm.translate(d);
|
||||
|
||||
if (!arranger.is_colliding(itm)) {
|
||||
itm.markAsFixed();
|
||||
|
||||
// Write the transformation data into the item. The
|
||||
// callback was set on the instantiation of Item and
|
||||
// calls the Arrangeable interface.
|
||||
it->callApplyFunction(0);
|
||||
|
||||
// Remove this item, as it is arranged now
|
||||
it = shapes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::reference_wrapper<Item>> inp;
|
||||
inp.reserve(shapes.size() + excludes.size());
|
||||
for (auto &itm : shapes ) inp.emplace_back(itm);
|
||||
for (auto &itm : excludes) inp.emplace_back(itm);
|
||||
|
||||
return arranger(shapes.begin(), shapes.end());
|
||||
return arranger(inp.begin(), inp.end());
|
||||
}
|
||||
|
||||
inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
|
||||
|
@ -713,8 +548,8 @@ inline SLIC3R_CONSTEXPR coord_t stride_padding(coord_t w)
|
|||
|
||||
// The final client function for arrangement. A progress indicator and
|
||||
// a stop predicate can be also be passed to control the process.
|
||||
bool arrange(ArrangeablePtrs & arrangables,
|
||||
const ArrangeablePtrs & excludes,
|
||||
bool arrange(ArrangeablePtrs & arrangables,
|
||||
const ArrangeablePtrs & excludes,
|
||||
coord_t min_obj_distance,
|
||||
const BedShapeHint & bedhint,
|
||||
std::function<void(unsigned)> progressind,
|
||||
|
|
Loading…
Reference in a new issue