Back-porting improvements for libnest2d
This commit is contained in:
parent
ab3890dab5
commit
f117d02750
@ -28,4 +28,4 @@ add_library(libnest2d STATIC ${LIBNEST2D_SRCFILES})
|
|||||||
|
|
||||||
target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(libnest2d PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
target_link_libraries(libnest2d PUBLIC clipper NLopt::nlopt TBB::tbb Boost::boost)
|
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)
|
||||||
|
@ -26,7 +26,10 @@ template<> struct ShapeTag<PointImpl> { using Type = PointTag; };
|
|||||||
|
|
||||||
// Type of coordinate units used by Clipper. Enough to specialize for point,
|
// Type of coordinate units used by Clipper. Enough to specialize for point,
|
||||||
// the rest of the types will work (Path, Polygon)
|
// 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
|
// Enough to specialize for path, it will work for multishape and Polygon
|
||||||
template<> struct PointType<PathImpl> { using Type = PointImpl; };
|
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
|
// Offsetting reverts the orientation and also removes the last vertex
|
||||||
// so boost will not have a closed polygon.
|
// so boost will not have a closed polygon.
|
||||||
|
|
||||||
|
// we plan to replace contours
|
||||||
|
sh.Holes.clear();
|
||||||
|
|
||||||
bool found_the_contour = false;
|
bool found_the_contour = false;
|
||||||
for(auto& r : result) {
|
for(auto& r : result) {
|
||||||
if(ClipperLib::Orientation(r)) {
|
if(ClipperLib::Orientation(r)) {
|
||||||
|
@ -47,7 +47,8 @@ using TPoint = typename PointType<remove_cvref_t<Shape>>::Type;
|
|||||||
|
|
||||||
/// Getting the coordinate data type for a geometry class.
|
/// Getting the coordinate data type for a geometry class.
|
||||||
template<class GeomClass> struct CoordType {
|
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`.
|
/// TCoord<GeomType> as shorthand for typename `CoordType<GeomType>::Type`.
|
||||||
|
@ -130,6 +130,11 @@ std::size_t nest(Container&& cont,
|
|||||||
return nest<Placer, Selector>(cont.begin(), cont.end(), bin, dist, cfg, ctl);
|
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
|
#endif // LIBNEST2D_HPP
|
||||||
|
63
src/libnest2d/include/libnest2d/parallel.hpp
Normal file
63
src/libnest2d/include/libnest2d/parallel.hpp
Normal 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
|
@ -20,59 +20,9 @@
|
|||||||
// temporary
|
// temporary
|
||||||
//#include "../tools/svgtools.hpp"
|
//#include "../tools/svgtools.hpp"
|
||||||
|
|
||||||
#ifdef USE_TBB
|
#include <libnest2d/parallel.hpp>
|
||||||
#include <tbb/parallel_for.h>
|
|
||||||
#elif defined(_OPENMP)
|
|
||||||
#include <omp.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace libnest2d {
|
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 {
|
namespace placers {
|
||||||
|
|
||||||
template<class RawShape>
|
template<class RawShape>
|
||||||
|
@ -54,10 +54,10 @@ public:
|
|||||||
if(conf_.origo_location == BOTTOMLEFT) {
|
if(conf_.origo_location == BOTTOMLEFT) {
|
||||||
auto d = static_cast<Coord>(
|
auto d = static_cast<Coord>(
|
||||||
std::round(conf_.height*conf_.mm_in_coord_units) );
|
std::round(conf_.height*conf_.mm_in_coord_units) );
|
||||||
|
|
||||||
auto& contour = shapelike::contour(tsh);
|
auto& contour = shapelike::contour(tsh);
|
||||||
for(auto& v : contour) setY(v, -getY(v) + d);
|
for(auto& v : contour) setY(v, -getY(v) + d);
|
||||||
|
|
||||||
auto& holes = shapelike::holes(tsh);
|
auto& holes = shapelike::holes(tsh);
|
||||||
for(auto& h : holes) for(auto& v : h) setY(v, -getY(v) + d);
|
for(auto& h : holes) for(auto& v : h) setY(v, -getY(v) + d);
|
||||||
|
|
||||||
@ -81,6 +81,18 @@ public:
|
|||||||
finishLayer();
|
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() {
|
void addLayer() {
|
||||||
svg_layers_.emplace_back(header());
|
svg_layers_.emplace_back(header());
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
#define PRINTER_PARTS_H
|
#define PRINTER_PARTS_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <libnest2d/backends/clipper/clipper_polygon.hpp>
|
#include <libnest2d/libnest2d.hpp>
|
||||||
|
|
||||||
using TestData = std::vector<ClipperLib::Path>;
|
using TestData = std::vector<libnest2d::PathImpl>;
|
||||||
using TestDataEx = std::vector<ClipperLib::Polygon>;
|
using TestDataEx = std::vector<libnest2d::PolygonImpl>;
|
||||||
|
|
||||||
extern const TestData PRINTER_PART_POLYGONS;
|
extern const TestData PRINTER_PART_POLYGONS;
|
||||||
extern const TestData STEGOSAUR_POLYGONS;
|
extern const TestData STEGOSAUR_POLYGONS;
|
||||||
|
Loading…
Reference in New Issue
Block a user