mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	WIP: first_layer_print_min/max, first_layer_print_convex_hull
placeholders for the G-code export.
This commit is contained in:
		
							parent
							
								
									d95c151823
								
							
						
					
					
						commit
						6529543518
					
				
					 4 changed files with 107 additions and 36 deletions
				
			
		|  | @ -1298,7 +1298,21 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu | ||||||
|     m_placeholder_parser.set("has_wipe_tower", has_wipe_tower); |     m_placeholder_parser.set("has_wipe_tower", has_wipe_tower); | ||||||
|     m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming); |     m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming); | ||||||
|     m_placeholder_parser.set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
 |     m_placeholder_parser.set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
 | ||||||
| 
 |     { | ||||||
|  |         // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
 | ||||||
|  |         // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
 | ||||||
|  |         // It does NOT encompass user extrusions generated by custom G-code,
 | ||||||
|  |         // therefore it does NOT encompass the initial purge line.
 | ||||||
|  |         // It does NOT encompass MMU/MMU2 starting (wipe) areas.
 | ||||||
|  |         auto pts = std::make_unique<ConfigOptionPoints>(); | ||||||
|  |         pts->values.reserve(print.first_layer_convex_hull().size()); | ||||||
|  |         for (const Point &pt : print.first_layer_convex_hull().points) | ||||||
|  |             pts->values.emplace_back(unscale(pt)); | ||||||
|  |         BoundingBoxf bbox(pts->values); | ||||||
|  |         m_placeholder_parser.set("first_layer_print_convex_hull", pts.release()); | ||||||
|  |         m_placeholder_parser.set("first_layer_print_min", new ConfigOptionFloats({ bbox.min.x(), bbox.min.y() })); | ||||||
|  |         m_placeholder_parser.set("first_layer_print_max", new ConfigOptionFloats({ bbox.max.x(), bbox.max.y() })); | ||||||
|  |     } | ||||||
|     std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config().start_gcode.value, initial_extruder_id); |     std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config().start_gcode.value, initial_extruder_id); | ||||||
|     // Set bed temperature if the start G-code does not contain any bed temp control G-codes.
 |     // Set bed temperature if the start G-code does not contain any bed temp control G-codes.
 | ||||||
|     this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true); |     this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true); | ||||||
|  |  | ||||||
|  | @ -166,6 +166,7 @@ class SupportLayer : public Layer | ||||||
| { | { | ||||||
| public: | public: | ||||||
|     // Polygons covered by the supports: base, interface and contact areas.
 |     // Polygons covered by the supports: base, interface and contact areas.
 | ||||||
|  |     // Used to suppress retraction if moving for a support extrusion over these support_islands.
 | ||||||
|     ExPolygonCollection         support_islands; |     ExPolygonCollection         support_islands; | ||||||
|     // Extrusion paths for the support base and for the support interface and contacts.
 |     // Extrusion paths for the support base and for the support interface and contacts.
 | ||||||
|     ExtrusionEntityCollection   support_fills; |     ExtrusionEntityCollection   support_fills; | ||||||
|  |  | ||||||
|  | @ -244,7 +244,6 @@ bool Print::invalidate_step(PrintStep step) | ||||||
| { | { | ||||||
| 	bool invalidated = Inherited::invalidate_step(step); | 	bool invalidated = Inherited::invalidate_step(step); | ||||||
|     // Propagate to dependent steps.
 |     // Propagate to dependent steps.
 | ||||||
|     //FIXME Why should skirt invalidate brim? Shouldn't it be vice versa?
 |  | ||||||
|     if (step == psSkirt) |     if (step == psSkirt) | ||||||
| 		invalidated |= Inherited::invalidate_step(psBrim); | 		invalidated |= Inherited::invalidate_step(psBrim); | ||||||
|     if (step != psGCodeExport) |     if (step != psGCodeExport) | ||||||
|  | @ -1606,6 +1605,8 @@ void Print::process() | ||||||
|     } |     } | ||||||
|     if (this->set_started(psSkirt)) { |     if (this->set_started(psSkirt)) { | ||||||
|         m_skirt.clear(); |         m_skirt.clear(); | ||||||
|  |         m_skirt_convex_hull.clear(); | ||||||
|  |         m_first_layer_convex_hull.points.clear(); | ||||||
|         if (this->has_skirt()) { |         if (this->has_skirt()) { | ||||||
|             this->set_status(88, L("Generating skirt")); |             this->set_status(88, L("Generating skirt")); | ||||||
|             this->_make_skirt(); |             this->_make_skirt(); | ||||||
|  | @ -1614,11 +1615,15 @@ void Print::process() | ||||||
|     } |     } | ||||||
| 	if (this->set_started(psBrim)) { | 	if (this->set_started(psBrim)) { | ||||||
|         m_brim.clear(); |         m_brim.clear(); | ||||||
|  |         m_first_layer_convex_hull.points.clear(); | ||||||
|         if (m_config.brim_width > 0) { |         if (m_config.brim_width > 0) { | ||||||
|             this->set_status(88, L("Generating brim")); |             this->set_status(88, L("Generating brim")); | ||||||
|             this->_make_brim(); |             this->_make_brim(); | ||||||
|         } |         } | ||||||
|        this->set_done(psBrim); |         // Brim depends on skirt (brim lines are trimmed by the skirt lines), therefore if
 | ||||||
|  |         // the skirt gets invalidated, brim gets invalidated as well and the following line is called.
 | ||||||
|  |         this->finalize_first_layer_convex_hull(); | ||||||
|  |         this->set_done(psBrim); | ||||||
|     } |     } | ||||||
|     BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); |     BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); | ||||||
| } | } | ||||||
|  | @ -1697,22 +1702,7 @@ void Print::_make_skirt() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Include the wipe tower.
 |     // Include the wipe tower.
 | ||||||
|     if (has_wipe_tower() && ! m_wipe_tower_data.tool_changes.empty()) { |     append(points, this->first_layer_wipe_tower_corners()); | ||||||
|         double width = m_config.wipe_tower_width + 2*m_wipe_tower_data.brim_width; |  | ||||||
|         double depth = m_wipe_tower_data.depth + 2*m_wipe_tower_data.brim_width; |  | ||||||
|         Vec2d pt = Vec2d(-m_wipe_tower_data.brim_width, -m_wipe_tower_data.brim_width); |  | ||||||
| 
 |  | ||||||
|         std::vector<Vec2d> pts; |  | ||||||
|         pts.push_back(Vec2d(pt.x(), pt.y())); |  | ||||||
|         pts.push_back(Vec2d(pt.x()+width, pt.y())); |  | ||||||
|         pts.push_back(Vec2d(pt.x()+width, pt.y()+depth)); |  | ||||||
|         pts.push_back(Vec2d(pt.x(), pt.y()+depth)); |  | ||||||
|         for (Vec2d& pt : pts) { |  | ||||||
|             pt = Eigen::Rotation2Dd(Geometry::deg2rad(m_config.wipe_tower_rotation_angle.value)) * pt; |  | ||||||
|             pt += Vec2d(m_config.wipe_tower_x.value, m_config.wipe_tower_y.value); |  | ||||||
|             points.push_back(Point(scale_(pt.x()), scale_(pt.y()))); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     if (points.size() < 3) |     if (points.size() < 3) | ||||||
|         // At least three points required for a convex hull.
 |         // At least three points required for a convex hull.
 | ||||||
|  | @ -1796,28 +1786,19 @@ void Print::_make_skirt() | ||||||
|     } |     } | ||||||
|     // Brims were generated inside out, reverse to print the outmost contour first.
 |     // Brims were generated inside out, reverse to print the outmost contour first.
 | ||||||
|     m_skirt.reverse(); |     m_skirt.reverse(); | ||||||
|  | 
 | ||||||
|  |     // Remember the outer edge of the last skirt line extruded as m_skirt_convex_hull.
 | ||||||
|  |     for (Polygon &poly : offset(convex_hull, distance + 0.5f * float(scale_(spacing)), ClipperLib::jtRound, float(scale_(0.1)))) | ||||||
|  |         append(m_skirt_convex_hull, std::move(poly.points)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Print::_make_brim() | void Print::_make_brim() | ||||||
| { | { | ||||||
|     // Brim is only printed on first layer and uses perimeter extruder.
 |     // Brim is only printed on first layer and uses perimeter extruder.
 | ||||||
|  |     Polygons    islands = this->first_layer_islands(); | ||||||
|  |     Polygons    loops; | ||||||
|     Flow        flow = this->brim_flow(); |     Flow        flow = this->brim_flow(); | ||||||
|     Polygons    islands; |     size_t      num_loops = size_t(floor(m_config.brim_width.value / flow.spacing())); | ||||||
|     for (PrintObject *object : m_objects) { |  | ||||||
|         Polygons object_islands; |  | ||||||
|         for (ExPolygon &expoly : object->m_layers.front()->lslices) |  | ||||||
|             object_islands.push_back(expoly.contour); |  | ||||||
|         if (! object->support_layers().empty()) |  | ||||||
|             object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); |  | ||||||
|         islands.reserve(islands.size() + object_islands.size() * object->instances().size()); |  | ||||||
|         for (const PrintInstance &instance : object->instances()) |  | ||||||
|             for (Polygon &poly : object_islands) { |  | ||||||
|                 islands.push_back(poly); |  | ||||||
|                 islands.back().translate(instance.shift); |  | ||||||
|             } |  | ||||||
|     } |  | ||||||
|     Polygons loops; |  | ||||||
|     size_t num_loops = size_t(floor(m_config.brim_width.value / flow.spacing())); |  | ||||||
|     for (size_t i = 0; i < num_loops; ++ i) { |     for (size_t i = 0; i < num_loops; ++ i) { | ||||||
|         this->throw_if_canceled(); |         this->throw_if_canceled(); | ||||||
|         islands = offset(islands, float(flow.scaled_spacing()), jtSquare); |         islands = offset(islands, float(flow.scaled_spacing()), jtSquare); | ||||||
|  | @ -1828,6 +1809,11 @@ void Print::_make_brim() | ||||||
|             p.pop_back(); |             p.pop_back(); | ||||||
|             poly.points = std::move(p); |             poly.points = std::move(p); | ||||||
|         } |         } | ||||||
|  |         if (i + 1 == num_loops) { | ||||||
|  |             // Remember the outer edge of the last brim line extruded as m_first_layer_convex_hull.
 | ||||||
|  |             for (Polygon &poly : islands) | ||||||
|  |                 append(m_first_layer_convex_hull.points, poly.points); | ||||||
|  |         } | ||||||
|         polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); |         polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); | ||||||
|     } |     } | ||||||
|     loops = union_pt_chained(loops, false); |     loops = union_pt_chained(loops, false); | ||||||
|  | @ -1967,6 +1953,58 @@ void Print::_make_brim() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | Polygons Print::first_layer_islands() const | ||||||
|  | { | ||||||
|  |     Polygons islands; | ||||||
|  |     for (PrintObject *object : m_objects) { | ||||||
|  |         Polygons object_islands; | ||||||
|  |         for (ExPolygon &expoly : object->m_layers.front()->lslices) | ||||||
|  |             object_islands.push_back(expoly.contour); | ||||||
|  |         if (! object->support_layers().empty()) | ||||||
|  |             object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); | ||||||
|  |         islands.reserve(islands.size() + object_islands.size() * object->instances().size()); | ||||||
|  |         for (const PrintInstance &instance : object->instances()) | ||||||
|  |             for (Polygon &poly : object_islands) { | ||||||
|  |                 islands.push_back(poly); | ||||||
|  |                 islands.back().translate(instance.shift); | ||||||
|  |             } | ||||||
|  |     } | ||||||
|  |     return islands; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::vector<Point> Print::first_layer_wipe_tower_corners() const | ||||||
|  | { | ||||||
|  |     std::vector<Point> corners; | ||||||
|  |     if (has_wipe_tower() && ! m_wipe_tower_data.tool_changes.empty()) { | ||||||
|  |         double width = m_config.wipe_tower_width + 2*m_wipe_tower_data.brim_width; | ||||||
|  |         double depth = m_wipe_tower_data.depth + 2*m_wipe_tower_data.brim_width; | ||||||
|  |         Vec2d pt0(-m_wipe_tower_data.brim_width, -m_wipe_tower_data.brim_width); | ||||||
|  |         for (Vec2d pt : { | ||||||
|  |                 pt0, | ||||||
|  |                 Vec2d(pt0.x()+width, pt0.y()      ), | ||||||
|  |                 Vec2d(pt0.x()+width, pt0.y()+depth), | ||||||
|  |                 Vec2d(pt0.x(),       pt0.y()+depth) | ||||||
|  |             }) { | ||||||
|  |             pt = Eigen::Rotation2Dd(Geometry::deg2rad(m_config.wipe_tower_rotation_angle.value)) * pt; | ||||||
|  |             pt += Vec2d(m_config.wipe_tower_x.value, m_config.wipe_tower_y.value); | ||||||
|  |             corners.emplace_back(Point(scale_(pt.x()), scale_(pt.y()))); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return corners; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Print::finalize_first_layer_convex_hull() | ||||||
|  | { | ||||||
|  |     append(m_first_layer_convex_hull.points, m_skirt_convex_hull); | ||||||
|  |     if (m_first_layer_convex_hull.empty()) { | ||||||
|  |         // Neither skirt nor brim was extruded. Collect points of printed objects from 1st layer.
 | ||||||
|  |         for (Polygon &poly : this->first_layer_islands()) | ||||||
|  |             append(m_first_layer_convex_hull.points, std::move(poly.points)); | ||||||
|  |     } | ||||||
|  |     append(m_first_layer_convex_hull.points, this->first_layer_wipe_tower_corners()); | ||||||
|  |     m_first_layer_convex_hull = Geometry::convex_hull(m_first_layer_convex_hull.points); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Wipe tower support.
 | // Wipe tower support.
 | ||||||
| bool Print::has_wipe_tower() const | bool Print::has_wipe_tower() const | ||||||
| { | { | ||||||
|  | @ -1991,7 +2029,6 @@ const WipeTowerData& Print::wipe_tower_data(size_t extruders_cnt, double first_l | ||||||
|     return m_wipe_tower_data; |     return m_wipe_tower_data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void Print::_make_wipe_tower() | void Print::_make_wipe_tower() | ||||||
| { | { | ||||||
|     m_wipe_tower_data.clear(); |     m_wipe_tower_data.clear(); | ||||||
|  |  | ||||||
|  | @ -402,6 +402,12 @@ public: | ||||||
| 
 | 
 | ||||||
|     const ExtrusionEntityCollection& skirt() const { return m_skirt; } |     const ExtrusionEntityCollection& skirt() const { return m_skirt; } | ||||||
|     const ExtrusionEntityCollection& brim() const { return m_brim; } |     const ExtrusionEntityCollection& brim() const { return m_brim; } | ||||||
|  |     // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line.
 | ||||||
|  |     // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
 | ||||||
|  |     // It does NOT encompass user extrusions generated by custom G-code,
 | ||||||
|  |     // therefore it does NOT encompass the initial purge line.
 | ||||||
|  |     // It does NOT encompass MMU/MMU2 starting (wipe) areas.
 | ||||||
|  |     const Polygon&                   first_layer_convex_hull() const { return m_first_layer_convex_hull; } | ||||||
| 
 | 
 | ||||||
|     const PrintStatistics&      print_statistics() const { return m_print_statistics; } |     const PrintStatistics&      print_statistics() const { return m_print_statistics; } | ||||||
| 
 | 
 | ||||||
|  | @ -437,6 +443,12 @@ private: | ||||||
|     void                _make_skirt(); |     void                _make_skirt(); | ||||||
|     void                _make_brim(); |     void                _make_brim(); | ||||||
|     void                _make_wipe_tower(); |     void                _make_wipe_tower(); | ||||||
|  |     void                finalize_first_layer_convex_hull(); | ||||||
|  | 
 | ||||||
|  |     // Islands of objects and their supports extruded at the 1st layer.
 | ||||||
|  |     Polygons            first_layer_islands() const; | ||||||
|  |     // Return 4 wipe tower corners in the world coordinates (shifted and rotated), including the wipe tower brim.
 | ||||||
|  |     std::vector<Point>  first_layer_wipe_tower_corners() const; | ||||||
| 
 | 
 | ||||||
|     // Declared here to have access to Model / ModelObject / ModelInstance
 |     // Declared here to have access to Model / ModelObject / ModelInstance
 | ||||||
|     static void         model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src); |     static void         model_volume_list_update_supports(ModelObject &model_object_dst, const ModelObject &model_object_src); | ||||||
|  | @ -450,6 +462,13 @@ private: | ||||||
|     // Ordered collections of extrusion paths to build skirt loops and brim.
 |     // Ordered collections of extrusion paths to build skirt loops and brim.
 | ||||||
|     ExtrusionEntityCollection               m_skirt; |     ExtrusionEntityCollection               m_skirt; | ||||||
|     ExtrusionEntityCollection               m_brim; |     ExtrusionEntityCollection               m_brim; | ||||||
|  |     // Convex hull of the 1st layer extrusions.
 | ||||||
|  |     // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower.
 | ||||||
|  |     // It does NOT encompass user extrusions generated by custom G-code,
 | ||||||
|  |     // therefore it does NOT encompass the initial purge line.
 | ||||||
|  |     // It does NOT encompass MMU/MMU2 starting (wipe) areas.
 | ||||||
|  |     Polygon                                 m_first_layer_convex_hull; | ||||||
|  |     Points                                  m_skirt_convex_hull; | ||||||
| 
 | 
 | ||||||
|     // Following section will be consumed by the GCodeGenerator.
 |     // Following section will be consumed by the GCodeGenerator.
 | ||||||
|     ToolOrdering 							m_tool_ordering; |     ToolOrdering 							m_tool_ordering; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vojtech Bubnik
						Vojtech Bubnik