2018-07-30 14:41:35 +00:00
|
|
|
#ifndef MODELARRANGE_HPP
|
|
|
|
#define MODELARRANGE_HPP
|
|
|
|
|
2019-07-12 19:03:49 +00:00
|
|
|
#include "ExPolygon.hpp"
|
2019-06-26 15:09:26 +00:00
|
|
|
#include "BoundingBox.hpp"
|
2018-08-03 10:37:27 +00:00
|
|
|
|
2018-07-30 14:41:35 +00:00
|
|
|
namespace Slic3r {
|
2018-08-02 11:15:30 +00:00
|
|
|
|
2019-07-01 16:22:07 +00:00
|
|
|
namespace arrangement {
|
2018-07-30 14:41:35 +00:00
|
|
|
|
2019-06-28 16:27:15 +00:00
|
|
|
/// A geometry abstraction for a circular print bed. Similarly to BoundingBox.
|
2019-06-28 15:03:50 +00:00
|
|
|
class CircleBed {
|
2018-08-03 12:49:26 +00:00
|
|
|
Point center_;
|
|
|
|
double radius_;
|
|
|
|
public:
|
|
|
|
|
2019-06-28 15:03:50 +00:00
|
|
|
inline CircleBed(): center_(0, 0), radius_(std::nan("")) {}
|
|
|
|
inline CircleBed(const Point& c, double r): center_(c), radius_(r) {}
|
2018-08-03 12:49:26 +00:00
|
|
|
|
|
|
|
inline double radius() const { return radius_; }
|
|
|
|
inline const Point& center() const { return center_; }
|
2018-08-06 09:30:10 +00:00
|
|
|
inline operator bool() { return !std::isnan(radius_); }
|
2018-08-03 12:49:26 +00:00
|
|
|
};
|
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
/// Representing an unbounded bed.
|
2019-07-01 16:22:07 +00:00
|
|
|
struct InfiniteBed { Point center; };
|
|
|
|
|
2019-06-28 16:27:15 +00:00
|
|
|
/// Types of print bed shapes.
|
2019-07-15 15:30:44 +00:00
|
|
|
enum BedShapes {
|
|
|
|
bsBox,
|
|
|
|
bsCircle,
|
|
|
|
bsIrregular,
|
|
|
|
bsInfinite,
|
|
|
|
bsUnknown
|
2018-08-02 11:15:30 +00:00
|
|
|
};
|
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
/// Info about the print bed for the arrange() function. This is a variant
|
|
|
|
/// holding one of the four shapes a bed can be.
|
|
|
|
class BedShapeHint {
|
|
|
|
BedShapes m_type = BedShapes::bsInfinite;
|
|
|
|
|
|
|
|
union BedShape_u { // TODO: use variant from cpp17?
|
2019-07-01 16:22:07 +00:00
|
|
|
CircleBed circ;
|
2018-08-03 12:49:26 +00:00
|
|
|
BoundingBox box;
|
2019-07-01 16:22:07 +00:00
|
|
|
Polyline polygon;
|
2019-07-15 15:30:44 +00:00
|
|
|
InfiniteBed infbed{};
|
2019-07-12 19:03:49 +00:00
|
|
|
~BedShape_u() {}
|
|
|
|
BedShape_u() {};
|
2019-07-15 15:30:44 +00:00
|
|
|
} m_bed;
|
2019-07-12 19:03:49 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
public:
|
|
|
|
|
|
|
|
BedShapeHint(){};
|
2019-07-12 19:03:49 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
/// Get a bed shape hint for arrange() from a naked Polyline.
|
|
|
|
explicit BedShapeHint(const Polyline &polyl);
|
|
|
|
explicit BedShapeHint(const BoundingBox &bb)
|
|
|
|
{
|
|
|
|
m_type = bsBox; m_bed.box = bb;
|
|
|
|
}
|
2019-07-12 19:03:49 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
explicit BedShapeHint(const CircleBed &c)
|
|
|
|
{
|
|
|
|
m_type = bsCircle; m_bed.circ = c;
|
2019-07-12 19:03:49 +00:00
|
|
|
}
|
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
explicit BedShapeHint(const InfiniteBed &ibed)
|
|
|
|
{
|
|
|
|
m_type = bsInfinite; m_bed.infbed = ibed;
|
|
|
|
}
|
|
|
|
|
|
|
|
~BedShapeHint()
|
|
|
|
{
|
|
|
|
if (m_type == BedShapes::bsIrregular)
|
|
|
|
m_bed.polygon.Slic3r::Polyline::~Polyline();
|
|
|
|
};
|
|
|
|
|
|
|
|
BedShapeHint(const BedShapeHint &cpy) { *this = cpy; }
|
|
|
|
BedShapeHint(BedShapeHint &&cpy) { *this = std::move(cpy); }
|
|
|
|
|
|
|
|
BedShapeHint &operator=(const BedShapeHint &cpy)
|
|
|
|
{
|
|
|
|
m_type = cpy.m_type;
|
|
|
|
switch(m_type) {
|
|
|
|
case bsBox: m_bed.box = cpy.m_bed.box; break;
|
|
|
|
case bsCircle: m_bed.circ = cpy.m_bed.circ; break;
|
|
|
|
case bsIrregular: m_bed.polygon = cpy.m_bed.polygon; break;
|
|
|
|
case bsInfinite: m_bed.infbed = cpy.m_bed.infbed; break;
|
|
|
|
case bsUnknown: break;
|
2019-07-12 19:03:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
2018-08-03 12:49:26 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
BedShapeHint& operator=(BedShapeHint &&cpy)
|
|
|
|
{
|
|
|
|
m_type = cpy.m_type;
|
|
|
|
switch(m_type) {
|
|
|
|
case bsBox: m_bed.box = std::move(cpy.m_bed.box); break;
|
|
|
|
case bsCircle: m_bed.circ = std::move(cpy.m_bed.circ); break;
|
|
|
|
case bsIrregular: m_bed.polygon = std::move(cpy.m_bed.polygon); break;
|
|
|
|
case bsInfinite: m_bed.infbed = std::move(cpy.m_bed.infbed); break;
|
|
|
|
case bsUnknown: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
BedShapes get_type() const { return m_type; }
|
2018-08-02 11:15:30 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
const BoundingBox &get_box() const
|
|
|
|
{
|
|
|
|
assert(m_type == bsBox); return m_bed.box;
|
|
|
|
}
|
|
|
|
const CircleBed &get_circle() const
|
|
|
|
{
|
|
|
|
assert(m_type == bsCircle); return m_bed.circ;
|
|
|
|
}
|
|
|
|
const Polyline &get_irregular() const
|
|
|
|
{
|
|
|
|
assert(m_type == bsIrregular); return m_bed.polygon;
|
|
|
|
}
|
|
|
|
const InfiniteBed &get_infinite() const
|
|
|
|
{
|
|
|
|
assert(m_type == bsInfinite); return m_bed.infbed;
|
|
|
|
}
|
|
|
|
};
|
2019-07-12 19:03:49 +00:00
|
|
|
|
2019-07-15 15:30:44 +00:00
|
|
|
/// A logical bed representing an object not being arranged. Either the arrange
|
|
|
|
/// has not yet succesfully run on this ArrangePolygon or it could not fit the
|
|
|
|
/// object due to overly large size or invalid geometry.
|
|
|
|
static const constexpr int UNARRANGED = -1;
|
|
|
|
|
|
|
|
/// Input/Output structure for the arrange() function. The poly field will not
|
|
|
|
/// be modified during arrangement. Instead, the translation and rotation fields
|
|
|
|
/// will mark the needed transformation for the polygon to be in the arranged
|
|
|
|
/// position. These can also be set to an initial offset and rotation.
|
|
|
|
///
|
|
|
|
/// The bed_idx field will indicate the logical bed into which the
|
|
|
|
/// polygon belongs: UNARRANGED means no place for the polygon
|
|
|
|
/// (also the initial state before arrange), 0..N means the index of the bed.
|
|
|
|
/// Zero is the physical bed, larger than zero means a virtual bed.
|
2019-07-16 16:33:42 +00:00
|
|
|
struct ArrangePolygon {
|
|
|
|
ExPolygon poly; /// The 2D silhouette to be arranged
|
2019-07-15 15:30:44 +00:00
|
|
|
Vec2crd translation{0, 0}; /// The translation of the poly
|
|
|
|
double rotation{0.0}; /// The rotation of the poly in radians
|
|
|
|
int bed_idx{UNARRANGED}; /// To which logical bed does poly belong...
|
2019-07-16 16:33:42 +00:00
|
|
|
int priority{0};
|
2019-06-26 15:09:26 +00:00
|
|
|
|
2019-07-16 16:33:42 +00:00
|
|
|
/// Optional setter function which can store arbitrary data in its closure
|
|
|
|
std::function<void(const ArrangePolygon&)> setter = nullptr;
|
|
|
|
|
|
|
|
/// Helper function to call the setter with the arrange data arguments
|
|
|
|
void apply() const { if (setter) setter(*this); }
|
2019-04-29 12:32:02 +00:00
|
|
|
};
|
|
|
|
|
2019-07-12 19:03:49 +00:00
|
|
|
using ArrangePolygons = std::vector<ArrangePolygon>;
|
2019-06-26 15:09:26 +00:00
|
|
|
|
2018-07-30 14:41:35 +00:00
|
|
|
/**
|
2019-07-15 15:30:44 +00:00
|
|
|
* \brief Arranges the input polygons.
|
2018-07-30 14:41:35 +00:00
|
|
|
*
|
2019-07-15 15:30:44 +00:00
|
|
|
* WARNING: Currently, only convex polygons are supported by the libnest2d
|
|
|
|
* library which is used to do the arrangement. This might change in the future
|
|
|
|
* this is why the interface contains a general polygon capable to have holes.
|
2019-06-28 16:27:15 +00:00
|
|
|
*
|
2019-07-15 15:30:44 +00:00
|
|
|
* \param items Input vector of ArrangePolygons. The transformation, rotation
|
|
|
|
* and bin_idx fields will be changed after the call finished and can be used
|
|
|
|
* to apply the result on the input polygon.
|
2019-06-28 16:27:15 +00:00
|
|
|
*
|
|
|
|
* \param min_obj_distance The minimum distance which is allowed for any
|
|
|
|
* pair of items on the print bed in any direction.
|
|
|
|
*
|
2019-07-15 15:30:44 +00:00
|
|
|
* \param bedhint Info about the shape and type of the bed.
|
2019-06-28 16:27:15 +00:00
|
|
|
*
|
|
|
|
* \param progressind Progress indicator callback called when
|
|
|
|
* an object gets packed. The unsigned argument is the number of items
|
|
|
|
* remaining to pack.
|
2018-07-30 14:41:35 +00:00
|
|
|
*
|
2018-09-17 13:12:13 +00:00
|
|
|
* \param stopcondition A predicate returning true if abort is needed.
|
2018-07-30 14:41:35 +00:00
|
|
|
*/
|
2019-07-12 19:03:49 +00:00
|
|
|
void arrange(ArrangePolygons & items,
|
|
|
|
coord_t min_obj_distance,
|
|
|
|
const BedShapeHint & bedhint,
|
|
|
|
std::function<void(unsigned)> progressind = nullptr,
|
|
|
|
std::function<bool(void)> stopcondition = nullptr);
|
2018-08-03 12:49:26 +00:00
|
|
|
|
2019-06-28 16:27:15 +00:00
|
|
|
/// Same as the previous, only that it takes unmovable items as an
|
2019-07-15 15:30:44 +00:00
|
|
|
/// additional argument. Those will be considered as already arranged objects.
|
2019-07-12 19:03:49 +00:00
|
|
|
void arrange(ArrangePolygons & items,
|
|
|
|
const ArrangePolygons & excludes,
|
|
|
|
coord_t min_obj_distance,
|
|
|
|
const BedShapeHint & bedhint,
|
|
|
|
std::function<void(unsigned)> progressind = nullptr,
|
|
|
|
std::function<bool(void)> stopcondition = nullptr);
|
2018-07-30 14:41:35 +00:00
|
|
|
|
2019-01-22 16:50:33 +00:00
|
|
|
} // arr
|
|
|
|
} // Slic3r
|
2018-07-30 14:41:35 +00:00
|
|
|
#endif // MODELARRANGE_HPP
|