Better support for circular bed.

This commit is contained in:
tamasmeszaros 2018-08-06 20:13:04 +02:00
parent 3c32a7c3db
commit e1edb05bbb
5 changed files with 172 additions and 530 deletions

View File

@ -50,492 +50,12 @@ void arrangeRectangles() {
using namespace libnest2d;
const int SCALE = 1000000;
// const int SCALE = 1;
std::vector<Rectangle> rects = {
{80*SCALE, 80*SCALE},
{60*SCALE, 90*SCALE},
{70*SCALE, 30*SCALE},
{80*SCALE, 60*SCALE},
{60*SCALE, 60*SCALE},
{60*SCALE, 40*SCALE},
{40*SCALE, 40*SCALE},
{10*SCALE, 10*SCALE},
{10*SCALE, 10*SCALE},
{10*SCALE, 10*SCALE},
{10*SCALE, 10*SCALE},
{10*SCALE, 10*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{5*SCALE, 5*SCALE},
{20*SCALE, 20*SCALE}
};
// std::vector<Rectangle> rects = {
// {20*SCALE, 10*SCALE},
// {20*SCALE, 10*SCALE},
// {20*SCALE, 20*SCALE},
// };
// std::vector<Item> input {
// {{0, 0}, {0, 20*SCALE}, {10*SCALE, 0}, {0, 0}}
// };
std::vector<Item> crasher =
{
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-5000000, 8954050},
{5000000, 8954050},
{5000000, -45949},
{4972609, -568549},
{3500000, -8954050},
{-3500000, -8954050},
{-4972609, -568549},
{-5000000, -45949},
{-5000000, 8954050},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-9945219, -3065619},
{-9781479, -2031780},
{-9510560, -1020730},
{-9135450, -43529},
{-2099999, 14110899},
{2099999, 14110899},
{9135450, -43529},
{9510560, -1020730},
{9781479, -2031780},
{9945219, -3065619},
{10000000, -4110899},
{9945219, -5156179},
{9781479, -6190020},
{9510560, -7201069},
{9135450, -8178270},
{8660249, -9110899},
{8090169, -9988750},
{7431449, -10802200},
{6691309, -11542300},
{5877850, -12201100},
{5000000, -12771100},
{4067369, -13246399},
{3090169, -13621500},
{2079119, -13892399},
{1045279, -14056099},
{0, -14110899},
{-1045279, -14056099},
{-2079119, -13892399},
{-3090169, -13621500},
{-4067369, -13246399},
{-5000000, -12771100},
{-5877850, -12201100},
{-6691309, -11542300},
{-7431449, -10802200},
{-8090169, -9988750},
{-8660249, -9110899},
{-9135450, -8178270},
{-9510560, -7201069},
{-9781479, -6190020},
{-9945219, -5156179},
{-10000000, -4110899},
{-9945219, -3065619},
},
{
{-18000000, -1000000},
{-15000000, 22000000},
{-11000000, 26000000},
{11000000, 26000000},
{15000000, 22000000},
{18000000, -1000000},
{18000000, -26000000},
{-18000000, -26000000},
{-18000000, -1000000},
},
{60*SCALE, 200*SCALE},
{60*SCALE, 200*SCALE}
};
std::vector<Item> proba = {
{
Rectangle(100, 2)
},
{
Rectangle(100, 2)
},
{
Rectangle(100, 2)
},
{
Rectangle(10, 10)
},
};
proba[0].rotate(Pi/3);
proba[1].rotate(Pi-Pi/3);
// std::vector<Item> input(25, Rectangle(70*SCALE, 10*SCALE));
std::vector<Item> input;
input.insert(input.end(), prusaParts().begin(), prusaParts().end());
// input.insert(input.end(), prusaExParts().begin(), prusaExParts().end());
@ -544,7 +64,7 @@ void arrangeRectangles() {
// input.insert(input.end(), proba.begin(), proba.end());
// input.insert(input.end(), crasher.begin(), crasher.end());
Box bin(250*SCALE, 210*SCALE);
// Box bin(250*SCALE, 210*SCALE);
// PolygonImpl bin = {
// {
// {25*SCALE, 0},
@ -560,9 +80,11 @@ void arrangeRectangles() {
// {}
// };
_Circle<PointImpl> bin({0, 0}, 125*SCALE);
auto min_obj_distance = static_cast<Coord>(0*SCALE);
using Placer = strategies::_NofitPolyPlacer<PolygonImpl, Box>;
using Placer = strategies::_NofitPolyPlacer<PolygonImpl, decltype(bin)>;
using Packer = Arranger<Placer, FirstFitSelection>;
Packer arrange(bin, min_obj_distance);
@ -571,9 +93,9 @@ void arrangeRectangles() {
pconf.alignment = Placer::Config::Alignment::CENTER;
pconf.starting_point = Placer::Config::Alignment::CENTER;
pconf.rotations = {0.0/*, Pi/2.0, Pi, 3*Pi/2*/};
pconf.accuracy = 0.5f;
pconf.accuracy = 1.0f;
// auto bincenter = ShapeLike::boundingBox(bin).center();
// auto bincenter = ShapeLike::boundingBox<PolygonImpl>(bin).center();
// pconf.object_function = [&bin, bincenter](
// Placer::Pile pile, const Item& item,
// double /*area*/, double norm, double penality) {
@ -660,10 +182,7 @@ void arrangeRectangles() {
// score = pl::distance(ibb.center(), bigbb.center()) / norm;
// }
// // If it does not fit into the print bed we will beat it
// // with a large penality. If we would not do this, there would be only
// // one big pile that doesn't care whether it fits onto the print bed.
// if(!NfpPlacer::wouldFit(fullbb, bin)) score = 2*penality - score;
// if(!Placer::wouldFit(fullbb, bin)) score += norm;
// return score;
// };

View File

@ -109,7 +109,7 @@ public:
inline void radius(double r) { radius_ = r; }
inline double area() const BP2D_NOEXCEPT {
return 2.0*Pi*radius_;
return 2.0*Pi*radius_*radius_;
}
};

View File

@ -1,16 +1,19 @@
#ifndef NOFITPOLY_HPP
#define NOFITPOLY_HPP
#include <cassert>
#include <random>
#ifndef NDEBUG
#include <iostream>
#endif
#include "placer_boilerplate.hpp"
#include "../geometry_traits_nfp.hpp"
#include "libnest2d/optimizer.hpp"
#include <cassert>
#include "tools/svgtools.hpp"
namespace libnest2d { namespace strategies {
template<class RawShape>
@ -161,12 +164,11 @@ template<class RawShape> class EdgeCache {
}
size_t stride(const size_t N) const {
using std::ceil;
using std::round;
using std::pow;
return static_cast<Coord>(
std::round(N/std::pow(N, std::pow(accuracy_, 1.0/3.0)))
round(N/pow(N, pow(accuracy_, 1.0/3.0)))
);
}
@ -177,6 +179,7 @@ template<class RawShape> class EdgeCache {
const auto S = stride(N);
contour_.corners.reserve(N / S + 1);
contour_.corners.emplace_back(0.0);
auto N_1 = N-1;
contour_.corners.emplace_back(0.0);
for(size_t i = 0; i < N_1; i += S) {
@ -190,8 +193,8 @@ template<class RawShape> class EdgeCache {
if(!hc.corners.empty()) return;
const auto N = hc.distances.size();
const auto S = stride(N);
auto N_1 = N-1;
const auto S = stride(N);
hc.corners.reserve(N / S + 1);
hc.corners.emplace_back(0.0);
for(size_t i = 0; i < N_1; i += S) {
@ -339,7 +342,7 @@ Nfp::Shapes<RawShape> nfp( const Container& polygons,
Nfp::Shapes<RawShape> nfps;
//int pi = 0;
// int pi = 0;
for(Item& sh : polygons) {
auto subnfp_r = Nfp::noFitPolygon<NfpLevel::CONVEX_ONLY>(
sh.transformedShape(), trsh.transformedShape());
@ -441,6 +444,63 @@ Nfp::Shapes<RawShape> nfp( const Container& polygons,
// return nfps;
}
template<class RawShape>
_Circle<TPoint<RawShape>> minimizeCircle(const RawShape& sh) {
using sl = ShapeLike; using pl = PointLike;
using Point = TPoint<RawShape>;
using Coord = TCoord<Point>;
auto bb = sl::boundingBox(sh);
auto capprx = bb.center();
auto rapprx = pl::distance(bb.minCorner(), bb.maxCorner());
auto& ctr = sl::getContour(sh);
opt::StopCriteria stopcr;
stopcr.max_iterations = 100;
stopcr.relative_score_difference = 1e-3;
opt::TOptimizer<opt::Method::L_SUBPLEX> solver(stopcr);
std::vector<double> dists(ctr.size(), 0);
auto result = solver.optimize_min(
[capprx, rapprx, &ctr, &dists](double xf, double yf) {
auto xt = Coord( std::round(getX(capprx) + rapprx*xf) );
auto yt = Coord( std::round(getY(capprx) + rapprx*yf) );
Point centr(xt, yt);
unsigned i = 0;
for(auto v : ctr) {
dists[i++] = pl::distance(v, centr);
}
auto mit = std::max_element(dists.begin(), dists.end());
assert(mit != dists.end());
return *mit;
},
opt::initvals(0.0, 0.0),
opt::bound(-1.0, 1.0), opt::bound(-1.0, 1.0)
);
double oxf = std::get<0>(result.optimum);
double oyf = std::get<1>(result.optimum);
auto xt = Coord( std::round(getX(capprx) + rapprx*oxf) );
auto yt = Coord( std::round(getY(capprx) + rapprx*oyf) );
Point cc(xt, yt);
auto r = result.score;
return {cc, r};
}
template<class RawShape>
_Circle<TPoint<RawShape>> boundingCircle(const RawShape& sh) {
return minimizeCircle(sh);
}
template<class RawShape, class TBin = _Box<TPoint<RawShape>>>
class _NofitPolyPlacer: public PlacerBoilerplate<_NofitPolyPlacer<RawShape, TBin>,
RawShape, TBin, NfpPConfig<RawShape>> {
@ -512,11 +572,7 @@ public:
bool static inline wouldFit(const RawShape& chull,
const _Circle<Vertex>& bin)
{
auto bb = sl::boundingBox(chull);
auto d = bin.center() - bb.center();
auto chullcpy = chull;
sl::translate(chullcpy, d);
return sl::isInside<RawShape>(chullcpy, bin);
return boundingCircle(chull).radius() < bin.radius();
}
PackResult trypack(Item& item) {
@ -574,8 +630,9 @@ public:
auto getNfpPoint = [&ecache](const Optimum& opt)
{
return opt.hidx < 0? ecache[opt.nfpidx].coords(opt.relpos) :
auto ret = opt.hidx < 0? ecache[opt.nfpidx].coords(opt.relpos) :
ecache[opt.nfpidx].coords(opt.hidx, opt.relpos);
return ret;
};
Nfp::Shapes<RawShape> pile;
@ -595,7 +652,7 @@ public:
[this, &merged_pile](
Nfp::Shapes<RawShape>& /*pile*/,
const Item& item,
double occupied_area,
double occupied_area,
double norm,
double /*penality*/)
{
@ -751,14 +808,37 @@ public:
}
inline void clearItems() {
finalAlign(bin_);
Base::clearItems();
}
private:
inline void finalAlign(const RawShape& pbin) {
auto bbin = sl::boundingBox(pbin);
finalAlign(bbin);
}
inline void finalAlign(_Circle<TPoint<RawShape>> cbin) {
if(items_.empty()) return;
Nfp::Shapes<RawShape> m;
m.reserve(items_.size());
for(Item& item : items_) m.emplace_back(item.transformedShape());
auto c = boundingCircle(sl::convexHull(m));
auto d = cbin.center() - c.center();
for(Item& item : items_) item.translate(d);
}
inline void finalAlign(Box bbin) {
Nfp::Shapes<RawShape> m;
m.reserve(items_.size());
for(Item& item : items_) m.emplace_back(item.transformedShape());
auto&& bb = sl::boundingBox<RawShape>(m);
Vertex ci, cb;
auto bbin = sl::boundingBox<RawShape>(bin_);
switch(config_.alignment) {
case Config::Alignment::CENTER: {
@ -790,12 +870,8 @@ public:
auto d = cb - ci;
for(Item& item : items_) item.translate(d);
Base::clearItems();
}
private:
void setInitialPosition(Item& item) {
Box&& bb = item.boundingBox();
Vertex ci, cb;

View File

@ -99,6 +99,43 @@ TEST(BasicFunctionality, creationAndDestruction)
}
TEST(GeometryAlgorithms, boundingCircle) {
using namespace libnest2d;
using strategies::boundingCircle;
PolygonImpl p = {{{0, 10}, {10, 0}, {0, -10}, {0, 10}}, {}};
_Circle<PointImpl> c = boundingCircle<PolygonImpl>(p);
ASSERT_EQ(c.center().X, 0);
ASSERT_EQ(c.center().Y, 0);
ASSERT_DOUBLE_EQ(c.radius(), 10);
ShapeLike::translate(p, PointImpl{10, 10});
c = boundingCircle<PolygonImpl>(p);
ASSERT_EQ(c.center().X, 10);
ASSERT_EQ(c.center().Y, 10);
ASSERT_DOUBLE_EQ(c.radius(), 10);
auto parts = prusaParts();
int i = 0;
for(auto& part : parts) {
c = boundingCircle(part.transformedShape());
if(std::isnan(c.radius())) std::cout << "fail: radius is nan" << std::endl;
else for(auto v : ShapeLike::getContour(part.transformedShape()) ) {
auto d = PointLike::distance(v, c.center());
if(d > c.radius() ) {
auto e = std::abs( 1.0 - d/c.radius());
ASSERT_LE(e, 1e-3);
}
}
i++;
}
}
TEST(GeometryAlgorithms, Distance) {
using namespace libnest2d;

View File

@ -102,9 +102,9 @@ using SpatIndex = bgi::rtree< SpatElement, bgi::rstar<16, 4> >;
std::tuple<double /*score*/, Box /*farthest point from bin center*/>
objfunc(const PointImpl& bincenter,
double /*bin_area*/,
double bin_area,
ShapeLike::Shapes<PolygonImpl>& pile, // The currently arranged pile
double /*pile_area*/,
double pile_area,
const Item &item,
double norm, // A norming factor for physical dimensions
std::vector<double>& areacache, // pile item areas will be cached
@ -115,12 +115,16 @@ objfunc(const PointImpl& bincenter,
using pl = PointLike;
using sl = ShapeLike;
static const double BIG_ITEM_TRESHOLD = 0.2;
static const double BIG_ITEM_TRESHOLD = 0.04;
static const double ROUNDNESS_RATIO = 0.5;
static const double DENSITY_RATIO = 1.0 - ROUNDNESS_RATIO;
// We will treat big items (compared to the print bed) differently
auto normarea = [norm](double area) { return std::sqrt(area)/norm; };
auto isBig = [&areacache, bin_area](double a) {
bool t = areacache.empty() ? true : a > 0.5*areacache.front();
return a/bin_area > BIG_ITEM_TRESHOLD || t;
};
// If a new bin has been created:
if(pile.size() < areacache.size()) {
@ -133,7 +137,7 @@ objfunc(const PointImpl& bincenter,
for(auto& p : pile) {
if(idx == areacache.size()) {
areacache.emplace_back(sl::area(p));
if(normarea(areacache[idx]) > BIG_ITEM_TRESHOLD)
if(isBig(areacache[idx]))
spatindex.insert({sl::boundingBox(p), idx});
}
@ -157,14 +161,10 @@ objfunc(const PointImpl& bincenter,
boost::geometry::convert(boostbb, bigbb);
}
// The size indicator of the candidate item. This is not the area,
// but almost...
double item_normarea = normarea(item.area());
// Will hold the resulting score
double score = 0;
if(item_normarea > BIG_ITEM_TRESHOLD) {
if(isBig(item.area())) {
// This branch is for the bigger items..
// Here we will use the closest point of the item bounding box to
// the already arranged pile. So not the bb center nor the a choosen
@ -223,10 +223,9 @@ objfunc(const PointImpl& bincenter,
// The final mix of the score is the balance between the distance
// from the full pile center, the pack density and the
// alignment with the neigbours
auto C = 0.33;
score = C * dist + C * density + C * alignment_score;
score = 0.4 * dist + 0.4 * density + 0.2 * alignment_score;
} else if( item_normarea < BIG_ITEM_TRESHOLD && spatindex.empty()) {
} else if( !isBig(item.area()) && spatindex.empty()) {
// If there are no big items, only small, we should consider the
// density here as well to not get silly results
auto bindist = pl::distance(ibb.center(), bincenter) / norm;
@ -349,17 +348,26 @@ public:
auto result = objfunc(bin.center(), bin_area_, pile,
pile_area, item, norm, areacache_, rtree_);
double score = std::get<0>(result);
// Circle fitting detection is very rough at the moment but
// we still need something that tells how badly the arrangement
// misses the print bed.
auto& fullbb = std::get<1>(result);
auto bbr = 0.5*PointLike::distance(fullbb.minCorner(),
fullbb.maxCorner());
auto diff = bbr - bin.radius();
if(diff > 0) score += std::pow(diff, 2) / norm;
auto d = PointLike::distance(fullbb.minCorner(),
fullbb.maxCorner());
auto diff = d - 2*bin.radius();
if(diff > 0) {
if( item.area() > 0.01*bin_area_ && item.vertexCount() < 20) {
pile.emplace_back(item.transformedShape());
auto chull = ShapeLike::convexHull(pile);
pile.pop_back();
auto C = strategies::boundingCircle(chull);
auto rdiff = C.radius() - bin.radius();
if(rdiff > 0) {
score += std::pow(rdiff, 3) / norm;
}
}
}
return score;
};
@ -695,6 +703,8 @@ bool arrange(Model &model, coordf_t min_obj_distance,
}
};
if(result.empty()) return false;
if(first_bin_only) {
applyResult(result.front(), 0, shapemap);
} else {