mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-30 20:21:12 -06:00 
			
		
		
		
	The last priming area is shortened and the excess wipe is moved
into the wipe tower if there is enough space inside the wipe tower.
This commit is contained in:
		
							parent
							
								
									6d4ec5c989
								
							
						
					
					
						commit
						b08d6f1969
					
				
					 8 changed files with 115 additions and 39 deletions
				
			
		|  | @ -125,15 +125,17 @@ template void BoundingBoxBase<Pointf>::merge(const Pointfs &points); | |||
| template <class PointClass> void | ||||
| BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb) | ||||
| { | ||||
|     if (this->defined) { | ||||
|         this->min.x = std::min(bb.min.x, this->min.x); | ||||
|         this->min.y = std::min(bb.min.y, this->min.y); | ||||
|         this->max.x = std::max(bb.max.x, this->max.x); | ||||
|         this->max.y = std::max(bb.max.y, this->max.y); | ||||
|     } else { | ||||
|         this->min = bb.min; | ||||
|         this->max = bb.max; | ||||
|         this->defined = true; | ||||
|     if (bb.defined) { | ||||
|         if (this->defined) { | ||||
|             this->min.x = std::min(bb.min.x, this->min.x); | ||||
|             this->min.y = std::min(bb.min.y, this->min.y); | ||||
|             this->max.x = std::max(bb.max.x, this->max.x); | ||||
|             this->max.y = std::max(bb.max.y, this->max.y); | ||||
|         } else { | ||||
|             this->min = bb.min; | ||||
|             this->max = bb.max; | ||||
|             this->defined = true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb); | ||||
|  | @ -160,11 +162,13 @@ template void BoundingBox3Base<Pointf3>::merge(const Pointf3s &points); | |||
| template <class PointClass> void | ||||
| BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb) | ||||
| { | ||||
|     if (this->defined) { | ||||
|         this->min.z = std::min(bb.min.z, this->min.z); | ||||
|         this->max.z = std::max(bb.max.z, this->max.z); | ||||
|     if (bb.defined) { | ||||
|         if (this->defined) { | ||||
|             this->min.z = std::min(bb.min.z, this->min.z); | ||||
|             this->max.z = std::max(bb.max.z, this->max.z); | ||||
|         } | ||||
|         BoundingBoxBase<PointClass>::merge(bb); | ||||
|     } | ||||
|     BoundingBoxBase<PointClass>::merge(bb); | ||||
| } | ||||
| template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb); | ||||
| 
 | ||||
|  |  | |||
|  | @ -700,15 +700,17 @@ bool GCode::_do_export(Print &print, FILE *file) | |||
|                 BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print)); | ||||
|                 bbox_prime.offset(0.5f); | ||||
|                 // Beep for 500ms, tone 800Hz. Yet better, play some Morse.
 | ||||
|                 write(file, this->retract()); | ||||
|                 fprintf(file, "M300 S800 P500\n"); | ||||
|                 if (bbox_prime.overlap(bbox_print)) { | ||||
|                     // Wait for the user to remove the priming extrusions, otherwise they would
 | ||||
|                     // get covered by the print.
 | ||||
|                     fprintf(file, "M1 Remove priming towers and click button.\n"); | ||||
|                     fprintf(file, "M1 Remove priming towers and click button.\nM117 Printing\n"); | ||||
|                 } else { | ||||
|                     // Just wait for a bit to let the user check, that the priming succeeded.
 | ||||
|                     fprintf(file, "M0 S10\n"); | ||||
|                     fprintf(file, "M117 Verify extruder priming\nM0 S10\nM117 Printing\n"); | ||||
|                 } | ||||
|                 write(file, this->unretract()); | ||||
|             } else | ||||
|                 write(file, WipeTowerIntegration::prime_single_color_print(print, initial_extruder_id, *this)); | ||||
|         } | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ BoundingBoxf get_print_extrusions_extents(const Print &print) | |||
|     return bbox; | ||||
| } | ||||
| 
 | ||||
| BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coord_t max_print_z) | ||||
| BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z) | ||||
| { | ||||
|     BoundingBoxf bbox; | ||||
|     for (const Layer *layer : print_object.layers) { | ||||
|  | @ -129,7 +129,7 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object | |||
| 
 | ||||
| // Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z.
 | ||||
| // The projection does not contain the priming regions.
 | ||||
| BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coord_t max_print_z) | ||||
| BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z) | ||||
| { | ||||
|     BoundingBoxf bbox; | ||||
|     for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) { | ||||
|  |  | |||
|  | @ -16,11 +16,11 @@ class BoundingBoxf; | |||
| BoundingBoxf get_print_extrusions_extents(const Print &print); | ||||
| 
 | ||||
| // Returns a bounding box of a projection of the object extrusions at z <= max_print_z.
 | ||||
| BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coord_t max_print_z); | ||||
| BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z); | ||||
| 
 | ||||
| // Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z.
 | ||||
| // The projection does not contain the priming regions.
 | ||||
| BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coord_t max_print_z); | ||||
| BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z); | ||||
| 
 | ||||
| // Returns a bounding box of the wipe tower priming extrusions.
 | ||||
| BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print); | ||||
|  |  | |||
|  | @ -105,7 +105,16 @@ public: | |||
| 	}; | ||||
| 
 | ||||
| 	// Returns gcode to prime the nozzles at the front edge of the print bed.
 | ||||
| 	virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; | ||||
| 	virtual ToolChangeResult prime( | ||||
| 		// print_z of the first layer.
 | ||||
| 		float 						first_layer_height,  | ||||
| 		// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
 | ||||
| 		std::vector<unsigned int> 	tools, | ||||
| 		// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
 | ||||
| 		// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
 | ||||
| 		bool 						last_wipe_inside_wipe_tower,  | ||||
| 		// May be used by a stand alone post processor.
 | ||||
| 		Purpose 					purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; | ||||
| 
 | ||||
| 	// Returns gcode for toolchange and the end position.
 | ||||
| 	// if new_tool == -1, just unload the current filament over the wipe tower.
 | ||||
|  |  | |||
|  | @ -364,7 +364,16 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam | |||
| } | ||||
| 
 | ||||
| // Returns gcode to prime the nozzles at the front edge of the print bed.
 | ||||
| WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose) | ||||
| WipeTower::ToolChangeResult WipeTowerPrusaMM::prime( | ||||
| 	// print_z of the first layer.
 | ||||
| 	float 						first_layer_height,  | ||||
| 	// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
 | ||||
| 	std::vector<unsigned int> 	tools, | ||||
| 	// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
 | ||||
| 	// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
 | ||||
| 	bool 						last_wipe_inside_wipe_tower,  | ||||
| 	// May be used by a stand alone post processor.
 | ||||
| 	Purpose 					purpose) | ||||
| { | ||||
| 	this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); | ||||
| 
 | ||||
|  | @ -411,6 +420,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, st | |||
| 		  .set_extruder_trimpot(750); | ||||
| 
 | ||||
| 	if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { | ||||
| 		float y_end = 0.f; | ||||
| 		for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { | ||||
| 			unsigned int tool = tools[idx_tool]; | ||||
| 			// Select the tool, set a speed override for soluble and flex materials.
 | ||||
|  | @ -419,10 +429,20 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, st | |||
| 			toolchange_Load(writer, cleaning_box); | ||||
| 			if (idx_tool + 1 == tools.size()) { | ||||
| 				// Last tool should not be unloaded, but it should be wiped enough to become of a pure color.
 | ||||
| 				toolchange_Wipe(writer, cleaning_box); | ||||
| 				if (last_wipe_inside_wipe_tower) { | ||||
| 					// Shrink the last wipe area to the area of the other purge areas,
 | ||||
| 					// remember the last initial wipe width to be purged into the 1st layer of the wipe tower.
 | ||||
| 					this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * 0.85f * m_perimeter_width - cleaning_box.ld.y)); | ||||
| 					cleaning_box.lu.y -= this->m_initial_extra_wipe; | ||||
| 					cleaning_box.ru.y -= this->m_initial_extra_wipe; | ||||
| 				} | ||||
| 				toolchange_Wipe(writer, cleaning_box, false); | ||||
| 			} else { | ||||
| 				// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
 | ||||
| 				writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200); | ||||
| 				toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tool]); | ||||
| 				// Save the y end of the non-last priming area.
 | ||||
| 				y_end = writer.y(); | ||||
| 			    cleaning_box.translate(m_wipe_tower_width, 0.f); | ||||
| 				writer.travel(cleaning_box.ld, 7200); | ||||
| 			} | ||||
|  | @ -546,7 +566,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo | |||
| 			toolchange_Change(writer, tool, m_material[tool]); | ||||
| 			toolchange_Load(writer, cleaning_box); | ||||
| 			// Wipe the newly loaded filament until the end of the assigned wipe area.
 | ||||
| 			toolchange_Wipe(writer, cleaning_box); | ||||
| 			toolchange_Wipe(writer, cleaning_box, false); | ||||
| 			// Draw a perimeter around cleaning_box and wipe.
 | ||||
| 			box_coordinates box = cleaning_box; | ||||
| 			if (m_current_shape == SHAPE_REVERSED) { | ||||
|  | @ -647,6 +667,21 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (m_initial_extra_wipe > m_perimeter_width * 1.9f) { | ||||
| 			box_coordinates cleaning_box( | ||||
| 				m_wipe_tower_pos + xy(0.f, 0.5f * m_perimeter_width), | ||||
| 				m_wipe_tower_width,  | ||||
| 				m_initial_extra_wipe - m_perimeter_width); | ||||
| 		    writer.travel(cleaning_box.ld + xy(m_perimeter_width, 0.5f * m_perimeter_width), 6000); | ||||
| 			// Wipe the newly loaded filament until the end of the assigned wipe area.
 | ||||
| 			toolchange_Wipe(writer, cleaning_box, true); | ||||
| 			// Draw a perimeter around cleaning_box.
 | ||||
| 			writer.travel(cleaning_box.lu, 7000) | ||||
| 				  .extrude(cleaning_box.ld, 3200).extrude(cleaning_box.rd) | ||||
| 				  .extrude(cleaning_box.ru).extrude(cleaning_box.lu); | ||||
| 		    m_current_wipe_start_y = m_initial_extra_wipe; | ||||
| 		} | ||||
| 
 | ||||
| 		// Move to the front left corner.
 | ||||
| 		writer.travel(wipeTower_box.ld, 7000); | ||||
| 
 | ||||
|  | @ -786,6 +821,9 @@ void WipeTowerPrusaMM::toolchange_Load( | |||
| { | ||||
| 	float xl = cleaning_box.ld.x + m_perimeter_width; | ||||
| 	float xr = cleaning_box.rd.x - m_perimeter_width; | ||||
| 	//FIXME flipping left / right side, so that the following toolchange_Wipe will start
 | ||||
| 	// where toolchange_Load ends. 
 | ||||
| 	std::swap(xl, xr); | ||||
| 
 | ||||
| 	writer.append("; CP TOOLCHANGE LOAD\n") | ||||
| 	// Load the filament while moving left / right,
 | ||||
|  | @ -819,7 +857,8 @@ void WipeTowerPrusaMM::toolchange_Load( | |||
| // Wipe the newly loaded filament until the end of the assigned wipe area.
 | ||||
| void WipeTowerPrusaMM::toolchange_Wipe( | ||||
| 	PrusaMultiMaterial::Writer &writer, | ||||
| 	const box_coordinates  &cleaning_box) | ||||
| 	const box_coordinates  &cleaning_box, | ||||
| 	bool skip_initial_y_move) | ||||
| { | ||||
| 	// Increase flow on first layer, slow down print.
 | ||||
| 	writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f)) | ||||
|  | @ -833,23 +872,27 @@ void WipeTowerPrusaMM::toolchange_Wipe( | |||
| 	float wipe_speed_max = 4800.f; | ||||
| 	// Y increment per wipe line.
 | ||||
| 	float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.8f; | ||||
| 	for (bool p = true; ; p = ! p) { | ||||
| 	for (bool p = true;  | ||||
| 		// Next wipe line fits the cleaning box.
 | ||||
| 		((m_current_shape == SHAPE_NORMAL) ? | ||||
| 			(writer.y() <= cleaning_box.lu.y - m_perimeter_width) : | ||||
| 			(writer.y() >= cleaning_box.ld.y + m_perimeter_width)); | ||||
| 		p = ! p) | ||||
| 	{ | ||||
| 		wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); | ||||
| 		if (p) { | ||||
| 			writer.extrude(xl - m_perimeter_width / 2, writer.y() + dy, wipe_speed * wipe_coeff); | ||||
| 			writer.extrude(xr + m_perimeter_width,     writer.y()); | ||||
| 		} else { | ||||
| 			writer.extrude(xl - m_perimeter_width,     writer.y() + dy, wipe_speed * wipe_coeff); | ||||
| 			writer.extrude(xr + m_perimeter_width * 2, writer.y()); | ||||
| 		} | ||||
| 		wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); | ||||
| 		writer.extrude(xr + m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff); | ||||
| 		writer.extrude(xl - m_perimeter_width, writer.y()); | ||||
| 		if (skip_initial_y_move) | ||||
| 			skip_initial_y_move = false; | ||||
| 		else | ||||
| 			writer.extrude(xl - (p ? m_perimeter_width / 2 : m_perimeter_width), writer.y() + dy, wipe_speed * wipe_coeff); | ||||
| 		writer.extrude(xr + (p ? m_perimeter_width : m_perimeter_width * 2), writer.y(), wipe_speed * wipe_coeff); | ||||
| 		// Next wipe line fits the cleaning box.
 | ||||
| 		if ((m_current_shape == SHAPE_NORMAL) ? | ||||
| 			(writer.y() > cleaning_box.lu.y - m_perimeter_width) : | ||||
| 			(writer.y() < cleaning_box.ld.y + m_perimeter_width)) | ||||
| 			// Next wipe line does not fit the cleaning box.
 | ||||
| 			break; | ||||
| 		wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); | ||||
| 		writer.extrude(xr + m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff); | ||||
| 		writer.extrude(xl - m_perimeter_width, writer.y()); | ||||
| 	} | ||||
| 	// Reset the extrusion flow.
 | ||||
| 	writer.set_extrusion_flow(m_extrusion_flow); | ||||
|  |  | |||
|  | @ -108,7 +108,16 @@ public: | |||
| 	virtual bool 	  		 finished() const { return m_max_color_changes == 0; } | ||||
| 
 | ||||
| 	// Returns gcode to prime the nozzles at the front edge of the print bed.
 | ||||
| 	virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE); | ||||
| 	virtual ToolChangeResult prime( | ||||
| 		// print_z of the first layer.
 | ||||
| 		float 						first_layer_height,  | ||||
| 		// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
 | ||||
| 		std::vector<unsigned int> 	tools, | ||||
| 		// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
 | ||||
| 		// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
 | ||||
| 		bool 						last_wipe_inside_wipe_tower,  | ||||
| 		// May be used by a stand alone post processor.
 | ||||
| 		Purpose 					purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE); | ||||
| 
 | ||||
| 	// Returns gcode for a toolchange and a final print head position.
 | ||||
| 	// On the first layer, extrude a brim around the future wipe tower first.
 | ||||
|  | @ -176,6 +185,9 @@ private: | |||
| 	unsigned int 	m_current_tool  = 0; | ||||
| 	// Current y position at the wipe tower.
 | ||||
| 	float 		 	m_current_wipe_start_y = 0.f; | ||||
| 	// How much to wipe the 1st extruder over the wipe tower at the 1st layer
 | ||||
| 	// after the wipe tower brim has been extruded?
 | ||||
| 	float  			m_initial_extra_wipe = 0.f; | ||||
| 
 | ||||
| 	struct box_coordinates | ||||
| 	{ | ||||
|  | @ -230,7 +242,8 @@ private: | |||
| 	 | ||||
| 	void toolchange_Wipe( | ||||
| 		PrusaMultiMaterial::Writer &writer, | ||||
| 		const box_coordinates  &cleaning_box); | ||||
| 		const box_coordinates  &cleaning_box, | ||||
| 		bool skip_initial_y_move); | ||||
| 	 | ||||
| 	void toolchange_Perimeter(); | ||||
| }; | ||||
|  |  | |||
|  | @ -992,8 +992,13 @@ void Print::_make_wipe_tower() | |||
|             this->config.temperature.get_at(i), | ||||
|             this->config.first_layer_temperature.get_at(i)); | ||||
| 
 | ||||
|     // When printing the first layer's wipe tower, the first extruder is expected to be active and primed.
 | ||||
|     // Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer.
 | ||||
|     // The following variable is true if the last priming section cannot be squeezed inside the wipe tower.
 | ||||
|     bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions; | ||||
| 
 | ||||
|     m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>( | ||||
|         wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), WipeTower::PURPOSE_EXTRUDE)); | ||||
|         wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE)); | ||||
| 
 | ||||
|     // Generate the wipe tower layers.
 | ||||
|     m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 bubnikv
						bubnikv