Many comments for maintainability.
This commit is contained in:
parent
ba1abf3f1f
commit
207c87a3d1
1 changed files with 58 additions and 26 deletions
|
@ -15,6 +15,7 @@ namespace arr {
|
|||
|
||||
using namespace libnest2d;
|
||||
|
||||
// Only for debugging. Prints the model object vertices on stdout.
|
||||
std::string toString(const Model& model, bool holes = true) {
|
||||
std::stringstream ss;
|
||||
|
||||
|
@ -78,6 +79,7 @@ std::string toString(const Model& model, bool holes = true) {
|
|||
return ss.str();
|
||||
}
|
||||
|
||||
// Debugging: Save model to svg file.
|
||||
void toSVG(SVG& svg, const Model& model) {
|
||||
for(auto objptr : model.objects) {
|
||||
if(!objptr) continue;
|
||||
|
@ -121,6 +123,10 @@ Box boundingBox(const Box& pilebb, const Box& ibb ) {
|
|||
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*/>
|
||||
objfunc(const PointImpl& bincenter,
|
||||
const shapelike::Shapes<PolygonImpl>& merged_pile,
|
||||
|
@ -253,6 +259,8 @@ objfunc(const PointImpl& bincenter,
|
|||
return std::make_tuple(score, fullbb);
|
||||
}
|
||||
|
||||
// Fill in the placer algorithm configuration with values carefully chosen for
|
||||
// Slic3r.
|
||||
template<class PConf>
|
||||
void fillConfig(PConf& pcfg) {
|
||||
|
||||
|
@ -274,13 +282,19 @@ void fillConfig(PConf& pcfg) {
|
|||
pcfg.parallel = true;
|
||||
}
|
||||
|
||||
// Type trait for an arranger class for different bin types (box, circle,
|
||||
// polygon, etc...)
|
||||
template<class TBin>
|
||||
class AutoArranger {};
|
||||
|
||||
|
||||
// A class encapsulating the libnest2d Nester class and extending it with other
|
||||
// management and spatial index structures for acceleration.
|
||||
template<class TBin>
|
||||
class _ArrBase {
|
||||
protected:
|
||||
|
||||
// Useful type shortcuts...
|
||||
using Placer = TPacker<TBin>;
|
||||
using Selector = FirstFitSelection;
|
||||
using Packer = Nester<Placer, Selector>;
|
||||
|
@ -289,15 +303,15 @@ protected:
|
|||
using Pile = sl::Shapes<PolygonImpl>;
|
||||
|
||||
Packer m_pck;
|
||||
PConfig m_pconf; // Placement configuration
|
||||
PConfig m_pconf; // Placement configuration
|
||||
double m_bin_area;
|
||||
SpatIndex m_rtree;
|
||||
SpatIndex m_smallsrtree;
|
||||
double m_norm;
|
||||
Pile m_merged_pile;
|
||||
Box m_pilebb;
|
||||
ItemGroup m_remaining;
|
||||
ItemGroup m_items;
|
||||
SpatIndex m_rtree; // spatial index for the normal (bigger) objects
|
||||
SpatIndex m_smallsrtree; // spatial index for only the smaller items
|
||||
double m_norm; // A coefficient to scale distances
|
||||
Pile m_merged_pile; // The already merged pile (vector of items)
|
||||
Box m_pilebb; // The bounding box of the merged pile.
|
||||
ItemGroup m_remaining; // Remaining items (m_items at the beginning)
|
||||
ItemGroup m_items; // The items to be packed
|
||||
public:
|
||||
|
||||
_ArrBase(const TBin& bin, Distance dist,
|
||||
|
@ -308,6 +322,8 @@ public:
|
|||
{
|
||||
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 =
|
||||
[this](const Pile& merged_pile, // merged pile
|
||||
const ItemGroup& items, // packed items
|
||||
|
@ -344,8 +360,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class AutoArranger<Box>: public _ArrBase<Box> {
|
||||
// Arranger specialization for a Box shaped bin.
|
||||
template<> class AutoArranger<Box>: public _ArrBase<Box> {
|
||||
public:
|
||||
|
||||
AutoArranger(const Box& bin, Distance dist,
|
||||
|
@ -354,6 +370,9 @@ public:
|
|||
_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) {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
template<>
|
||||
class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
|
||||
// Arranger specialization for circle shaped bin.
|
||||
template<> class AutoArranger<lnCircle>: public _ArrBase<lnCircle> {
|
||||
public:
|
||||
|
||||
AutoArranger(const lnCircle& bin, Distance dist,
|
||||
|
@ -396,6 +415,7 @@ public:
|
|||
std::function<bool(void)> 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) {
|
||||
|
||||
auto result = objfunc(bin.center(),
|
||||
|
@ -431,8 +451,9 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
|
||||
// Arranger specialization for a generalized polygon.
|
||||
// Warning: this is unfinished business. It may or may not work.
|
||||
template<> class AutoArranger<PolygonImpl>: public _ArrBase<PolygonImpl> {
|
||||
public:
|
||||
AutoArranger(const PolygonImpl& bin, Distance dist,
|
||||
std::function<void(unsigned)> progressind,
|
||||
|
@ -461,8 +482,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
template<> // Specialization with no bin
|
||||
class AutoArranger<bool>: public _ArrBase<Box> {
|
||||
// Specialization with no bin. In this case the arranger should just arrange
|
||||
// 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:
|
||||
|
||||
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
|
||||
// 2D shape from top view.
|
||||
using ShapeData2D =
|
||||
std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
|
||||
using ShapeData2D = std::vector<std::pair<Slic3r::ModelInstance*, Item>>;
|
||||
|
||||
ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
||||
ShapeData2D ret;
|
||||
|
||||
auto s = std::accumulate(model.objects.begin(), model.objects.end(), size_t(0),
|
||||
[](size_t s, ModelObject* o){
|
||||
// Count all the items on the bin (all the object's instances)
|
||||
auto s = std::accumulate(model.objects.begin(), model.objects.end(),
|
||||
size_t(0), [](size_t s, ModelObject* o)
|
||||
{
|
||||
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_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();
|
||||
|
||||
p.make_clockwise();
|
||||
|
@ -549,6 +574,8 @@ ShapeData2D projectModelFromTop(const Slic3r::Model &model) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
// Apply the calculated translations and rotations (currently disabled) to the
|
||||
// Model object instances.
|
||||
void applyResult(
|
||||
IndexedPackGroup::value_type& group,
|
||||
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 ret;
|
||||
|
||||
|
@ -654,11 +682,15 @@ BedShapeHint bedShape(const Polyline &bed) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool arrange(Model &model,
|
||||
coord_t min_obj_distance,
|
||||
const Polyline &bed,
|
||||
BedShapeHint bedhint,
|
||||
bool first_bin_only,
|
||||
// The final client function to arrange the Model. A progress indicator and
|
||||
// a stop predicate can be also be passed to control the process.
|
||||
bool arrange(Model &model, // The model with the geometries
|
||||
coord_t min_obj_distance, // Has to be in scaled (clipper) measure
|
||||
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<bool ()> stopcondition)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue