Many comments for maintainability.

This commit is contained in:
tamasmeszaros 2019-01-21 10:34:10 +01:00
parent ba1abf3f1f
commit 207c87a3d1

View file

@ -15,6 +15,7 @@ namespace arr {
using namespace libnest2d; using namespace libnest2d;
// Only for debugging. Prints the model object vertices on stdout.
std::string toString(const Model& model, bool holes = true) { std::string toString(const Model& model, bool holes = true) {
std::stringstream ss; std::stringstream ss;
@ -78,6 +79,7 @@ std::string toString(const Model& model, bool holes = true) {
return ss.str(); return ss.str();
} }
// Debugging: Save model to svg file.
void toSVG(SVG& svg, const Model& model) { void toSVG(SVG& svg, const Model& model) {
for(auto objptr : model.objects) { for(auto objptr : model.objects) {
if(!objptr) continue; if(!objptr) continue;
@ -121,6 +123,10 @@ Box boundingBox(const Box& pilebb, const Box& ibb ) {
return Box(minc, maxc); return Box(minc, maxc);
} }
// This is "the" object function which is evaluated many times for each vertex
// (decimated with the accuracy parameter) of each object. Therefore it is
// upmost crucial for this function to be as efficient as it possibly can be but
// at the same time, it has to provide reasonable results.
std::tuple<double /*score*/, Box /*farthest point from bin center*/> std::tuple<double /*score*/, Box /*farthest point from bin center*/>
objfunc(const PointImpl& bincenter, objfunc(const PointImpl& bincenter,
const shapelike::Shapes<PolygonImpl>& merged_pile, const shapelike::Shapes<PolygonImpl>& merged_pile,
@ -253,6 +259,8 @@ objfunc(const PointImpl& bincenter,
return std::make_tuple(score, fullbb); return std::make_tuple(score, fullbb);
} }
// Fill in the placer algorithm configuration with values carefully chosen for
// Slic3r.
template<class PConf> template<class PConf>
void fillConfig(PConf& pcfg) { void fillConfig(PConf& pcfg) {
@ -274,13 +282,19 @@ void fillConfig(PConf& pcfg) {
pcfg.parallel = true; pcfg.parallel = true;
} }
// Type trait for an arranger class for different bin types (box, circle,
// polygon, etc...)
template<class TBin> template<class TBin>
class AutoArranger {}; class AutoArranger {};
// A class encapsulating the libnest2d Nester class and extending it with other
// management and spatial index structures for acceleration.
template<class TBin> template<class TBin>
class _ArrBase { class _ArrBase {
protected: protected:
// Useful type shortcuts...
using Placer = TPacker<TBin>; using Placer = TPacker<TBin>;
using Selector = FirstFitSelection; using Selector = FirstFitSelection;
using Packer = Nester<Placer, Selector>; using Packer = Nester<Placer, Selector>;
@ -289,15 +303,15 @@ protected:
using Pile = sl::Shapes<PolygonImpl>; using Pile = sl::Shapes<PolygonImpl>;
Packer m_pck; Packer m_pck;
PConfig m_pconf; // Placement configuration PConfig m_pconf; // Placement configuration
double m_bin_area; double m_bin_area;
SpatIndex m_rtree; SpatIndex m_rtree; // spatial index for the normal (bigger) objects
SpatIndex m_smallsrtree; SpatIndex m_smallsrtree; // spatial index for only the smaller items
double m_norm; double m_norm; // A coefficient to scale distances
Pile m_merged_pile; Pile m_merged_pile; // The already merged pile (vector of items)
Box m_pilebb; Box m_pilebb; // The bounding box of the merged pile.
ItemGroup m_remaining; ItemGroup m_remaining; // Remaining items (m_items at the beginning)
ItemGroup m_items; ItemGroup m_items; // The items to be packed
public: public:
_ArrBase(const TBin& bin, Distance dist, _ArrBase(const TBin& bin, Distance dist,
@ -308,6 +322,8 @@ public:
{ {
fillConfig(m_pconf); fillConfig(m_pconf);
// Set up a callback that is called just before arranging starts
// This functionality is provided by the Nester class (m_pack).
m_pconf.before_packing = m_pconf.before_packing =
[this](const Pile& merged_pile, // merged pile [this](const Pile& merged_pile, // merged pile
const ItemGroup& items, // packed items const ItemGroup& items, // packed items
@ -344,8 +360,8 @@ public:
} }
}; };
template<> // Arranger specialization for a Box shaped bin.
class AutoArranger<Box>: public _ArrBase<Box> { template<> class AutoArranger<Box>: public _ArrBase<Box> {
public: public:
AutoArranger(const Box& bin, Distance dist, AutoArranger(const Box& bin, Distance dist,
@ -354,6 +370,9 @@ public:
_ArrBase<Box>(bin, dist, progressind, stopcond) _ArrBase<Box>(bin, dist, progressind, stopcond)
{ {
// Here we set up the actual object function that calls the common
// object function for all bin shapes than does an additional inside
// check for the arranged pile.
m_pconf.object_function = [this, bin] (const Item &item) { m_pconf.object_function = [this, bin] (const Item &item) {
auto result = objfunc(bin.center(), auto result = objfunc(bin.center(),
@ -387,8 +406,8 @@ inline lnCircle to_lnCircle(const Circle& circ) {
return lnCircle({circ.center()(0), circ.center()(1)}, circ.radius()); return lnCircle({circ.center()(0), circ.center()(1)}, circ.radius());
} }
template<> // Arranger specialization for circle shaped bin.
class AutoArranger<lnCircle>: public _ArrBase<lnCircle> { template<> class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
public: public:
AutoArranger(const lnCircle& bin, Distance dist, AutoArranger(const lnCircle& bin, Distance dist,
@ -396,6 +415,7 @@ public:
std::function<bool(void)> stopcond): std::function<bool(void)> stopcond):
_ArrBase<lnCircle>(bin, dist, progressind, stopcond) { _ArrBase<lnCircle>(bin, dist, progressind, stopcond) {
// As with the box, only the inside check is different.
m_pconf.object_function = [this, &bin] (const Item &item) { m_pconf.object_function = [this, &bin] (const Item &item) {
auto result = objfunc(bin.center(), auto result = objfunc(bin.center(),
@ -431,8 +451,9 @@ public:
} }
}; };
template<> // Arranger specialization for a generalized polygon.
class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> { // Warning: this is unfinished business. It may or may not work.
template<> class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
public: public:
AutoArranger(const PolygonImpl& bin, Distance dist, AutoArranger(const PolygonImpl& bin, Distance dist,
std::function<void(unsigned)> progressind, std::function<void(unsigned)> progressind,
@ -461,8 +482,10 @@ public:
} }
}; };
template<> // Specialization with no bin // Specialization with no bin. In this case the arranger should just arrange
class AutoArranger<bool>: public _ArrBase<Box> { // all objects into a minimum sized pile but it is not limited by a bin. A
// consequence is that only one pile should be created.
template<> class AutoArranger<bool>: public _ArrBase<Box> {
public: public:
AutoArranger(Distance dist, std::function<void(unsigned)> progressind, AutoArranger(Distance dist, std::function<void(unsigned)> progressind,
@ -490,14 +513,15 @@ public:
// A container which stores a pointer to the 3D object and its projected // A container which stores a pointer to the 3D object and its projected
// 2D shape from top view. // 2D shape from top view.
using ShapeData2D = using ShapeData2D = std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
ShapeData2D projectModelFromTop(const Slic3r::Model &model) { ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
ShapeData2D ret; ShapeData2D ret;
auto s = std::accumulate(model.objects.begin(), model.objects.end(), size_t(0), // Count all the items on the bin (all the object's instances)
[](size_t s, ModelObject* o){ auto s = std::accumulate(model.objects.begin(), model.objects.end(),
size_t(0), [](size_t s, ModelObject* o)
{
return s + o->instances.size(); return s + o->instances.size();
}); });
@ -517,7 +541,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
rmesh.rotate_x(float(finst->get_rotation()(X))); rmesh.rotate_x(float(finst->get_rotation()(X)));
rmesh.rotate_y(float(finst->get_rotation()(Y))); rmesh.rotate_y(float(finst->get_rotation()(Y)));
// TODO export the exact 2D projection // TODO export the exact 2D projection. Cannot do it as libnest2d
// does not support concave shapes (yet).
auto p = rmesh.convex_hull(); auto p = rmesh.convex_hull();
p.make_clockwise(); p.make_clockwise();
@ -549,6 +574,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
return ret; return ret;
} }
// Apply the calculated translations and rotations (currently disabled) to the
// Model object instances.
void applyResult( void applyResult(
IndexedPackGroup::value_type& group, IndexedPackGroup::value_type& group,
Coord batch_offset, Coord batch_offset,
@ -576,6 +603,7 @@ void applyResult(
} }
} }
// Get the type of bed geometry from a simple vector of points.
BedShapeHint bedShape(const Polyline &bed) { BedShapeHint bedShape(const Polyline &bed) {
BedShapeHint ret; BedShapeHint ret;
@ -654,11 +682,15 @@ BedShapeHint bedShape(const Polyline &bed) {
return ret; return ret;
} }
bool arrange(Model &model, // The final client function to arrange the Model. A progress indicator and
coord_t min_obj_distance, // a stop predicate can be also be passed to control the process.
const Polyline &bed, bool arrange(Model &model, // The model with the geometries
BedShapeHint bedhint, coord_t min_obj_distance, // Has to be in scaled (clipper) measure
bool first_bin_only, const Polyline &bed, // The bed geometry.
BedShapeHint bedhint, // Hint about the bed geometry type.
bool first_bin_only, // What to do is not all items fit.
// Controlling callbacks.
std::function<void (unsigned)> progressind, std::function<void (unsigned)> progressind,
std::function<bool ()> stopcondition) std::function<bool ()> stopcondition)
{ {