Merge branch 'tm_libnest2d_backport'

This commit is contained in:
tamasmeszaros 2021-04-01 09:50:12 +02:00
commit 04526d5c28
8 changed files with 96 additions and 59 deletions

View File

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

View File

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

View File

@ -48,6 +48,7 @@ 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;
static const constexpr Type MM_IN_COORDS = Type{1};
};
/// TCoord<GeomType> as shorthand for typename `CoordType<GeomType>::Type`.

View File

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

View File

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

View File

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

View File

@ -82,6 +82,18 @@ public:
}
}
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());
finished_ = false;

View File

@ -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;