#ifndef ARRANGE_HPP #define ARRANGE_HPP #include "ExPolygon.hpp" namespace Slic3r { class BoundingBox; namespace arrangement { /// A geometry abstraction for a circular print bed. Similarly to BoundingBox. class CircleBed { Point center_; double radius_; public: inline CircleBed(): center_(0, 0), radius_(std::nan("")) {} explicit inline CircleBed(const Point& c, double r): center_(c), radius_(r) {} inline double radius() const { return radius_; } inline const Point& center() const { return center_; } }; /// Representing an unbounded bed. struct InfiniteBed { Point center; explicit InfiniteBed(const Point &p = {0, 0}): center{p} {} }; /// A logical bed representing an object not being arranged. Either the arrange /// has not yet successfully 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. struct ArrangePolygon { ExPolygon poly; /// The 2D silhouette to be arranged Vec2crd translation{0, 0}; /// The translation of the poly double rotation{0.0}; /// The rotation of the poly in radians coord_t inflation = 0; /// Arrange with inflated polygon int bed_idx{UNARRANGED}; /// To which logical bed does poly belong... int priority{0}; // If empty, any rotation is allowed (currently unsupported) // If only a zero is there, no rotation is allowed std::vector allowed_rotations = {0.}; /// Optional setter function which can store arbitrary data in its closure std::function setter = nullptr; /// Helper function to call the setter with the arrange data arguments void apply() const { if (setter) setter(*this); } /// Test if arrange() was called previously and gave a successful result. bool is_arranged() const { return bed_idx != UNARRANGED; } inline ExPolygon transformed_poly() const { ExPolygon ret = poly; ret.rotate(rotation); ret.translate(translation.x(), translation.y()); return ret; } }; using ArrangePolygons = std::vector; struct ArrangeParams { /// The minimum distance which is allowed for any /// pair of items on the print bed in any direction. coord_t min_obj_distance = 0; /// The accuracy of optimization. /// Goes from 0.0 to 1.0 and scales performance as well float accuracy = 1.f; /// Allow parallel execution. bool parallel = true; bool allow_rotations = false; /// Progress indicator callback called when an object gets packed. /// The unsigned argument is the number of items remaining to pack. std::function progressind; std::function on_packed; /// A predicate returning true if abort is needed. std::function stopcondition; ArrangeParams() = default; explicit ArrangeParams(coord_t md) : min_obj_distance(md) {} }; /** * \brief Arranges the input polygons. * * 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. * * \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. */ template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const TBed &bed, const ArrangeParams ¶ms = {}); // A dispatch function that determines the bed shape from a set of points. template<> void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const Points &bed, const ArrangeParams ¶ms); extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const BoundingBox &bed, const ArrangeParams ¶ms); extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const CircleBed &bed, const ArrangeParams ¶ms); extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const Polygon &bed, const ArrangeParams ¶ms); extern template void arrange(ArrangePolygons &items, const ArrangePolygons &excludes, const InfiniteBed &bed, const ArrangeParams ¶ms); inline void arrange(ArrangePolygons &items, const Points &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); } inline void arrange(ArrangePolygons &items, const BoundingBox &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); } inline void arrange(ArrangePolygons &items, const CircleBed &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); } inline void arrange(ArrangePolygons &items, const Polygon &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); } inline void arrange(ArrangePolygons &items, const InfiniteBed &bed, const ArrangeParams ¶ms = {}) { arrange(items, {}, bed, params); } }} // namespace Slic3r::arrangement #endif // MODELARRANGE_HPP