Fix for incorrect inside check of fixed items.

libnest2d: Add dispatched overloads for offsetting different shapes.
This commit is contained in:
tamasmeszaros 2019-07-19 12:34:27 +02:00
parent 6ae50a710a
commit 72ed8c034e
3 changed files with 53 additions and 15 deletions

View file

@ -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)
{ {

View file

@ -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) \

View file

@ -515,18 +515,29 @@ void _arrange(
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);