1 #ifndef slic3r_Surface_hpp_
2 #define slic3r_Surface_hpp_
3
4 #include "libslic3r.h"
5 #include "ExPolygon.hpp"
6
7 namespace Slic3r {
8
9 enum SurfaceType {
10 // Top horizontal surface, visible from the top.
11 stTop,
12 // Bottom horizontal surface, visible from the bottom, printed with a normal extrusion flow.
13 stBottom,
14 // Bottom horizontal surface, visible from the bottom, unsupported, printed with a bridging extrusion flow.
15 stBottomBridge,
16 // Normal sparse infill.
17 stInternal,
18 // Full infill, supporting the top surfaces and/or defining the verticall wall thickness.
19 stInternalSolid,
20 // 1st layer of dense infill over sparse infill, printed with a bridging extrusion flow.
21 stInternalBridge,
22 // stInternal turns into void surfaces if the sparse infill is used for supports only,
23 // or if sparse infill layers get combined into a single layer.
24 stInternalVoid,
25 // Inner/outer perimeters.
26 stPerimeter,
27 // Number of SurfaceType enums.
28 stCount,
29 };
30
31 class Surface
32 {
33 public:
34 SurfaceType surface_type;
35 ExPolygon expolygon;
36 double thickness; // in mm
37 unsigned short thickness_layers; // in layers
38 double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
39 unsigned short extra_perimeters;
40
Surface(const Slic3r::Surface & rhs)41 Surface(const Slic3r::Surface &rhs)
42 : surface_type(rhs.surface_type), expolygon(rhs.expolygon),
43 thickness(rhs.thickness), thickness_layers(rhs.thickness_layers),
44 bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters)
45 {};
46
Surface(SurfaceType _surface_type,const ExPolygon & _expolygon)47 Surface(SurfaceType _surface_type, const ExPolygon &_expolygon)
48 : surface_type(_surface_type), expolygon(_expolygon),
49 thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0)
50 {};
Surface(const Surface & other,const ExPolygon & _expolygon)51 Surface(const Surface &other, const ExPolygon &_expolygon)
52 : surface_type(other.surface_type), expolygon(_expolygon),
53 thickness(other.thickness), thickness_layers(other.thickness_layers),
54 bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters)
55 {};
Surface(Surface && rhs)56 Surface(Surface &&rhs)
57 : surface_type(rhs.surface_type), expolygon(std::move(rhs.expolygon)),
58 thickness(rhs.thickness), thickness_layers(rhs.thickness_layers),
59 bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters)
60 {};
Surface(SurfaceType _surface_type,const ExPolygon && _expolygon)61 Surface(SurfaceType _surface_type, const ExPolygon &&_expolygon)
62 : surface_type(_surface_type), expolygon(std::move(_expolygon)),
63 thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0)
64 {};
Surface(const Surface & other,const ExPolygon && _expolygon)65 Surface(const Surface &other, const ExPolygon &&_expolygon)
66 : surface_type(other.surface_type), expolygon(std::move(_expolygon)),
67 thickness(other.thickness), thickness_layers(other.thickness_layers),
68 bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters)
69 {};
70
operator =(const Surface & rhs)71 Surface& operator=(const Surface &rhs)
72 {
73 surface_type = rhs.surface_type;
74 expolygon = rhs.expolygon;
75 thickness = rhs.thickness;
76 thickness_layers = rhs.thickness_layers;
77 bridge_angle = rhs.bridge_angle;
78 extra_perimeters = rhs.extra_perimeters;
79 return *this;
80 }
81
operator =(Surface && rhs)82 Surface& operator=(Surface &&rhs)
83 {
84 surface_type = rhs.surface_type;
85 expolygon = std::move(rhs.expolygon);
86 thickness = rhs.thickness;
87 thickness_layers = rhs.thickness_layers;
88 bridge_angle = rhs.bridge_angle;
89 extra_perimeters = rhs.extra_perimeters;
90 return *this;
91 }
92
operator Polygons() const93 operator Polygons() const { return this->expolygon; }
area() const94 double area() const { return this->expolygon.area(); }
empty() const95 bool empty() const { return expolygon.empty(); }
clear()96 void clear() { expolygon.clear(); }
97
98 // The following methods do not test for stPerimeter.
is_top() const99 bool is_top() const { return this->surface_type == stTop; }
is_bottom() const100 bool is_bottom() const { return this->surface_type == stBottom || this->surface_type == stBottomBridge; }
is_bridge() const101 bool is_bridge() const { return this->surface_type == stBottomBridge || this->surface_type == stInternalBridge; }
is_external() const102 bool is_external() const { return this->is_top() || this->is_bottom(); }
is_internal() const103 bool is_internal() const { return ! this->is_external(); }
is_solid() const104 bool is_solid() const { return this->is_external() || this->surface_type == stInternalSolid || this->surface_type == stInternalBridge; }
105 };
106
107 typedef std::vector<Surface> Surfaces;
108 typedef std::vector<Surface*> SurfacesPtr;
109
to_polygons(const Surfaces & src)110 inline Polygons to_polygons(const Surfaces &src)
111 {
112 size_t num = 0;
113 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it)
114 num += it->expolygon.holes.size() + 1;
115 Polygons polygons;
116 polygons.reserve(num);
117 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it) {
118 polygons.emplace_back(it->expolygon.contour);
119 for (Polygons::const_iterator ith = it->expolygon.holes.begin(); ith != it->expolygon.holes.end(); ++ith)
120 polygons.emplace_back(*ith);
121 }
122 return polygons;
123 }
124
to_polygons(const SurfacesPtr & src)125 inline Polygons to_polygons(const SurfacesPtr &src)
126 {
127 size_t num = 0;
128 for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it)
129 num += (*it)->expolygon.holes.size() + 1;
130 Polygons polygons;
131 polygons.reserve(num);
132 for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it) {
133 polygons.emplace_back((*it)->expolygon.contour);
134 for (Polygons::const_iterator ith = (*it)->expolygon.holes.begin(); ith != (*it)->expolygon.holes.end(); ++ith)
135 polygons.emplace_back(*ith);
136 }
137 return polygons;
138 }
139
to_expolygons(const Surfaces & src)140 inline ExPolygons to_expolygons(const Surfaces &src)
141 {
142 ExPolygons expolygons;
143 expolygons.reserve(src.size());
144 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it)
145 expolygons.emplace_back(it->expolygon);
146 return expolygons;
147 }
148
to_expolygons(Surfaces && src)149 inline ExPolygons to_expolygons(Surfaces &&src)
150 {
151 ExPolygons expolygons;
152 expolygons.reserve(src.size());
153 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++it)
154 expolygons.emplace_back(ExPolygon(std::move(it->expolygon)));
155 src.clear();
156 return expolygons;
157 }
158
to_expolygons(const SurfacesPtr & src)159 inline ExPolygons to_expolygons(const SurfacesPtr &src)
160 {
161 ExPolygons expolygons;
162 expolygons.reserve(src.size());
163 for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++it)
164 expolygons.emplace_back((*it)->expolygon);
165 return expolygons;
166 }
167
168 // Count a nuber of polygons stored inside the vector of expolygons.
169 // Useful for allocating space for polygons when converting expolygons to polygons.
number_polygons(const Surfaces & surfaces)170 inline size_t number_polygons(const Surfaces &surfaces)
171 {
172 size_t n_polygons = 0;
173 for (Surfaces::const_iterator it = surfaces.begin(); it != surfaces.end(); ++ it)
174 n_polygons += it->expolygon.holes.size() + 1;
175 return n_polygons;
176 }
number_polygons(const SurfacesPtr & surfaces)177 inline size_t number_polygons(const SurfacesPtr &surfaces)
178 {
179 size_t n_polygons = 0;
180 for (SurfacesPtr::const_iterator it = surfaces.begin(); it != surfaces.end(); ++ it)
181 n_polygons += (*it)->expolygon.holes.size() + 1;
182 return n_polygons;
183 }
184
185 // Append a vector of Surfaces at the end of another vector of polygons.
polygons_append(Polygons & dst,const Surfaces & src)186 inline void polygons_append(Polygons &dst, const Surfaces &src)
187 {
188 dst.reserve(dst.size() + number_polygons(src));
189 for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++ it) {
190 dst.emplace_back(it->expolygon.contour);
191 dst.insert(dst.end(), it->expolygon.holes.begin(), it->expolygon.holes.end());
192 }
193 }
194
polygons_append(Polygons & dst,Surfaces && src)195 inline void polygons_append(Polygons &dst, Surfaces &&src)
196 {
197 dst.reserve(dst.size() + number_polygons(src));
198 for (Surfaces::iterator it = src.begin(); it != src.end(); ++ it) {
199 dst.emplace_back(std::move(it->expolygon.contour));
200 std::move(std::begin(it->expolygon.holes), std::end(it->expolygon.holes), std::back_inserter(dst));
201 it->expolygon.holes.clear();
202 }
203 }
204
205 // Append a vector of Surfaces at the end of another vector of polygons.
polygons_append(Polygons & dst,const SurfacesPtr & src)206 inline void polygons_append(Polygons &dst, const SurfacesPtr &src)
207 {
208 dst.reserve(dst.size() + number_polygons(src));
209 for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) {
210 dst.emplace_back((*it)->expolygon.contour);
211 dst.insert(dst.end(), (*it)->expolygon.holes.begin(), (*it)->expolygon.holes.end());
212 }
213 }
214
polygons_append(Polygons & dst,SurfacesPtr && src)215 inline void polygons_append(Polygons &dst, SurfacesPtr &&src)
216 {
217 dst.reserve(dst.size() + number_polygons(src));
218 for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) {
219 dst.emplace_back(std::move((*it)->expolygon.contour));
220 std::move(std::begin((*it)->expolygon.holes), std::end((*it)->expolygon.holes), std::back_inserter(dst));
221 (*it)->expolygon.holes.clear();
222 }
223 }
224
225 // Append a vector of Surfaces at the end of another vector of polygons.
surfaces_append(Surfaces & dst,const ExPolygons & src,SurfaceType surfaceType)226 inline void surfaces_append(Surfaces &dst, const ExPolygons &src, SurfaceType surfaceType)
227 {
228 dst.reserve(dst.size() + src.size());
229 for (const ExPolygon &expoly : src)
230 dst.emplace_back(Surface(surfaceType, expoly));
231 }
surfaces_append(Surfaces & dst,const ExPolygons & src,const Surface & surfaceTempl)232 inline void surfaces_append(Surfaces &dst, const ExPolygons &src, const Surface &surfaceTempl)
233 {
234 dst.reserve(dst.size() + number_polygons(src));
235 for (const ExPolygon &expoly : src)
236 dst.emplace_back(Surface(surfaceTempl, expoly));
237 }
surfaces_append(Surfaces & dst,const Surfaces & src)238 inline void surfaces_append(Surfaces &dst, const Surfaces &src)
239 {
240 dst.insert(dst.end(), src.begin(), src.end());
241 }
242
surfaces_append(Surfaces & dst,ExPolygons && src,SurfaceType surfaceType)243 inline void surfaces_append(Surfaces &dst, ExPolygons &&src, SurfaceType surfaceType)
244 {
245 dst.reserve(dst.size() + src.size());
246 for (ExPolygon &expoly : src)
247 dst.emplace_back(Surface(surfaceType, std::move(expoly)));
248 src.clear();
249 }
250
surfaces_append(Surfaces & dst,ExPolygons && src,const Surface & surfaceTempl)251 inline void surfaces_append(Surfaces &dst, ExPolygons &&src, const Surface &surfaceTempl)
252 {
253 dst.reserve(dst.size() + number_polygons(src));
254 for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it)
255 dst.emplace_back(Surface(surfaceTempl, std::move(*it)));
256 src.clear();
257 }
258
surfaces_append(Surfaces & dst,Surfaces && src)259 inline void surfaces_append(Surfaces &dst, Surfaces &&src)
260 {
261 if (dst.empty()) {
262 dst = std::move(src);
263 } else {
264 std::move(std::begin(src), std::end(src), std::back_inserter(dst));
265 src.clear();
266 }
267 }
268
269 extern BoundingBox get_extents(const Surface &surface);
270 extern BoundingBox get_extents(const Surfaces &surfaces);
271 extern BoundingBox get_extents(const SurfacesPtr &surfaces);
272
surfaces_could_merge(const Surface & s1,const Surface & s2)273 inline bool surfaces_could_merge(const Surface &s1, const Surface &s2)
274 {
275 return
276 s1.surface_type == s2.surface_type &&
277 s1.thickness == s2.thickness &&
278 s1.thickness_layers == s2.thickness_layers &&
279 s1.bridge_angle == s2.bridge_angle;
280 }
281
282 class SVG;
283
284 extern const char* surface_type_to_color_name(const SurfaceType surface_type);
285 extern void export_surface_type_legend_to_svg(SVG &svg, const Point &pos);
286 extern Point export_surface_type_legend_to_svg_box_size();
287 extern bool export_to_svg(const char *path, const Surfaces &surfaces, const float transparency = 1.f);
288
289 }
290
291 #endif
292