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