1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
//#ifndef NDEBUG
//#define NFP_DEBUG
//#endif
#include "libnfpglue.hpp"
#include "tools/libnfporb/libnfporb.hpp"
namespace libnest2d {
namespace {
inline bool vsort(const libnfporb::point_t& v1, const libnfporb::point_t& v2)
{
using Coord = libnfporb::coord_t;
Coord x1 = v1.x_, x2 = v2.x_, y1 = v1.y_, y2 = v2.y_;
auto diff = y1 - y2;
#ifdef LIBNFP_USE_RATIONAL
long double diffv = diff.convert_to<long double>();
#else
long double diffv = diff.val();
#endif
if(std::abs(diffv) <=
std::numeric_limits<Coord>::epsilon())
return x1 < x2;
return diff < 0;
}
TCoord<PointImpl> getX(const libnfporb::point_t& p) {
#ifdef LIBNFP_USE_RATIONAL
return p.x_.convert_to<TCoord<PointImpl>>();
#else
return static_cast<TCoord<PointImpl>>(std::round(p.x_.val()));
#endif
}
TCoord<PointImpl> getY(const libnfporb::point_t& p) {
#ifdef LIBNFP_USE_RATIONAL
return p.y_.convert_to<TCoord<PointImpl>>();
#else
return static_cast<TCoord<PointImpl>>(std::round(p.y_.val()));
#endif
}
libnfporb::point_t scale(const libnfporb::point_t& p, long double factor) {
#ifdef LIBNFP_USE_RATIONAL
auto px = p.x_.convert_to<long double>();
auto py = p.y_.convert_to<long double>();
#else
long double px = p.x_.val();
long double py = p.y_.val();
#endif
return {px*factor, py*factor};
}
}
NfpR _nfp(const PolygonImpl &sh, const PolygonImpl &cother)
{
namespace sl = shapelike;
NfpR ret;
try {
libnfporb::polygon_t pstat, porb;
boost::geometry::convert(sh, pstat);
boost::geometry::convert(cother, porb);
long double factor = 0.0000001;//libnfporb::NFP_EPSILON;
long double refactor = 1.0/factor;
for(auto& v : pstat.outer()) v = scale(v, factor);
// std::string message;
// boost::geometry::is_valid(pstat, message);
// std::cout << message << std::endl;
for(auto& h : pstat.inners()) for(auto& v : h) v = scale(v, factor);
for(auto& v : porb.outer()) v = scale(v, factor);
// message;
// boost::geometry::is_valid(porb, message);
// std::cout << message << std::endl;
for(auto& h : porb.inners()) for(auto& v : h) v = scale(v, factor);
// this can throw
auto nfp = libnfporb::generateNFP(pstat, porb, true);
auto &ct = sl::getContour(ret.first);
ct.reserve(nfp.front().size()+1);
for(auto v : nfp.front()) {
v = scale(v, refactor);
ct.emplace_back(getX(v), getY(v));
}
ct.push_back(ct.front());
std::reverse(ct.begin(), ct.end());
auto &rholes = sl::holes(ret.first);
for(size_t hidx = 1; hidx < nfp.size(); ++hidx) {
if(nfp[hidx].size() >= 3) {
rholes.emplace_back();
auto& h = rholes.back();
h.reserve(nfp[hidx].size()+1);
for(auto& v : nfp[hidx]) {
v = scale(v, refactor);
h.emplace_back(getX(v), getY(v));
}
h.push_back(h.front());
std::reverse(h.begin(), h.end());
}
}
ret.second = nfp::referenceVertex(ret.first);
} catch(std::exception& e) {
std::cout << "Error: " << e.what() << "\nTrying with convex hull..." << std::endl;
// auto ch_stat = ShapeLike::convexHull(sh);
// auto ch_orb = ShapeLike::convexHull(cother);
ret = nfp::nfpConvexOnly(sh, cother);
}
return ret;
}
NfpR nfp::NfpImpl<PolygonImpl, nfp::NfpLevel::CONVEX_ONLY>::operator()(
const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
{
return _nfp(sh, cother);//nfpConvexOnly(sh, cother);
}
NfpR nfp::NfpImpl<PolygonImpl, nfp::NfpLevel::ONE_CONVEX>::operator()(
const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
{
return _nfp(sh, cother);
}
NfpR nfp::NfpImpl<PolygonImpl, nfp::NfpLevel::BOTH_CONCAVE>::operator()(
const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
{
return _nfp(sh, cother);
}
//PolygonImpl
//Nfp::NfpImpl<PolygonImpl, NfpLevel::ONE_CONVEX_WITH_HOLES>::operator()(
// const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
//{
// return _nfp(sh, cother);
//}
//PolygonImpl
//Nfp::NfpImpl<PolygonImpl, NfpLevel::BOTH_CONCAVE_WITH_HOLES>::operator()(
// const PolygonImpl &sh, const ClipperLib::PolygonImpl &cother)
//{
// return _nfp(sh, cother);
//}
}
|