Fix for incorrect inside check of fixed items.
libnest2d: Add dispatched overloads for offsetting different shapes.
This commit is contained in:
parent
6ae50a710a
commit
72ed8c034e
3 changed files with 53 additions and 15 deletions
|
@ -71,7 +71,8 @@ template<> inline ClipperLib::cInt& y(PointImpl& p)
|
||||||
|
|
||||||
namespace shapelike {
|
namespace shapelike {
|
||||||
|
|
||||||
template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
|
template<>
|
||||||
|
inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance, const PolygonTag&)
|
||||||
{
|
{
|
||||||
#define DISABLE_BOOST_OFFSET
|
#define DISABLE_BOOST_OFFSET
|
||||||
|
|
||||||
|
@ -123,6 +124,14 @@ template<> inline void offset(PolygonImpl& sh, TCoord<PointImpl> distance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline void offset(PathImpl& sh, TCoord<PointImpl> distance, const PathTag&)
|
||||||
|
{
|
||||||
|
PolygonImpl p(std::move(sh));
|
||||||
|
offset(p, distance, PolygonTag());
|
||||||
|
sh = p.Contour;
|
||||||
|
}
|
||||||
|
|
||||||
// Tell libnest2d how to make string out of a ClipperPolygon object
|
// Tell libnest2d how to make string out of a ClipperPolygon object
|
||||||
template<> inline std::string toString(const PolygonImpl& sh)
|
template<> inline std::string toString(const PolygonImpl& sh)
|
||||||
{
|
{
|
||||||
|
|
|
@ -507,15 +507,13 @@ enum class Formats {
|
||||||
namespace shapelike {
|
namespace shapelike {
|
||||||
|
|
||||||
template<class S>
|
template<class S>
|
||||||
inline S create(const TContour<S>& contour,
|
inline S create(const TContour<S>& contour, const THolesContainer<S>& holes)
|
||||||
const THolesContainer<S>& holes)
|
|
||||||
{
|
{
|
||||||
return S(contour, holes);
|
return S(contour, holes);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class S>
|
template<class S>
|
||||||
inline S create(TContour<S>&& contour,
|
inline S create(TContour<S>&& contour, THolesContainer<S>&& holes)
|
||||||
THolesContainer<S>&& holes)
|
|
||||||
{
|
{
|
||||||
return S(contour, holes);
|
return S(contour, holes);
|
||||||
}
|
}
|
||||||
|
@ -727,11 +725,18 @@ inline void translate(S& /*sh*/, const P& /*offs*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class S>
|
template<class S>
|
||||||
inline void offset(S& /*sh*/, TCoord<TPoint<S>> /*distance*/)
|
inline void offset(S& /*sh*/, TCoord<S> /*distance*/, const PathTag&)
|
||||||
{
|
{
|
||||||
dout() << "The current geometry backend does not support offsetting!\n";
|
dout() << "The current geometry backend does not support offsetting!\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class S>
|
||||||
|
inline void offset(S& sh, TCoord<S> distance, const PolygonTag&)
|
||||||
|
{
|
||||||
|
offset(contour(sh), distance);
|
||||||
|
for(auto &h : holes(sh)) offset(h, -distance);
|
||||||
|
}
|
||||||
|
|
||||||
template<class S>
|
template<class S>
|
||||||
inline std::pair<bool, std::string> isValid(const S& /*sh*/)
|
inline std::pair<bool, std::string> isValid(const S& /*sh*/)
|
||||||
{
|
{
|
||||||
|
@ -1228,6 +1233,23 @@ template<class S> inline bool isConvex(const S& sh) // dispatch
|
||||||
return isConvex(sh, Tag<S>());
|
return isConvex(sh, Tag<S>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class Box> inline void offset(Box& bb, TCoord<Box> d, const BoxTag&)
|
||||||
|
{
|
||||||
|
TPoint<Box> md{d, d};
|
||||||
|
bb.minCorner() -= md;
|
||||||
|
bb.maxCorner() += md;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class C> inline void offset(C& circ, TCoord<C> d, const CircleTag&)
|
||||||
|
{
|
||||||
|
circ.radius(circ.radius() + double(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch function
|
||||||
|
template<class S> inline void offset(S& sh, TCoord<S> d) {
|
||||||
|
offset(sh, d, Tag<S>());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_MAIN_TYPES(T) \
|
#define DECLARE_MAIN_TYPES(T) \
|
||||||
|
|
|
@ -514,19 +514,30 @@ void _arrange(
|
||||||
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};
|
// Integer ceiling the min distance from the bed perimeters
|
||||||
|
coord_t md = minobjd - 2 * scaled(0.1 + EPSILON);
|
||||||
|
md = (md % 2) ? md / 2 + 1 : md / 2;
|
||||||
|
|
||||||
|
auto corrected_bin = bin;
|
||||||
|
sl::offset(corrected_bin, md);
|
||||||
|
|
||||||
|
AutoArranger<BinT> arranger{corrected_bin, 0, prind, stopfn};
|
||||||
|
|
||||||
|
auto infl = coord_t(std::ceil(minobjd / 2.0));
|
||||||
|
for (Item& itm : shapes) itm.inflate(infl);
|
||||||
|
for (Item& itm : excludes) itm.inflate(infl);
|
||||||
|
|
||||||
auto it = excludes.begin();
|
auto it = excludes.begin();
|
||||||
while (it != excludes.end())
|
while (it != excludes.end())
|
||||||
sl::isInside(it->transformedShape(), bin) ?
|
sl::isInside(it->transformedShape(), corrected_bin) ?
|
||||||
++it : it = excludes.erase(it);
|
++it : it = excludes.erase(it);
|
||||||
|
|
||||||
// If there is something on the plate
|
// If there is something on the plate
|
||||||
if(!excludes.empty())
|
if(!excludes.empty())
|
||||||
{
|
{
|
||||||
arranger.preload(excludes);
|
arranger.preload(excludes);
|
||||||
auto binbb = sl::boundingBox(bin);
|
auto binbb = sl::boundingBox(corrected_bin);
|
||||||
|
|
||||||
// Try to put the first item to the center, as the arranger
|
// Try to put the first item to the center, as the arranger
|
||||||
// will not do this for us.
|
// will not do this for us.
|
||||||
|
@ -548,6 +559,7 @@ void _arrange(
|
||||||
for (auto &itm : excludes) inp.emplace_back(itm);
|
for (auto &itm : excludes) inp.emplace_back(itm);
|
||||||
|
|
||||||
arranger(inp.begin(), inp.end());
|
arranger(inp.begin(), inp.end());
|
||||||
|
for (Item &itm : inp) itm.inflate(-infl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The final client function for arrangement. A progress indicator and
|
// The final client function for arrangement. A progress indicator and
|
||||||
|
@ -594,10 +606,6 @@ void arrange(ArrangePolygons & arrangables,
|
||||||
|
|
||||||
for (Item &itm : fixeditems) itm.inflate(scaled(-2. * EPSILON));
|
for (Item &itm : fixeditems) itm.inflate(scaled(-2. * EPSILON));
|
||||||
|
|
||||||
// Integer ceiling the min distance from the bed perimeters
|
|
||||||
coord_t md = min_obj_dist - 2 * scaled(0.1 + EPSILON);
|
|
||||||
md = (md % 2) ? md / 2 + 1 : md / 2;
|
|
||||||
|
|
||||||
auto &cfn = stopcondition;
|
auto &cfn = stopcondition;
|
||||||
auto &pri = progressind;
|
auto &pri = progressind;
|
||||||
|
|
||||||
|
@ -605,7 +613,6 @@ void arrange(ArrangePolygons & arrangables,
|
||||||
case bsBox: {
|
case bsBox: {
|
||||||
// Create the arranger for the box shaped bed
|
// Create the arranger for the box shaped bed
|
||||||
BoundingBox bbb = bedhint.get_box();
|
BoundingBox bbb = bedhint.get_box();
|
||||||
bbb.min -= Point{md, md}, bbb.max += Point{md, md};
|
|
||||||
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)}};
|
||||||
|
|
||||||
_arrange(items, fixeditems, binbb, min_obj_dist, pri, cfn);
|
_arrange(items, fixeditems, binbb, min_obj_dist, pri, cfn);
|
||||||
|
|
Loading…
Reference in a new issue