Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Arrange.hpp « libslic3r « src - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c705b612bf90c30805edaf1d373118135181cdfb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#ifndef MODELARRANGE_HPP
#define MODELARRANGE_HPP

#include "ExPolygon.hpp"
#include "BoundingBox.hpp"

namespace Slic3r {

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("")) {}
    inline CircleBed(const Point& c, double r): center_(c), radius_(r) {}

    inline double radius() const { return radius_; }
    inline const Point& center() const { return center_; }
    inline operator bool() { return !std::isnan(radius_); }
};

/// Representing an unbounded bed.
struct InfiniteBed { Point center; };

/// Types of print bed shapes.
enum BedShapes {
    bsBox,
    bsCircle,
    bsIrregular,
    bsInfinite,
    bsUnknown
};

/// 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?
        CircleBed   circ;
        BoundingBox box;
        Polyline    polygon;
        InfiniteBed infbed{};
        ~BedShape_u() {}
        BedShape_u() {};
    } m_bed;
    
public:

    BedShapeHint(){};
    
    /// 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;
    }
    
    explicit BedShapeHint(const CircleBed &c)
    {
        m_type = bsCircle; m_bed.circ = c;
    }
    
    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;
        }
        
        return *this;
    }

    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; }

    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;
    }
};

/// 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.
struct ArrangePolygon {
    const 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
    int       bed_idx{UNARRANGED};  /// To which logical bed does poly belong...
    
    ArrangePolygon(ExPolygon p, const Vec2crd &tr = {}, double rot = 0.0)
        : poly{std::move(p)}, translation{tr}, rotation{rot}
    {}
};

using ArrangePolygons = std::vector<ArrangePolygon>;

/**
 * \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.
 *
 * \param min_obj_distance The minimum distance which is allowed for any
 * pair of items on the print bed in any direction.
 *
 * \param bedhint Info about the shape and type of the bed.
 *
 * \param progressind Progress indicator callback called when
 * an object gets packed. The unsigned argument is the number of items
 * remaining to pack.
 *
 * \param stopcondition A predicate returning true if abort is needed.
 */
void arrange(ArrangePolygons &             items,
             coord_t                       min_obj_distance,
             const BedShapeHint &          bedhint,
             std::function<void(unsigned)> progressind   = nullptr,
             std::function<bool(void)>     stopcondition = nullptr);

/// Same as the previous, only that it takes unmovable items as an
/// additional argument. Those will be considered as already arranged objects.
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);

}   // arr
}   // Slic3r
#endif // MODELARRANGE_HPP