Arranging with new structure.

This commit is contained in:
tamasmeszaros 2019-06-28 17:03:50 +02:00
parent 19e6bf58dd
commit 299e4f74c7
11 changed files with 189 additions and 479 deletions

View file

@ -30,9 +30,7 @@ using Circle = _Circle<PointImpl>;
using Item = _Item<PolygonImpl>;
using Rectangle = _Rectangle<PolygonImpl>;
using PackGroup = _PackGroup<PolygonImpl>;
using IndexedPackGroup = _IndexedPackGroup<PolygonImpl>;
using FillerSelection = selections::_FillerSelection<PolygonImpl>;
using FirstFitSelection = selections::_FirstFitSelection<PolygonImpl>;

View file

@ -65,6 +65,8 @@ class _Item {
Box bb; bool valid;
BBCache(): valid(false) {}
} bb_cache_;
std::function<void(const _Item&, unsigned)> applyfn_;
public:
@ -121,8 +123,26 @@ public:
inline _Item(TContour<RawShape>&& contour,
THolesContainer<RawShape>&& holes):
sh_(sl::create<RawShape>(std::move(contour),
std::move(holes))) {}
sh_(sl::create<RawShape>(std::move(contour), std::move(holes))) {}
template<class... Args>
_Item(std::function<void(const _Item&, unsigned)> applyfn, Args &&... args):
_Item(std::forward<Args>(args)...)
{
applyfn_ = std::move(applyfn);
}
// Call the apply callback set in constructor. Within the callback, the
// original caller can apply the stored transformation to the original
// objects inteded for nesting. It might not be the shape handed over
// to _Item (e.g. arranging 3D shapes based on 2D silhouette or the
// client uses a simplified or processed polygon for nesting)
// This callback, if present, will be called for each item after the nesting
// is finished.
inline void callApplyFunction(unsigned binidx) const
{
if (applyfn_) applyfn_(*this, binidx);
}
/**
* @brief Convert the polygon to string representation. The format depends
@ -492,24 +512,6 @@ template<class RawShape> using _ItemGroup = std::vector<_ItemRef<RawShape>>;
template<class RawShape>
using _PackGroup = std::vector<std::vector<_ItemRef<RawShape>>>;
/**
* \brief A list of packed (index, item) pair vectors. Each vector represents a
* bin.
*
* The index is points to the position of the item in the original input
* sequence. This way the caller can use the items as a transformation data
* carrier and transform the original objects manually.
*/
template<class RawShape>
using _IndexedPackGroup = std::vector<
std::vector<
std::pair<
unsigned,
_ItemRef<RawShape>
>
>
>;
template<class Iterator>
struct ConstItemRange {
Iterator from;
@ -768,13 +770,9 @@ public:
using BinType = typename TPlacer::BinType;
using PlacementConfig = typename TPlacer::Config;
using SelectionConfig = typename TSel::Config;
using Unit = TCoord<TPoint<typename Item::ShapeType>>;
using IndexedPackGroup = _IndexedPackGroup<typename Item::ShapeType>;
using PackGroup = _PackGroup<typename Item::ShapeType>;
using ResultType = PackGroup;
using ResultTypeIndexed = IndexedPackGroup;
private:
BinType bin_;
@ -786,6 +784,7 @@ private:
using TSItem = remove_cvref_t<SItem>;
std::vector<TPItem> item_cache_;
StopCondition stopfn_;
public:
@ -814,11 +813,13 @@ public:
void configure(const PlacementConfig& pconf) { pconfig_ = pconf; }
void configure(const SelectionConfig& sconf) { selector_.configure(sconf); }
void configure(const PlacementConfig& pconf, const SelectionConfig& sconf) {
void configure(const PlacementConfig& pconf, const SelectionConfig& sconf)
{
pconfig_ = pconf;
selector_.configure(sconf);
}
void configure(const SelectionConfig& sconf, const PlacementConfig& pconf) {
void configure(const SelectionConfig& sconf, const PlacementConfig& pconf)
{
pconfig_ = pconf;
selector_.configure(sconf);
}
@ -836,26 +837,6 @@ public:
return _execute(from, to);
}
/**
* A version of the arrange method returning an IndexedPackGroup with
* the item indexes into the original input sequence.
*
* Takes a little longer to collect the indices. Scales linearly with the
* input sequence size.
*/
template<class TIterator>
inline IndexedPackGroup executeIndexed(TIterator from, TIterator to)
{
return _executeIndexed(from, to);
}
/// Shorthand to normal arrange method.
template<class TIterator>
inline PackGroup operator() (TIterator from, TIterator to)
{
return _execute(from, to);
}
/// Set a progress indicator function object for the selector.
inline Nester& progressIndicator(ProgressFunction func)
{
@ -865,7 +846,7 @@ public:
/// Set a predicate to tell when to abort nesting.
inline Nester& stopCondition(StopCondition fn)
{
selector_.stopCondition(fn); return *this;
stopfn_ = fn; selector_.stopCondition(fn); return *this;
}
inline const PackGroup& lastResult() const
@ -878,16 +859,6 @@ public:
selector_.preload(pgrp);
}
inline void preload(const IndexedPackGroup& ipgrp)
{
PackGroup pgrp; pgrp.reserve(ipgrp.size());
for(auto& ig : ipgrp) {
pgrp.emplace_back(); pgrp.back().reserve(ig.size());
for(auto& r : ig) pgrp.back().emplace_back(r.second);
}
preload(pgrp);
}
private:
template<class TIterator,
@ -917,66 +888,6 @@ private:
return lastResult();
}
template<class TIterator,
class IT = remove_cvref_t<typename TIterator::value_type>,
// This function will be used only if the iterators are pointing to
// a type compatible with the libnest2d::_Item template.
// This way we can use references to input elements as they will
// have to exist for the lifetime of this call.
class T = enable_if_t< std::is_convertible<IT, TPItem>::value, IT>
>
inline IndexedPackGroup _executeIndexed(TIterator from,
TIterator to,
bool = false)
{
__execute(from, to);
return createIndexedPackGroup(from, to, selector_);
}
template<class TIterator,
class IT = remove_cvref_t<typename TIterator::value_type>,
class T = enable_if_t<!std::is_convertible<IT, TPItem>::value, IT>
>
inline IndexedPackGroup _executeIndexed(TIterator from,
TIterator to,
int = false)
{
item_cache_ = {from, to};
__execute(item_cache_.begin(), item_cache_.end());
return createIndexedPackGroup(from, to, selector_);
}
template<class TIterator>
static IndexedPackGroup createIndexedPackGroup(TIterator from,
TIterator to,
TSel& selector)
{
IndexedPackGroup pg;
pg.reserve(selector.getResult().size());
const PackGroup& pckgrp = selector.getResult();
for(size_t i = 0; i < pckgrp.size(); i++) {
auto items = pckgrp[i];
pg.emplace_back();
pg[i].reserve(items.size());
for(Item& itemA : items) {
auto it = from;
unsigned idx = 0;
while(it != to) {
Item& itemB = *it;
if(&itemB == &itemA) break;
it++; idx++;
}
pg[i].emplace_back(idx, itemA);
}
}
return pg;
}
template<class TIter> inline void __execute(TIter from, TIter to)
{
if(min_obj_distance_ > 0) std::for_each(from, to, [this](Item& item) {
@ -985,10 +896,19 @@ private:
selector_.template packItems<PlacementStrategy>(
from, to, bin_, pconfig_);
if(min_obj_distance_ > 0) std::for_each(from, to, [](Item& item) {
if(min_obj_distance_ > 0) std::for_each(from, to, [this](Item& item) {
item.removeOffset();
});
if(stopfn_ && !stopfn_()) { // Ignore results if nesting was stopped.
const PackGroup& bins = lastResult();
unsigned binidx = 0;
for(auto& bin : bins) {
for(const Item& itm : bin) itm.callApplyFunction(binidx);
++binidx;
}
}
}
};

View file

@ -366,7 +366,7 @@ TEST(GeometryAlgorithms, ArrangeRectanglesTight)
Nester<BottomLeftPlacer, DJDHeuristic> arrange(Box(210, 250));
auto groups = arrange(rects.begin(), rects.end());
auto groups = arrange.execute(rects.begin(), rects.end());
ASSERT_EQ(groups.size(), 1u);
ASSERT_EQ(groups[0].size(), rects.size());
@ -420,7 +420,7 @@ TEST(GeometryAlgorithms, ArrangeRectanglesLoose)
Nester<BottomLeftPlacer, DJDHeuristic> arrange(Box(210, 250),
min_obj_distance);
auto groups = arrange(rects.begin(), rects.end());
auto groups = arrange.execute(rects.begin(), rects.end());
ASSERT_EQ(groups.size(), 1u);
ASSERT_EQ(groups[0].size(), rects.size());