From 6819c506d8dacb389838b8e38a245eca5e52a7eb Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 23 Jan 2019 16:35:21 +0100 Subject: [PATCH] Fixing items partially outside the bed when auto-placing new items. --- .../libnest2d/backends/clipper/geometries.hpp | 1 + .../include/libnest2d/geometry_traits.hpp | 80 +++++++++++-------- src/libnest2d/include/libnest2d/libnest2d.hpp | 4 +- .../include/libnest2d/placers/nfpplacer.hpp | 18 +++-- .../include/libnest2d/utils/boost_alg.hpp | 6 +- 5 files changed, 65 insertions(+), 44 deletions(-) diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index c05d08d0d..9f881e7e0 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -113,6 +113,7 @@ template<> struct CountourType { template<> struct ShapeTag { using Type = PolygonTag; }; template<> struct ShapeTag { using Type = PathTag; }; +template<> struct ShapeTag { using Type = PointTag; }; template<> struct ShapeTag> { using Type = MultiPolygonTag; diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index 828044afe..917f5280d 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -69,12 +69,14 @@ struct PointPair { RawPoint p2; }; +struct PointTag {}; struct PolygonTag {}; struct PathTag {}; struct MultiPolygonTag {}; struct BoxTag {}; struct CircleTag {}; +/// Meta-functions to derive the tags template struct ShapeTag { using Type = typename Shape::Tag; }; template using Tag = typename ShapeTag>::Type; @@ -131,7 +133,7 @@ public: _Circle(const RawPoint& center, double r): center_(center), radius_(r) {} inline const RawPoint& center() const BP2D_NOEXCEPT { return center_; } - inline const void center(const RawPoint& c) { center_ = c; } + inline void center(const RawPoint& c) { center_ = c; } inline double radius() const BP2D_NOEXCEPT { return radius_; } inline void radius(double r) { radius_ = r; } @@ -518,21 +520,19 @@ inline bool intersects(const RawShape& /*sh*/, const RawShape& /*sh*/) return false; } -template -inline bool isInside(const TPoint& /*point*/, - const RawShape& /*shape*/) -{ - static_assert(always_false::value, - "shapelike::isInside(point, shape) unimplemented!"); +template +inline bool isInside(const TGuest&, const THost&, + const PointTag&, const PolygonTag&) { + static_assert(always_false::value, + "shapelike::isInside(point, path) unimplemented!"); return false; } -template -inline bool isInside(const RawShape& /*shape*/, - const RawShape& /*shape*/) -{ - static_assert(always_false::value, - "shapelike::isInside(shape, shape) unimplemented!"); +template +inline bool isInside(const TGuest&, const THost&, + const PolygonTag&, const PolygonTag&) { + static_assert(always_false::value, + "shapelike::isInside(shape, shape) unimplemented!"); return false; } @@ -651,7 +651,7 @@ template inline bool isConvex(const RawPath& sh, const PathTag&) template inline typename TContour::iterator -begin(RawShape& sh, const PolygonTag& t) +begin(RawShape& sh, const PolygonTag&) { return begin(contour(sh), PathTag()); } @@ -818,16 +818,16 @@ inline auto convexHull(const RawShape& sh) return convexHull(sh, Tag()); } -template -inline bool isInside(const TPoint& point, - const _Circle>& circ) +template +inline bool isInside(const TP& point, const TC& circ, + const PointTag&, const CircleTag&) { return pointlike::distance(point, circ.center()) < circ.radius(); } -template -inline bool isInside(const TPoint& point, - const _Box>& box) +template +inline bool isInside(const TP& point, const TB& box, + const PointTag&, const BoxTag&) { auto px = getX(point); auto py = getY(point); @@ -839,27 +839,27 @@ inline bool isInside(const TPoint& point, return px > minx && px < maxx && py > miny && py < maxy; } -template -inline bool isInside(const RawShape& sh, - const _Circle>& circ) +template +inline bool isInside(const RawShape& sh, const TC& circ, + const PolygonTag&, const CircleTag&) { - return std::all_of(cbegin(sh), cend(sh), - [&circ](const TPoint& p){ - return isInside(p, circ); + return std::all_of(cbegin(sh), cend(sh), [&circ](const TPoint& p) + { + return isInside(p, circ, PointTag(), CircleTag()); }); } -template -inline bool isInside(const _Box>& box, - const _Circle>& circ) +template +inline bool isInside(const TB& box, const TC& circ, + const BoxTag&, const CircleTag&) { - return isInside(box.minCorner(), circ) && - isInside(box.maxCorner(), circ); + return isInside(box.minCorner(), circ, BoxTag(), CircleTag()) && + isInside(box.maxCorner(), circ, BoxTag(), CircleTag()); } -template -inline bool isInside(const _Box>& ibb, - const _Box>& box) +template +inline bool isInside(const TBGuest& ibb, const TBHost& box, + const BoxTag&, const BoxTag&) { auto iminX = getX(ibb.minCorner()); auto imaxX = getX(ibb.maxCorner()); @@ -874,6 +874,18 @@ inline bool isInside(const _Box>& ibb, return iminX > minX && imaxX < maxX && iminY > minY && imaxY < maxY; } +template +inline bool isInside(const RawShape& poly, const TB& box, + const PolygonTag&, const BoxTag&) +{ + return isInside(boundingBox(poly), box, BoxTag(), BoxTag()); +} + +template +inline bool isInside(const TGuest& guest, const THost& host) { + return isInside(guest, host, Tag(), Tag()); +} + template // Potential O(1) implementation may exist inline TPoint& vertex(RawShape& sh, unsigned long idx, const PolygonTag&) diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index 3d0c6f9a4..49baa65f2 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -482,12 +482,12 @@ public: template inline bool _Item::isInside(const _Box>& box) const { - return sl::isInside(boundingBox(), box); + return sl::isInside(boundingBox(), box); } template inline bool _Item::isInside(const _Circle>& circ) const { - return sl::isInside(transformedShape(), circ); + return sl::isInside(transformedShape(), circ); } template using _ItemRef = std::reference_wrapper<_Item>; diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 4573027e4..6fb717a7a 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -916,8 +916,8 @@ private: if(config_.alignment == Config::Alignment::DONT_ALIGN) ins_check = [&binbb, norm](const Box& fullbb) { double ret = 0; - if(sl::isInside(fullbb, binbb)) - ret += norm*norm; + if(!sl::isInside(fullbb, binbb)) + ret += norm; return ret; }; else @@ -958,9 +958,10 @@ private: ecache[opt.nfpidx].coords(opt.hidx, opt.relpos); }; - auto boundaryCheck = - [&merged_pile, &getNfpPoint, &item, &bin, &iv, &startpos] - (const Optimum& o) + auto alignment = config_.alignment; + + auto boundaryCheck = [alignment, &merged_pile, &getNfpPoint, + &item, &bin, &iv, &startpos] (const Optimum& o) { auto v = getNfpPoint(o); auto d = v - iv; @@ -971,7 +972,12 @@ private: auto chull = sl::convexHull(merged_pile); merged_pile.pop_back(); - return overfit(chull, bin); + double miss = 0; + if(alignment == Config::Alignment::DONT_ALIGN) + miss = sl::isInside(chull, bin) ? -1.0 : 1.0; + else miss = overfit(chull, bin); + + return miss; }; Optimum optimum(0, 0); diff --git a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp index c573edb47..a6988ca00 100644 --- a/src/libnest2d/include/libnest2d/utils/boost_alg.hpp +++ b/src/libnest2d/include/libnest2d/utils/boost_alg.hpp @@ -356,13 +356,15 @@ inline double area(const PolygonImpl& shape, const PolygonTag&) #endif template<> -inline bool isInside(const PointImpl& point, const PolygonImpl& shape) +inline bool isInside(const PointImpl& point, const PolygonImpl& shape, + const PointTag&, const PolygonTag&) { return boost::geometry::within(point, shape); } template<> -inline bool isInside(const PolygonImpl& sh1, const PolygonImpl& sh2) +inline bool isInside(const PolygonImpl& sh1, const PolygonImpl& sh2, + const PolygonTag&, const PolygonTag&) { return boost::geometry::within(sh1, sh2); }