From f117d02750ffe9cf32695ce1e6015bbcb05c487f Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Sun, 28 Mar 2021 14:23:44 +0200 Subject: [PATCH] Back-porting improvements for libnest2d --- src/libnest2d/CMakeLists.txt | 2 +- .../libnest2d/backends/clipper/geometries.hpp | 8 ++- .../include/libnest2d/geometry_traits.hpp | 3 +- src/libnest2d/include/libnest2d/libnest2d.hpp | 5 ++ src/libnest2d/include/libnest2d/parallel.hpp | 63 +++++++++++++++++++ .../include/libnest2d/placers/nfpplacer.hpp | 52 +-------------- src/libnest2d/tools/svgtools.hpp | 16 ++++- tests/libnest2d/printer_parts.hpp | 6 +- 8 files changed, 96 insertions(+), 59 deletions(-) create mode 100644 src/libnest2d/include/libnest2d/parallel.hpp diff --git a/src/libnest2d/CMakeLists.txt b/src/libnest2d/CMakeLists.txt index 592ab069c..3892ed30b 100644 --- a/src/libnest2d/CMakeLists.txt +++ b/src/libnest2d/CMakeLists.txt @@ -28,4 +28,4 @@ add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES}) target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include) target_link_libraries(libnest2d PUBLIC clipper NLopt::nlopt TBB::tbb Boost::boost) -target_compile_definitions(libnest2d PUBLIC USE_TBB LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_clipper) +target_compile_definitions(libnest2d PUBLIC LIBNEST2D_THREADING_tbb LIBNEST2D_STATIC LIBNEST2D_OPTIMIZER_nlopt LIBNEST2D_GEOMETRIES_clipper) diff --git a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp index dd80322bc..9586db35c 100644 --- a/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp +++ b/src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp @@ -26,7 +26,10 @@ template<> struct ShapeTag { using Type = PointTag; }; // Type of coordinate units used by Clipper. Enough to specialize for point, // the rest of the types will work (Path, Polygon) -template<> struct CoordType { using Type = ClipperLib::cInt; }; +template<> struct CoordType { + using Type = ClipperLib::cInt; + static const constexpr ClipperLib::cInt MM_IN_COORDS = 1000000; +}; // Enough to specialize for path, it will work for multishape and Polygon template<> struct PointType { using Type = PointImpl; }; @@ -95,6 +98,9 @@ inline void offset(PolygonImpl& sh, TCoord distance, const PolygonTag // Offsetting reverts the orientation and also removes the last vertex // so boost will not have a closed polygon. + // we plan to replace contours + sh.Holes.clear(); + bool found_the_contour = false; for(auto& r : result) { if(ClipperLib::Orientation(r)) { diff --git a/src/libnest2d/include/libnest2d/geometry_traits.hpp b/src/libnest2d/include/libnest2d/geometry_traits.hpp index c447cfcd9..d9c3d7862 100644 --- a/src/libnest2d/include/libnest2d/geometry_traits.hpp +++ b/src/libnest2d/include/libnest2d/geometry_traits.hpp @@ -47,7 +47,8 @@ using TPoint = typename PointType>::Type; /// Getting the coordinate data type for a geometry class. template struct CoordType { - using Type = typename CoordType>::Type; + using Type = typename CoordType>::Type; + static const constexpr Type MM_IN_COORDS = Type{1}; }; /// TCoord as shorthand for typename `CoordType::Type`. diff --git a/src/libnest2d/include/libnest2d/libnest2d.hpp b/src/libnest2d/include/libnest2d/libnest2d.hpp index 5eef28c40..9d24a2569 100644 --- a/src/libnest2d/include/libnest2d/libnest2d.hpp +++ b/src/libnest2d/include/libnest2d/libnest2d.hpp @@ -130,6 +130,11 @@ std::size_t nest(Container&& cont, return nest(cont.begin(), cont.end(), bin, dist, cfg, ctl); } +template enable_if_t::value, TCoord> mm(T val = T(1)) +{ + return TCoord(val * CoordType::MM_IN_COORDS); +} + } #endif // LIBNEST2D_HPP diff --git a/src/libnest2d/include/libnest2d/parallel.hpp b/src/libnest2d/include/libnest2d/parallel.hpp new file mode 100644 index 000000000..2eaf86c01 --- /dev/null +++ b/src/libnest2d/include/libnest2d/parallel.hpp @@ -0,0 +1,63 @@ +#ifndef LIBNEST2D_PARALLEL_HPP +#define LIBNEST2D_PARALLEL_HPP + +#include +#include +#include + +#ifdef LIBNEST2D_THREADING_tbb +#include +#endif + +#ifdef LIBNEST2D_THREADING_omp +#include +#endif + +namespace libnest2d { namespace __parallel { + +template +using TIteratorValue = typename std::iterator_traits::value_type; + +template +inline void enumerate( + Iterator from, Iterator to, + std::function, size_t)> fn, + std::launch policy = std::launch::deferred | std::launch::async) +{ + using TN = size_t; + auto iN = to-from; + TN N = iN < 0? 0 : TN(iN); + +#ifdef LIBNEST2D_THREADING_tbb + if((policy & std::launch::async) == std::launch::async) { + tbb::parallel_for(0, N, [from, fn] (TN n) { fn(*(from + n), n); } ); + } else { + for(TN n = 0; n < N; n++) fn(*(from + n), n); + } +#endif + +#ifdef LIBNEST2D_THREADING_omp + if((policy & std::launch::async) == std::launch::async) { + #pragma omp parallel for + for(int n = 0; n < int(N); n++) fn(*(from + n), TN(n)); + } + else { + for(TN n = 0; n < N; n++) fn(*(from + n), n); + } +#endif + +#ifdef LIBNEST2D_THREADING_std + std::vector> rets(N); + + auto it = from; + for(TN b = 0; b < N; b++) { + rets[b] = std::async(policy, fn, *it++, unsigned(b)); + } + + for(TN fi = 0; fi < N; ++fi) rets[fi].wait(); +#endif +} + +}} + +#endif //LIBNEST2D_PARALLEL_HPP diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 83f7bd246..bd9c60355 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -20,59 +20,9 @@ // temporary //#include "../tools/svgtools.hpp" -#ifdef USE_TBB -#include -#elif defined(_OPENMP) -#include -#endif +#include namespace libnest2d { - -namespace __parallel { - -using std::function; -using std::iterator_traits; -template -using TIteratorValue = typename iterator_traits::value_type; - -template -inline void enumerate( - Iterator from, Iterator to, - function, size_t)> fn, - std::launch policy = std::launch::deferred | std::launch::async) -{ - using TN = size_t; - auto iN = to-from; - TN N = iN < 0? 0 : TN(iN); - -#ifdef USE_TBB - if((policy & std::launch::async) == std::launch::async) { - tbb::parallel_for(0, N, [from, fn] (TN n) { fn(*(from + n), n); } ); - } else { - for(TN n = 0; n < N; n++) fn(*(from + n), n); - } -#elif defined(_OPENMP) - if((policy & std::launch::async) == std::launch::async) { - #pragma omp parallel for - for(int n = 0; n < int(N); n++) fn(*(from + n), TN(n)); - } - else { - for(TN n = 0; n < N; n++) fn(*(from + n), n); - } -#else - std::vector> rets(N); - - auto it = from; - for(TN b = 0; b < N; b++) { - rets[b] = std::async(policy, fn, *it++, unsigned(b)); - } - - for(TN fi = 0; fi < N; ++fi) rets[fi].wait(); -#endif -} - -} - namespace placers { template diff --git a/src/libnest2d/tools/svgtools.hpp b/src/libnest2d/tools/svgtools.hpp index 2a05b551d..47757cd46 100644 --- a/src/libnest2d/tools/svgtools.hpp +++ b/src/libnest2d/tools/svgtools.hpp @@ -54,10 +54,10 @@ public: if(conf_.origo_location == BOTTOMLEFT) { auto d = static_cast( std::round(conf_.height*conf_.mm_in_coord_units) ); - + auto& contour = shapelike::contour(tsh); for(auto& v : contour) setY(v, -getY(v) + d); - + auto& holes = shapelike::holes(tsh); for(auto& h : holes) for(auto& v : h) setY(v, -getY(v) + d); @@ -81,6 +81,18 @@ public: finishLayer(); } } + + template void writeItems(ItemIt from, ItemIt to) { + auto it = from; + PackGroup pg; + while(it != to) { + if(it->binId() == BIN_ID_UNSET) continue; + while(pg.size() <= size_t(it->binId())) pg.emplace_back(); + pg[it->binId()].emplace_back(*it); + ++it; + } + writePackGroup(pg); + } void addLayer() { svg_layers_.emplace_back(header()); diff --git a/tests/libnest2d/printer_parts.hpp b/tests/libnest2d/printer_parts.hpp index 1e65826bd..075e32a83 100644 --- a/tests/libnest2d/printer_parts.hpp +++ b/tests/libnest2d/printer_parts.hpp @@ -2,10 +2,10 @@ #define PRINTER_PARTS_H #include -#include +#include -using TestData = std::vector; -using TestDataEx = std::vector; +using TestData = std::vector; +using TestDataEx = std::vector; extern const TestData PRINTER_PART_POLYGONS; extern const TestData STEGOSAUR_POLYGONS;