Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::arrangement::AutoArranger< TBin > Class Template Reference
+ Collaboration diagram for Slic3r::arrangement::AutoArranger< TBin >:

Public Types

using Placer = typename placers::_NofitPolyPlacer< ExPolygon, TBin >
 
using Selector = selections::_FirstFitSelection< ExPolygon >
 
using Packer = _Nester< Placer, Selector >
 
using PConfig = typename Packer::PlacementConfig
 
using Distance = TCoord< PointImpl >
 

Public Member Functions

 AutoArranger (const TBin &bin, const ArrangeParams &params, std::function< void(unsigned)> progressind, std::function< bool(void)> stopcond)
 
template<class It >
void operator() (It from, It to)
 
PConfigconfig ()
 
const PConfigconfig () const
 
void preload (std::vector< Item > &fixeditems)
 

Protected Member Functions

template<class T >
ArithmeticOnly< T, double > norm (T val)
 
std::tuple< double, Boxobjfunc (const Item &item, const Point &bincenter)
 
std::function< double(const Item &)> get_objfn ()
 
std::function< double(const Item &)> get_objfn ()
 
std::function< double(const Item &)> get_objfn ()
 
std::function< double(const Item &)> get_objfn ()
 

Protected Attributes

Packer m_pck
 
PConfig m_pconf
 
TBin m_bin
 
double m_bin_area
 
SpatIndex m_rtree
 
SpatIndex m_smallsrtree
 
double m_norm
 
MultiPolygon m_merged_pile
 
Box m_pilebb
 
ItemGroup m_remaining
 
ItemGroup m_items
 
size_t m_item_count = 0
 

Detailed Description

template<class TBin>
class Slic3r::arrangement::AutoArranger< TBin >

Member Typedef Documentation

◆ Distance

template<class TBin >
using Slic3r::arrangement::AutoArranger< TBin >::Distance = TCoord<PointImpl>

◆ Packer

template<class TBin >
using Slic3r::arrangement::AutoArranger< TBin >::Packer = _Nester<Placer, Selector>

◆ PConfig

template<class TBin >
using Slic3r::arrangement::AutoArranger< TBin >::PConfig = typename Packer::PlacementConfig

◆ Placer

template<class TBin >
using Slic3r::arrangement::AutoArranger< TBin >::Placer = typename placers::_NofitPolyPlacer<ExPolygon, TBin>

◆ Selector

template<class TBin >
using Slic3r::arrangement::AutoArranger< TBin >::Selector = selections::_FirstFitSelection<ExPolygon>

Constructor & Destructor Documentation

◆ AutoArranger()

template<class TBin >
Slic3r::arrangement::AutoArranger< TBin >::AutoArranger ( const TBin &  bin,
const ArrangeParams params,
std::function< void(unsigned)>  progressind,
std::function< bool(void)>  stopcond 
)
inline
319 : m_pck(bin, params.min_obj_distance)
320 , m_bin(bin)
321 , m_bin_area(sl::area(bin))
322 , m_norm(std::sqrt(m_bin_area))
323 {
324 fill_config(m_pconf, params);
325
326 // Set up a callback that is called just before arranging starts
327 // This functionality is provided by the Nester class (m_pack).
328 m_pconf.before_packing =
329 [this](const MultiPolygon& merged_pile, // merged pile
330 const ItemGroup& items, // packed items
331 const ItemGroup& remaining) // future items to be packed
332 {
333 m_items = items;
334 m_merged_pile = merged_pile;
335 m_remaining = remaining;
336
337 m_pilebb = sl::boundingBox(merged_pile);
338
339 m_rtree.clear();
340 m_smallsrtree.clear();
341
342 // We will treat big items (compared to the print bed) differently
343 auto isBig = [this](double a) {
344 return a / m_bin_area > BIG_ITEM_TRESHOLD ;
345 };
346
347 for(unsigned idx = 0; idx < items.size(); ++idx) {
348 Item& itm = items[idx];
349 if(isBig(itm.area())) m_rtree.insert({itm.boundingBox(), idx});
350 m_smallsrtree.insert({itm.boundingBox(), idx});
351 }
352 };
353
354 m_pconf.object_function = get_objfn();
355
356 m_pconf.on_preload = [this](const ItemGroup &items, PConfig &cfg) {
357 if (items.empty()) return;
358
359 cfg.alignment = PConfig::Alignment::DONT_ALIGN;
360 auto bb = sl::boundingBox(m_bin);
361 auto bbcenter = bb.center();
362 cfg.object_function = [this, bb, bbcenter](const Item &item) {
363 return fixed_overfit(objfunc(item, bbcenter), bb);
364 };
365 };
366
367 auto on_packed = params.on_packed;
368
369 if (progressind || on_packed)
370 m_pck.progressIndicator([this, progressind, on_packed](unsigned rem) {
371
372 if (progressind)
373 progressind(rem);
374
375 if (on_packed) {
376 int last_bed = m_pck.lastPackedBinId();
377 if (last_bed >= 0) {
378 Item &last_packed = m_pck.lastResult()[last_bed].back();
379 ArrangePolygon ap;
380 ap.bed_idx = last_packed.binId();
381 ap.priority = last_packed.priority();
382 on_packed(ap);
383 }
384 }
385 });
386
387 if (stopcond) m_pck.stopCondition(stopcond);
388
390 }
PConfig m_pconf
Definition Arrange.cpp:142
TBin m_bin
Definition Arrange.cpp:143
double m_norm
Definition Arrange.cpp:157
std::function< double(const Item &)> get_objfn()
double m_bin_area
Definition Arrange.cpp:144
ItemGroup m_items
Definition Arrange.cpp:161
std::tuple< double, Box > objfunc(const Item &item, const Point &bincenter)
Definition Arrange.cpp:175
Packer m_pck
Definition Arrange.cpp:141
ItemGroup m_remaining
Definition Arrange.cpp:160
Box m_pilebb
Definition Arrange.cpp:159
SpatIndex m_rtree
Definition Arrange.cpp:151
typename Packer::PlacementConfig PConfig
Definition Arrange.cpp:137
SpatIndex m_smallsrtree
Definition Arrange.cpp:152
MultiPolygon m_merged_pile
Definition Arrange.cpp:158
const PackGroup & lastResult() const
Definition nester.hpp:871
int lastPackedBinId() const
Definition nester.hpp:876
_Nester & progressIndicator(ProgressFunction func)
Set a progress indicator function object for the selector.
Definition nester.hpp:860
_Nester & stopCondition(StopCondition fn)
Set a predicate to tell when to abort nesting.
Definition nester.hpp:866
void configure(const PlacementConfig &pconf)
Definition nester.hpp:818
const double BIG_ITEM_TRESHOLD
Definition Arrange.cpp:80
void fill_config(PConf &pcfg, const ArrangeParams &params)
Definition Arrange.cpp:85
std::vector< std::reference_wrapper< Item > > ItemGroup
Definition Arrange.cpp:77
static double fixed_overfit(const std::tuple< double, Box > &result, const Box &binbb)
Definition Arrange.cpp:117
TPoint< P > back(const P &p)
Definition geometry_traits.hpp:873
Unit area(const Cntr &poly, const PathTag &)
Definition geometry_traits.hpp:971
_Box< TPoint< S > > boundingBox(const S &, const PathTag &)
Definition geometry_traits.hpp:706
TMultiShape< PolygonImpl > MultiPolygon
Definition libnest2d.hpp:34
_Item< PolygonImpl > Item
Definition libnest2d.hpp:36
ConstItemRange< typename Container::const_iterator > rem(typename Container::const_iterator it, const Container &cont)
Definition nester.hpp:534

References libnest2d::_Item< RawShape >::area(), Slic3r::arrangement::BIG_ITEM_TRESHOLD, libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), Slic3r::arrangement::fill_config(), Slic3r::arrangement::AutoArranger< TBin >::m_bin_area, Slic3r::arrangement::AutoArranger< TBin >::m_items, Slic3r::arrangement::AutoArranger< TBin >::m_merged_pile, Slic3r::arrangement::AutoArranger< TBin >::m_pconf, Slic3r::arrangement::AutoArranger< TBin >::m_pilebb, Slic3r::arrangement::AutoArranger< TBin >::m_remaining, Slic3r::arrangement::AutoArranger< TBin >::m_rtree, and Slic3r::arrangement::AutoArranger< TBin >::m_smallsrtree.

+ Here is the call graph for this function:

Member Function Documentation

◆ config() [1/2]

template<class TBin >
PConfig & Slic3r::arrangement::AutoArranger< TBin >::config ( )
inline
399{ return m_pconf; }

◆ config() [2/2]

template<class TBin >
const PConfig & Slic3r::arrangement::AutoArranger< TBin >::config ( ) const
inline
400{ return m_pconf; }

◆ get_objfn() [1/4]

template<class TBin >
std::function< double(const Item &)> Slic3r::arrangement::AutoArranger< TBin >::get_objfn ( )
protected

◆ get_objfn() [2/4]

std::function< double(const Item &)> Slic3r::arrangement::AutoArranger< Box >::get_objfn ( )
protected
413{
414 auto bincenter = m_bin.center();
415
416 return [this, bincenter](const Item &itm) {
417 auto result = objfunc(itm, bincenter);
418
419 double score = std::get<0>(result);
420 auto& fullbb = std::get<1>(result);
421
422 double miss = Placer::overfit(fullbb, m_bin);
423 miss = miss > 0? miss : 0;
424 score += miss * miss;
425
426 return score;
427 };
428}

◆ get_objfn() [3/4]

std::function< double(const Item &)> Slic3r::arrangement::AutoArranger< Circle >::get_objfn ( )
protected
431{
432 auto bincenter = m_bin.center();
433 return [this, bincenter](const Item &item) {
434
435 auto result = objfunc(item, bincenter);
436
437 double score = std::get<0>(result);
438
439 return score;
440 };
441}

◆ get_objfn() [4/4]

std::function< double(const Item &)> Slic3r::arrangement::AutoArranger< ExPolygon >::get_objfn ( )
protected
447{
448 auto bincenter = sl::boundingBox(m_bin).center();
449 return [this, bincenter](const Item &item) {
450 return std::get<0>(objfunc(item, bincenter));
451 };
452}

◆ norm()

template<class TBin >
template<class T >
ArithmeticOnly< T, double > Slic3r::arrangement::AutoArranger< TBin >::norm ( val)
inlineprotected
165 {
166 return double(val) / m_norm;
167 }

References Slic3r::arrangement::AutoArranger< TBin >::m_norm.

Referenced by Slic3r::arrangement::AutoArranger< TBin >::objfunc().

+ Here is the caller graph for this function:

◆ objfunc()

template<class TBin >
std::tuple< double, Box > Slic3r::arrangement::AutoArranger< TBin >::objfunc ( const Item item,
const Point bincenter 
)
inlineprotected
176 {
177 const double bin_area = m_bin_area;
178 const SpatIndex& spatindex = m_rtree;
179 const SpatIndex& smalls_spatindex = m_smallsrtree;
180
181 // We will treat big items (compared to the print bed) differently
182 auto isBig = [bin_area](double a) {
183 return a/bin_area > BIG_ITEM_TRESHOLD ;
184 };
185
186 // Candidate item bounding box
187 auto ibb = item.boundingBox();
188
189 // Calculate the full bounding box of the pile with the candidate item
190 auto fullbb = sl::boundingBox(m_pilebb, ibb);
191
192 // The bounding box of the big items (they will accumulate in the center
193 // of the pile
194 Box bigbb;
195 if(spatindex.empty()) bigbb = fullbb;
196 else {
197 auto boostbb = spatindex.bounds();
198 boost::geometry::convert(boostbb, bigbb);
199 }
200
201 // Will hold the resulting score
202 double score = 0;
203
204 // Density is the pack density: how big is the arranged pile
205 double density = 0;
206
207 // Distinction of cases for the arrangement scene
208 enum e_cases {
209 // This branch is for big items in a mixed (big and small) scene
210 // OR for all items in a small-only scene.
211 BIG_ITEM,
212
213 // This branch is for the last big item in a mixed scene
214 LAST_BIG_ITEM,
215
216 // For small items in a mixed scene.
217 SMALL_ITEM
218 } compute_case;
219
220 bool bigitems = isBig(item.area()) || spatindex.empty();
221 if(bigitems && !m_remaining.empty()) compute_case = BIG_ITEM;
222 else if (bigitems && m_remaining.empty()) compute_case = LAST_BIG_ITEM;
223 else compute_case = SMALL_ITEM;
224
225 switch (compute_case) {
226 case BIG_ITEM: {
227 const Point& minc = ibb.minCorner(); // bottom left corner
228 const Point& maxc = ibb.maxCorner(); // top right corner
229
230 // top left and bottom right corners
231 Point top_left{getX(minc), getY(maxc)};
232 Point bottom_right{getX(maxc), getY(minc)};
233
234 // Now the distance of the gravity center will be calculated to the
235 // five anchor points and the smallest will be chosen.
236 std::array<double, 5> dists;
237 auto cc = fullbb.center(); // The gravity center
238 dists[0] = pl::distance(minc, cc);
239 dists[1] = pl::distance(maxc, cc);
240 dists[2] = pl::distance(ibb.center(), cc);
241 dists[3] = pl::distance(top_left, cc);
242 dists[4] = pl::distance(bottom_right, cc);
243
244 // The smalles distance from the arranged pile center:
245 double dist = norm(*(std::min_element(dists.begin(), dists.end())));
246 double bindist = norm(pl::distance(ibb.center(), bincenter));
247 dist = 0.8 * dist + 0.2 * bindist;
248
249 // Prepare a variable for the alignment score.
250 // This will indicate: how well is the candidate item
251 // aligned with its neighbors. We will check the alignment
252 // with all neighbors and return the score for the best
253 // alignment. So it is enough for the candidate to be
254 // aligned with only one item.
255 auto alignment_score = 1.0;
256
257 auto query = bgi::intersects(ibb);
258 auto& index = isBig(item.area()) ? spatindex : smalls_spatindex;
259
260 // Query the spatial index for the neighbors
261 std::vector<SpatElement> result;
262 result.reserve(index.size());
263
264 index.query(query, std::back_inserter(result));
265
266 // now get the score for the best alignment
267 for(auto& e : result) {
268 auto idx = e.second;
269 Item& p = m_items[idx];
270 auto parea = p.area();
271 if(std::abs(1.0 - parea/item.area()) < 1e-6) {
272 auto bb = sl::boundingBox(p.boundingBox(), ibb);
273 auto bbarea = bb.area();
274 auto ascore = 1.0 - (item.area() + parea)/bbarea;
275
276 if(ascore < alignment_score) alignment_score = ascore;
277 }
278 }
279
280 density = std::sqrt(norm(fullbb.width()) * norm(fullbb.height()));
281 double R = double(m_remaining.size()) / m_item_count;
282
283 // The final mix of the score is the balance between the
284 // distance from the full pile center, the pack density and
285 // the alignment with the neighbors
286 if (result.empty())
287 score = 0.50 * dist + 0.50 * density;
288 else
289 // Let the density matter more when fewer objects remain
290 score = 0.50 * dist + (1.0 - R) * 0.20 * density +
291 0.30 * alignment_score;
292
293 break;
294 }
295 case LAST_BIG_ITEM: {
296 score = norm(pl::distance(ibb.center(), m_pilebb.center()));
297 break;
298 }
299 case SMALL_ITEM: {
300 // Here there are the small items that should be placed around the
301 // already processed bigger items.
302 // No need to play around with the anchor points, the center will be
303 // just fine for small items
304 score = norm(pl::distance(ibb.center(), bigbb.center()));
305 break;
306 }
307 }
308
309 return std::make_tuple(score, fullbb);
310 }
size_t m_item_count
Definition Arrange.cpp:162
ArithmeticOnly< T, double > norm(T val)
Definition Arrange.cpp:164
P center() const BP2D_NOEXCEPT
Definition geometry_traits.hpp:499
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:280
bgi::rtree< SpatElement, bgi::rstar< 16, 4 > > SpatIndex
Definition Arrange.cpp:76
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
TCoord< P > getX(const P &p)
Definition geometry_traits.hpp:424
_Box< PointImpl > Box
Definition libnest2d.hpp:31
TCoord< P > getY(const P &p)
Definition geometry_traits.hpp:427
Kernel::Point_2 Point
Definition point_areas.cpp:20

References libnest2d::_Item< RawShape >::area(), Slic3r::arrangement::BIG_ITEM_TRESHOLD, libnest2d::_Item< RawShape >::boundingBox(), libnest2d::shapelike::boundingBox(), libnest2d::_Box< P >::center(), libnest2d::pointlike::distance(), libnest2d::getX(), libnest2d::getY(), Slic3r::arrangement::AutoArranger< TBin >::m_bin_area, Slic3r::arrangement::AutoArranger< TBin >::m_item_count, Slic3r::arrangement::AutoArranger< TBin >::m_items, Slic3r::arrangement::AutoArranger< TBin >::m_pilebb, Slic3r::arrangement::AutoArranger< TBin >::m_remaining, Slic3r::arrangement::AutoArranger< TBin >::m_rtree, Slic3r::arrangement::AutoArranger< TBin >::m_smallsrtree, and Slic3r::arrangement::AutoArranger< TBin >::norm().

+ Here is the call graph for this function:

◆ operator()()

template<class TBin >
template<class It >
void Slic3r::arrangement::AutoArranger< TBin >::operator() ( It  from,
It  to 
)
inline
392 {
393 m_rtree.clear();
394 m_item_count += size_t(to - from);
395 m_pck.execute(from, to);
396 m_item_count = 0;
397 }
ItemIteratorOnly< It, size_t > execute(It from, It to)
Arrange an input sequence of _Item-s.
Definition nester.hpp:842

References libnest2d::_Nester< PlacementStrategy, SelectionStrategy >::execute().

+ Here is the call graph for this function:

◆ preload()

template<class TBin >
void Slic3r::arrangement::AutoArranger< TBin >::preload ( std::vector< Item > &  fixeditems)
inline
402 {
403 for(unsigned idx = 0; idx < fixeditems.size(); ++idx) {
404 Item& itm = fixeditems[idx];
405 itm.markAsFixedInBin(itm.binId());
406 }
407
408 m_item_count += fixeditems.size();
409 }

References libnest2d::_Item< RawShape >::binId(), and libnest2d::_Item< RawShape >::markAsFixedInBin().

+ Here is the call graph for this function:

Member Data Documentation

◆ m_bin

template<class TBin >
TBin Slic3r::arrangement::AutoArranger< TBin >::m_bin
protected

◆ m_bin_area

◆ m_item_count

template<class TBin >
size_t Slic3r::arrangement::AutoArranger< TBin >::m_item_count = 0
protected

◆ m_items

◆ m_merged_pile

template<class TBin >
MultiPolygon Slic3r::arrangement::AutoArranger< TBin >::m_merged_pile
protected

◆ m_norm

template<class TBin >
double Slic3r::arrangement::AutoArranger< TBin >::m_norm
protected

◆ m_pck

template<class TBin >
Packer Slic3r::arrangement::AutoArranger< TBin >::m_pck
protected

◆ m_pconf

template<class TBin >
PConfig Slic3r::arrangement::AutoArranger< TBin >::m_pconf
protected

◆ m_pilebb

◆ m_remaining

◆ m_rtree

◆ m_smallsrtree


The documentation for this class was generated from the following file: