1 #ifndef slic3r_SupportMaterial_hpp_
2 #define slic3r_SupportMaterial_hpp_
3 
4 #include "Flow.hpp"
5 #include "PrintConfig.hpp"
6 #include "Slicing.hpp"
7 
8 namespace Slic3r {
9 
10 class PrintObject;
11 class PrintConfig;
12 class PrintObjectConfig;
13 
14 // how much we extend support around the actual contact area
15 //FIXME this should be dependent on the nozzle diameter!
16 #define SUPPORT_MATERIAL_MARGIN 1.5
17 
18 // This class manages raft and supports for a single PrintObject.
19 // Instantiated by Slic3r::Print::Object->_support_material()
20 // This class is instantiated before the slicing starts as Object.pm will query
21 // the parameters of the raft to determine the 1st layer height and thickness.
22 class PrintObjectSupportMaterial
23 {
24 public:
25 	// Support layer type to be used by MyLayer. This type carries a much more detailed information
26 	// about the support layer type than the final support layers stored in a PrintObject.
27 	enum SupporLayerType {
28 		sltUnknown = 0,
29 		// Ratft base layer, to be printed with the support material.
30 		sltRaftBase,
31 		// Raft interface layer, to be printed with the support interface material.
32 		sltRaftInterface,
33 		// Bottom contact layer placed over a top surface of an object. To be printed with a support interface material.
34 		sltBottomContact,
35 		// Dense interface layer, to be printed with the support interface material.
36 		// This layer is separated from an object by an sltBottomContact layer.
37 		sltBottomInterface,
38 		// Sparse base support layer, to be printed with a support material.
39 		sltBase,
40 		// Dense interface layer, to be printed with the support interface material.
41 		// This layer is separated from an object with sltTopContact layer.
42 		sltTopInterface,
43 		// Top contact layer directly supporting an overhang. To be printed with a support interface material.
44 		sltTopContact,
45 		// Some undecided type yet. It will turn into sltBase first, then it may turn into sltBottomInterface or sltTopInterface.
46 		sltIntermediate,
47 	};
48 
49 	// A support layer type used internally by the SupportMaterial class. This class carries a much more detailed
50 	// information about the support layer than the layers stored in the PrintObject, mainly
51 	// the MyLayer is aware of the bridging flow and the interface gaps between the object and the support.
52 	class MyLayer
53 	{
54 	public:
MyLayer()55 		MyLayer() :
56 			layer_type(sltUnknown),
57 			print_z(0.),
58 			bottom_z(0.),
59 			height(0.),
60 			idx_object_layer_above(size_t(-1)),
61 			idx_object_layer_below(size_t(-1)),
62 			bridging(false),
63 			contact_polygons(nullptr),
64 			overhang_polygons(nullptr)
65 			{}
66 
~MyLayer()67 		~MyLayer()
68 		{
69 			delete contact_polygons;
70 			contact_polygons = nullptr;
71 			delete overhang_polygons;
72 			overhang_polygons = nullptr;
73 		}
74 
reset()75 		void reset() {
76 			layer_type  			= sltUnknown;
77 			print_z 				= 0.;
78 			bottom_z 				= 0.;
79 			height 					= 0.;
80 			idx_object_layer_above  = size_t(-1);
81 			idx_object_layer_below  = size_t(-1);
82 			bridging 				= false;
83 			polygons.clear();
84 			delete contact_polygons;
85 			contact_polygons 		= nullptr;
86 			delete overhang_polygons;
87 			overhang_polygons 		= nullptr;
88 		}
89 
operator ==(const MyLayer & layer2) const90 		bool operator==(const MyLayer &layer2) const {
91 			return print_z == layer2.print_z && height == layer2.height && bridging == layer2.bridging;
92 		}
93 
94 		// Order the layers by lexicographically by an increasing print_z and a decreasing layer height.
operator <(const MyLayer & layer2) const95 		bool operator<(const MyLayer &layer2) const {
96 			if (print_z < layer2.print_z) {
97 				return true;
98 			} else if (print_z == layer2.print_z) {
99 			 	if (height > layer2.height)
100 			 		return true;
101 			 	else if (height == layer2.height) {
102 			 		// Bridging layers first.
103 			 	 	return bridging && ! layer2.bridging;
104 			 	} else
105 			 		return false;
106 			} else
107 				return false;
108 		}
109 
110 		// For the bridging flow, bottom_print_z will be above bottom_z to account for the vertical separation.
111 		// For the non-bridging flow, bottom_print_z will be equal to bottom_z.
bottom_print_z() const112 		coordf_t bottom_print_z() const { return print_z - height; }
113 
114 		// To sort the extremes of top / bottom interface layers.
extreme_z() const115 		coordf_t extreme_z() const { return (this->layer_type == sltTopContact) ? this->bottom_z : this->print_z; }
116 
117 		SupporLayerType layer_type;
118 		// Z used for printing, in unscaled coordinates.
119 		coordf_t print_z;
120 		// Bottom Z of this layer. For soluble layers, bottom_z + height = print_z,
121 		// otherwise bottom_z + gap + height = print_z.
122 		coordf_t bottom_z;
123 		// Layer height in unscaled coordinates.
124     	coordf_t height;
125     	// Index of a PrintObject layer_id supported by this layer. This will be set for top contact layers.
126     	// If this is not a contact layer, it will be set to size_t(-1).
127     	size_t 	 idx_object_layer_above;
128     	// Index of a PrintObject layer_id, which supports this layer. This will be set for bottom contact layers.
129     	// If this is not a contact layer, it will be set to size_t(-1).
130     	size_t 	 idx_object_layer_below;
131     	// Use a bridging flow when printing this support layer.
132     	bool 	 bridging;
133 
134     	// Polygons to be filled by the support pattern.
135     	Polygons polygons;
136     	// Currently for the contact layers only.
137     	// MyLayer owns the contact_polygons and overhang_polygons, they are freed by the destructor.
138     	Polygons *contact_polygons;
139     	Polygons *overhang_polygons;
140 	};
141 
142 	// Layers are allocated and owned by a deque. Once a layer is allocated, it is maintained
143 	// up to the end of a generate() method. The layer storage may be replaced by an allocator class in the future,
144 	// which would allocate layers by multiple chunks.
145 	typedef std::deque<MyLayer> 				MyLayerStorage;
146 	typedef std::vector<MyLayer*> 				MyLayersPtr;
147 
148 public:
149 	PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params);
150 
151 	// Is raft enabled?
has_raft() const152 	bool 		has_raft() 					const { return m_slicing_params.has_raft(); }
153 	// Has any support?
has_support() const154 	bool 		has_support()				const { return m_object_config->support_material.value; }
build_plate_only() const155 	bool 		build_plate_only() 			const { return this->has_support() && m_object_config->support_material_buildplate_only.value; }
156 
synchronize_layers() const157 	bool 		synchronize_layers()		const { return m_slicing_params.soluble_interface && m_object_config->support_material_synchronize_layers.value; }
has_contact_loops() const158 	bool 		has_contact_loops() 		const { return m_object_config->support_material_interface_contact_loops.value; }
159 
160 	// Generate support material for the object.
161 	// New support layers will be added to the object,
162 	// with extrusion paths and islands filled in for each support layer.
163 	void 		generate(PrintObject &object);
164 
165 private:
166 	// Generate top contact layers supporting overhangs.
167 	// For a soluble interface material synchronize the layer heights with the object, otherwise leave the layer height undefined.
168 	// If supports over bed surface only are requested, don't generate contact layers over an object.
169 	MyLayersPtr top_contact_layers(const PrintObject &object, MyLayerStorage &layer_storage) const;
170 
171 	// Generate bottom contact layers supporting the top contact layers.
172 	// For a soluble interface material synchronize the layer heights with the object,
173 	// otherwise set the layer height to a bridging flow of a support interface nozzle.
174 	MyLayersPtr bottom_contact_layers_and_layer_support_areas(
175 		const PrintObject &object, const MyLayersPtr &top_contacts, MyLayerStorage &layer_storage,
176 		std::vector<Polygons> &layer_support_areas) const;
177 
178 	// Trim the top_contacts layers with the bottom_contacts layers if they overlap, so there would not be enough vertical space for both of them.
179 	void trim_top_contacts_by_bottom_contacts(const PrintObject &object, const MyLayersPtr &bottom_contacts, MyLayersPtr &top_contacts) const;
180 
181 	// Generate raft layers and the intermediate support layers between the bottom contact and top contact surfaces.
182 	MyLayersPtr raft_and_intermediate_support_layers(
183 	    const PrintObject   &object,
184 	    const MyLayersPtr   &bottom_contacts,
185 	    const MyLayersPtr   &top_contacts,
186 	    MyLayerStorage	 	&layer_storage) const;
187 
188 	// Fill in the base layers with polygons.
189 	void generate_base_layers(
190 	    const PrintObject   &object,
191 	    const MyLayersPtr   &bottom_contacts,
192 	    const MyLayersPtr   &top_contacts,
193 	    MyLayersPtr         &intermediate_layers,
194 	    const std::vector<Polygons> &layer_support_areas) const;
195 
196 	// Generate raft layers, also expand the 1st support layer
197 	// in case there is no raft layer to improve support adhesion.
198     MyLayersPtr generate_raft_base(
199 	    const MyLayersPtr   &top_contacts,
200 	    const MyLayersPtr   &interface_layers,
201 	    const MyLayersPtr   &base_layers,
202 	    MyLayerStorage      &layer_storage) const;
203 
204     // Turn some of the base layers into interface layers.
205 	MyLayersPtr generate_interface_layers(
206 	    const MyLayersPtr   &bottom_contacts,
207 	    const MyLayersPtr   &top_contacts,
208 	    MyLayersPtr         &intermediate_layers,
209 	    MyLayerStorage      &layer_storage) const;
210 
211 	// Trim support layers by an object to leave a defined gap between
212 	// the support volume and the object.
213 	void trim_support_layers_by_object(
214 	    const PrintObject   &object,
215 	    MyLayersPtr         &support_layers,
216 	    const coordf_t       gap_extra_above,
217 	    const coordf_t       gap_extra_below,
218 	    const coordf_t       gap_xy) const;
219 
220 /*
221 	void generate_pillars_shape();
222 	void clip_with_shape();
223 */
224 
225 	// Produce the actual G-code.
226 	void generate_toolpaths(
227         const PrintObject	&object,
228         const MyLayersPtr 	&raft_layers,
229         const MyLayersPtr   &bottom_contacts,
230         const MyLayersPtr   &top_contacts,
231         const MyLayersPtr   &intermediate_layers,
232         const MyLayersPtr   &interface_layers) const;
233 
234 	// Following objects are not owned by SupportMaterial class.
235 	const PrintObject 		*m_object;
236 	const PrintConfig 		*m_print_config;
237 	const PrintObjectConfig *m_object_config;
238 	// Pre-calculated parameters shared between the object slicer and the support generator,
239 	// carrying information on a raft, 1st layer height, 1st object layer height, gap between the raft and object etc.
240 	SlicingParameters	     m_slicing_params;
241 
242 	Flow 			 	 m_first_layer_flow;
243 	Flow 			 	 m_support_material_flow;
244 	Flow 			 	 m_support_material_interface_flow;
245 	// Is merging of regions allowed? Could the interface & base support regions be printed with the same extruder?
246 	bool 				 m_can_merge_support_regions;
247 
248     coordf_t 			 m_support_layer_height_min;
249 	coordf_t		 	 m_support_layer_height_max;
250 
251 	coordf_t			 m_gap_xy;
252 };
253 
254 } // namespace Slic3r
255 
256 #endif /* slic3r_SupportMaterial_hpp_ */
257