ENH: auto-arrange uses inner NFP to simplify fixed_overfit

1. Add inner nfp algo.The final nfp result is inner nfp subtract outer nfp.
2. Leave 5(scaled) room in inflation to allow numeric float eps.

Change-Id: I6be0b205c9811af24a238352b256bf1399ee3716
(cherry picked from commit dbab96efc7bfa16afd9db9607b862886606b0aa0)
This commit is contained in:
miaoxin 2022-12-06 17:10:35 +08:00 committed by Lane.Wei
parent 29e6f71402
commit 9857f7384b
5 changed files with 51 additions and 12 deletions

View File

@ -261,6 +261,8 @@ inline TMultiShape<PolygonImpl> merge(const TMultiShape<PolygonImpl>& shapes)
return Slic3r::union_ex(shapes);
}
inline TMultiShape<PolygonImpl> subtract(const TMultiShape<PolygonImpl> &outerBinNfp, const TMultiShape<PolygonImpl> &shapes) { return Slic3r::diff_ex(outerBinNfp, shapes); }
} // namespace nfp
} // namespace libnest2d

View File

@ -179,6 +179,42 @@ inline TPoint<RawShape> referenceVertex(const RawShape& sh)
return rightmostUpVertex(sh);
}
template<class RawBox, class RawShape, class Ratio = double> inline NfpResult<RawShape> nfpInnerRectBed(const RawBox &bed, const RawShape &other)
{
using Vertex = TPoint<RawShape>;
using Edge = _Segment<Vertex>;
namespace sl = shapelike;
auto sbox = sl::boundingBox(other);
auto sheight = sbox.height();
auto swidth = sbox.width();
Vertex slidingTop = rightmostUpVertex(other);
auto leftOffset = slidingTop.x() - sbox.minCorner().x();
auto rightOffset = slidingTop.x() - sbox.maxCorner().x();
auto topOffset = 0;
auto bottomOffset = sheight;
auto boxWidth = bed.width();
auto boxHeight = bed.height();
auto bedMinx = bed.minCorner().x();
auto bedMiny = bed.minCorner().y();
auto bedMaxx = bed.maxCorner().x();
auto bedMaxy = bed.maxCorner().y();
RawShape innerNfp{{bedMinx + leftOffset, bedMaxy + topOffset},
{bedMaxx + rightOffset, bedMaxy + topOffset},
{bedMaxx + rightOffset, bedMiny + bottomOffset},
{bedMinx + leftOffset, bedMiny + bottomOffset},
{bedMinx + leftOffset, bedMaxy + topOffset}};
if (sheight > boxHeight || swidth > boxWidth) {
return {{}, {0, 0}};
} else {
return {innerNfp, {0, 0}};
}
}
/**
* The "trivial" Cuninghame-Green implementation of NFP for convex polygons.
*

View File

@ -565,7 +565,7 @@ private:
using Shapes = TMultiShape<RawShape>;
Shapes calcnfp(const Item &trsh, Lvl<nfp::NfpLevel::CONVEX_ONLY>)
Shapes calcnfp(const Item &trsh, const Box& bed ,Lvl<nfp::NfpLevel::CONVEX_ONLY>)
{
using namespace nfp;
@ -598,7 +598,8 @@ private:
nfps[n] = subnfp_r.first;
});
return nfp::merge(nfps);
RawShape innerNfp = nfpInnerRectBed(bed, trsh.transformedShape()).first;
return nfp::subtract({innerNfp}, nfps);
}
@ -738,7 +739,7 @@ private:
// it is disjunct from the current merged pile
placeOutsideOfBin(item);
nfps = calcnfp(item, Lvl<MaxNfpLevel::value>());
nfps = calcnfp(item, binbb, Lvl<MaxNfpLevel::value>());
auto iv = item.referenceVertex();

View File

@ -554,11 +554,11 @@ public:
// 对于屏蔽区域,摆入的对象仍然是可以向右上滑动的;
// 对挤出料塔,摆入的对象不能滑动(必须围绕料塔)
bool pack_around_wipe_tower = std::any_of(packed_items.begin(), packed_items.end(), [](Item& itm) { return itm.is_wipe_tower; });
if(pack_around_wipe_tower)
//if(pack_around_wipe_tower)
return fixed_overfit(objfunc(item, starting_point), binbb);
else {
return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb, m_excluded_and_extruCali_regions);
}
//else {
// return fixed_overfit_topright_sliding(objfunc(item, starting_point), binbb, m_excluded_and_extruCali_regions);
//}
};
};

View File

@ -539,11 +539,11 @@ void ArrangeJob::process()
std::for_each(m_selected.begin(), m_selected.end(), [&](ArrangePolygon &ap) {
ap.inflation = params.min_obj_distance / 2;
BoundingBox apbb = ap.poly.contour.bounding_box();
coord_t diffx = bedbb.size().x() - apbb.size().x();
coord_t diffy = bedbb.size().y() - apbb.size().y();
if (diffx > 0 && diffy > 0) {
coord_t min_diff = std::min(diffx, diffy);
ap.inflation = std::min(min_diff / 2, ap.inflation);
auto diffx = bedbb.size().x() - apbb.size().x() - 5;
auto diffy = bedbb.size().y() - apbb.size().y() - 5;
if (diffx > 0 && diffy > 0) {
auto min_diff = std::min(diffx, diffy);
ap.inflation = std::min(min_diff / 2, ap.inflation);
}
});
// For occulusion regions, inflation should be larger to prevent genrating brim on them.