Просмотр исходного кода

Back-porting improvements for libnest2d

tamasmeszaros 4 лет назад
Родитель
Сommit
f117d02750

+ 1 - 1
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)

+ 7 - 1
src/libnest2d/include/libnest2d/backends/clipper/geometries.hpp

@@ -26,7 +26,10 @@ template<> struct ShapeTag<PointImpl>   { 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<PointImpl> { using Type = ClipperLib::cInt; };
+template<> struct CoordType<PointImpl> { 
+    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<PathImpl> { using Type = PointImpl; };
@@ -95,6 +98,9 @@ inline void offset(PolygonImpl& sh, TCoord<PointImpl> 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)) {

+ 2 - 1
src/libnest2d/include/libnest2d/geometry_traits.hpp

@@ -47,7 +47,8 @@ using TPoint = typename PointType<remove_cvref_t<Shape>>::Type;
 
 /// Getting the coordinate data type for a geometry class.
 template<class GeomClass> struct CoordType { 
-    using Type = typename CoordType<TPoint<GeomClass>>::Type; 
+    using Type = typename CoordType<TPoint<GeomClass>>::Type;
+    static const constexpr Type MM_IN_COORDS = Type{1};
 };
 
 /// TCoord<GeomType> as shorthand for typename `CoordType<GeomType>::Type`.

+ 5 - 0
src/libnest2d/include/libnest2d/libnest2d.hpp

@@ -130,6 +130,11 @@ std::size_t nest(Container&& cont,
     return nest<Placer, Selector>(cont.begin(), cont.end(), bin, dist, cfg, ctl);
 }
 
+template<class T = double> enable_if_t<std::is_arithmetic<T>::value, TCoord<PointImpl>> mm(T val = T(1)) 
+{
+    return TCoord<PointImpl>(val * CoordType<PointImpl>::MM_IN_COORDS);
+}
+
 }
 
 #endif // LIBNEST2D_HPP

+ 63 - 0
src/libnest2d/include/libnest2d/parallel.hpp

@@ -0,0 +1,63 @@
+#ifndef LIBNEST2D_PARALLEL_HPP
+#define LIBNEST2D_PARALLEL_HPP
+
+#include <iterator>
+#include <functional>
+#include <future>
+
+#ifdef LIBNEST2D_THREADING_tbb
+#include <tbb/parallel_for.h>
+#endif
+
+#ifdef LIBNEST2D_THREADING_omp
+#include <omp.h>
+#endif
+
+namespace libnest2d { namespace __parallel {
+    
+template<class It> 
+using TIteratorValue = typename std::iterator_traits<It>::value_type;
+
+template<class Iterator>
+inline void enumerate(
+        Iterator from, Iterator to,
+        std::function<void(TIteratorValue<Iterator>, 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<TN>(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<std::future<void>> 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

+ 1 - 51
src/libnest2d/include/libnest2d/placers/nfpplacer.hpp

@@ -20,59 +20,9 @@
 // temporary
 //#include "../tools/svgtools.hpp"
 
-#ifdef USE_TBB
-#include <tbb/parallel_for.h>
-#elif defined(_OPENMP)
-#include <omp.h>
-#endif
+#include <libnest2d/parallel.hpp>
 
 namespace libnest2d {
-
-namespace __parallel {
-
-using std::function;
-using std::iterator_traits;
-template<class It>
-using TIteratorValue = typename iterator_traits<It>::value_type;
-
-template<class Iterator>
-inline void enumerate(
-        Iterator from, Iterator to,
-        function<void(TIteratorValue<Iterator>, 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<TN>(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<std::future<void>> 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<class RawShape>

+ 14 - 2
src/libnest2d/tools/svgtools.hpp

@@ -54,10 +54,10 @@ public:
         if(conf_.origo_location == BOTTOMLEFT) {
             auto d = static_cast<Coord>(
                 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<class ItemIt> 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());

+ 3 - 3
tests/libnest2d/printer_parts.hpp

@@ -2,10 +2,10 @@
 #define PRINTER_PARTS_H
 
 #include <vector>
-#include <libnest2d/backends/clipper/clipper_polygon.hpp>
+#include <libnest2d/libnest2d.hpp>
 
-using TestData = std::vector<ClipperLib::Path>;
-using TestDataEx = std::vector<ClipperLib::Polygon>;
+using TestData = std::vector<libnest2d::PathImpl>;
+using TestDataEx = std::vector<libnest2d::PolygonImpl>;
 
 extern const TestData PRINTER_PART_POLYGONS;
 extern const TestData STEGOSAUR_POLYGONS;