mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 20:51:12 -06:00 
			
		
		
		
	New config value "gcode_resolution" replaces the hard coded RESOLUTION
value, which was set to 0.0125mm.
This commit is contained in:
		
							parent
							
								
									efaf4e47c1
								
							
						
					
					
						commit
						4158f9ec8e
					
				
					 15 changed files with 56 additions and 27 deletions
				
			
		|  | @ -126,7 +126,7 @@ static ConstPrintObjectPtrs get_top_level_objects_with_brim(const Print &print, | |||
|     return top_level_objects_with_brim; | ||||
| } | ||||
| 
 | ||||
| static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_level_objects_with_brim) | ||||
| static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_level_objects_with_brim, const double scaled_resolution) | ||||
| { | ||||
|     Polygons islands; | ||||
|     for (const PrintObject *object : top_level_objects_with_brim) { | ||||
|  | @ -139,7 +139,7 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev | |||
|         for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { | ||||
|             Polygons contour_offset = offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare); | ||||
|             for (Polygon &poly : contour_offset) | ||||
|                 poly.douglas_peucker(SCALED_RESOLUTION); | ||||
|                 poly.douglas_peucker(scaled_resolution); | ||||
| 
 | ||||
|             polygons_append(islands_object, std::move(contour_offset)); | ||||
|         } | ||||
|  | @ -359,13 +359,14 @@ static void make_inner_brim(const Print                   &print, | |||
|                             ExtrusionEntityCollection     &brim) | ||||
| { | ||||
|     assert(print.objects().size() == bottom_layers_expolygons.size()); | ||||
|     const auto scaled_resolution = scaled<double>(print.config().gcode_resolution.value); | ||||
|     Flow       flow = print.brim_flow(); | ||||
|     ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing())); | ||||
|     Polygons   loops; | ||||
|     islands_ex      = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), ClipperLib::jtSquare); | ||||
|     for (size_t i = 0; !islands_ex.empty(); ++i) { | ||||
|         for (ExPolygon &poly_ex : islands_ex) | ||||
|             poly_ex.douglas_peucker(SCALED_RESOLUTION); | ||||
|             poly_ex.douglas_peucker(scaled_resolution); | ||||
|         polygons_append(loops, to_polygons(islands_ex)); | ||||
|         islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), ClipperLib::jtSquare); | ||||
|     } | ||||
|  | @ -380,10 +381,11 @@ static void make_inner_brim(const Print                   &print, | |||
| // Collect islands_area to be merged into the final 1st layer convex hull.
 | ||||
| ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cancel, Polygons &islands_area) | ||||
| { | ||||
|     const auto              scaled_resolution           = scaled<double>(print.config().gcode_resolution.value); | ||||
|     Flow                    flow                        = print.brim_flow(); | ||||
|     std::vector<ExPolygons> bottom_layers_expolygons    = get_print_bottom_layers_expolygons(print); | ||||
|     ConstPrintObjectPtrs    top_level_objects_with_brim = get_top_level_objects_with_brim(print, bottom_layers_expolygons); | ||||
|     Polygons                islands                     = top_level_outer_brim_islands(top_level_objects_with_brim); | ||||
|     Polygons                islands                     = top_level_outer_brim_islands(top_level_objects_with_brim, scaled_resolution); | ||||
|     ExPolygons              islands_area_ex             = top_level_outer_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing())); | ||||
|     islands_area                                        = to_polygons(islands_area_ex); | ||||
| 
 | ||||
|  | @ -393,7 +395,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance | |||
|         try_cancel(); | ||||
|         islands = expand(islands, float(flow.scaled_spacing()), ClipperLib::jtSquare); | ||||
|         for (Polygon &poly : islands)  | ||||
|             poly.douglas_peucker(SCALED_RESOLUTION); | ||||
|             poly.douglas_peucker(scaled_resolution); | ||||
|         polygons_append(loops, shrink(islands, 0.5f * float(flow.scaled_spacing()))); | ||||
|     } | ||||
|     loops = union_pt_chained_outside_in(loops); | ||||
|  |  | |||
|  | @ -329,7 +329,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: | |||
| #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ | ||||
| 
 | ||||
| 	std::vector<SurfaceFill>  surface_fills = group_fills(*this); | ||||
| 	const Slic3r::BoundingBox bbox = this->object()->bounding_box(); | ||||
| 	const Slic3r::BoundingBox bbox 			= this->object()->bounding_box(); | ||||
| 	const auto                resolution 	= this->object()->print()->config().gcode_resolution.value; | ||||
| 
 | ||||
| #ifdef SLIC3R_DEBUG_SLICE_PROCESSING | ||||
| 	{ | ||||
|  | @ -371,6 +372,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: | |||
| 		params.dont_adjust		 = false; //  surface_fill.params.dont_adjust;
 | ||||
|         params.anchor_length     = surface_fill.params.anchor_length; | ||||
| 		params.anchor_length_max = surface_fill.params.anchor_length_max; | ||||
| 		params.resolution        = resolution; | ||||
| 
 | ||||
|         for (ExPolygon &expoly : surface_fill.expolygons) { | ||||
| 			// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
 | ||||
|  |  | |||
|  | @ -44,6 +44,9 @@ struct FillParams | |||
|     float       anchor_length       { 1000.f }; | ||||
|     float       anchor_length_max   { 1000.f }; | ||||
| 
 | ||||
|     // G-code resolution.
 | ||||
|     double      resolution          { 0.0125 }; | ||||
| 
 | ||||
|     // Don't adjust spacing to fill the space evenly.
 | ||||
|     bool        dont_adjust 	{ true }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,7 +31,8 @@ void FillPlanePath::_fill_surface_single( | |||
|         coord_t(ceil(coordf_t(bounding_box.min.x()) / distance_between_lines)), | ||||
|         coord_t(ceil(coordf_t(bounding_box.min.y()) / distance_between_lines)), | ||||
|         coord_t(ceil(coordf_t(bounding_box.max.x()) / distance_between_lines)), | ||||
|         coord_t(ceil(coordf_t(bounding_box.max.y()) / distance_between_lines))); | ||||
|         coord_t(ceil(coordf_t(bounding_box.max.y()) / distance_between_lines)), | ||||
|         params.resolution); | ||||
| 
 | ||||
|     if (pts.size() >= 2) { | ||||
|         // Convert points to a polyline, upscale.
 | ||||
|  | @ -58,7 +59,7 @@ void FillPlanePath::_fill_surface_single( | |||
| } | ||||
| 
 | ||||
| // Follow an Archimedean spiral, in polar coordinates: r=a+b\theta
 | ||||
| Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) | ||||
| Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) | ||||
| { | ||||
|     // Radius to achieve.
 | ||||
|     coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5; | ||||
|  | @ -72,8 +73,8 @@ Pointfs FillArchimedeanChords::_generate(coord_t min_x, coord_t min_y, coord_t m | |||
|     out.emplace_back(0, 0); | ||||
|     out.emplace_back(1, 0); | ||||
|     while (r < rmax) { | ||||
|         // Discretization angle to achieve a discretization error lower than RESOLUTION.
 | ||||
|         theta += 2. * acos(1. - RESOLUTION / r); | ||||
|         // Discretization angle to achieve a discretization error lower than resolution.
 | ||||
|         theta += 2. * acos(1. - resolution / r); | ||||
|         r = a + b * theta; | ||||
|         out.emplace_back(r * cos(theta), r * sin(theta)); | ||||
|     } | ||||
|  | @ -125,7 +126,7 @@ static inline Point hilbert_n_to_xy(const size_t n) | |||
|     return Point(x, y); | ||||
| } | ||||
| 
 | ||||
| Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) | ||||
| Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */) | ||||
| { | ||||
|     // Minimum power of two square to fit the domain.
 | ||||
|     size_t sz = 2; | ||||
|  | @ -148,7 +149,7 @@ Pointfs FillHilbertCurve::_generate(coord_t min_x, coord_t min_y, coord_t max_x, | |||
|     return line; | ||||
| } | ||||
| 
 | ||||
| Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) | ||||
| Pointfs FillOctagramSpiral::_generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double /* resolution */) | ||||
| { | ||||
|     // Radius to achieve.
 | ||||
|     coordf_t rmax = std::sqrt(coordf_t(max_x)*coordf_t(max_x)+coordf_t(max_y)*coordf_t(max_y)) * std::sqrt(2.) + 1.5; | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ protected: | |||
| 
 | ||||
|     float _layer_angle(size_t idx) const override { return 0.f; } | ||||
|     virtual bool  _centered() const = 0; | ||||
|     virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) = 0; | ||||
|     virtual Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) = 0; | ||||
| }; | ||||
| 
 | ||||
| class FillArchimedeanChords : public FillPlanePath | ||||
|  | @ -39,7 +39,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     bool  _centered() const override { return true; } | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) override; | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override; | ||||
| }; | ||||
| 
 | ||||
| class FillHilbertCurve : public FillPlanePath | ||||
|  | @ -50,7 +50,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     bool  _centered() const override { return false; } | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) override; | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override; | ||||
| }; | ||||
| 
 | ||||
| class FillOctagramSpiral : public FillPlanePath | ||||
|  | @ -61,7 +61,7 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     bool  _centered() const override { return true; } | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y) override; | ||||
|     Pointfs _generate(coord_t min_x, coord_t min_y, coord_t max_x, coord_t max_y, const double resolution) override; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Slic3r
 | ||||
|  |  | |||
|  | @ -2414,6 +2414,7 @@ void GCode::apply_print_config(const PrintConfig &print_config) | |||
| { | ||||
|     m_writer.apply_print_config(print_config); | ||||
|     m_config.apply(print_config); | ||||
|     m_scaled_resolution = scaled<double>(print_config.gcode_resolution.value); | ||||
| } | ||||
| 
 | ||||
| void GCode::append_full_config(const Print &print, std::string &str) | ||||
|  | @ -2565,7 +2566,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou | |||
|     for (ExtrusionPaths::iterator path = paths.begin(); path != paths.end(); ++path) { | ||||
| //    description += ExtrusionLoop::role_to_string(loop.loop_role());
 | ||||
| //    description += ExtrusionEntity::role_to_string(path->role);
 | ||||
|         path->simplify(SCALED_RESOLUTION); | ||||
|         path->simplify(m_scaled_resolution); | ||||
|         gcode += this->_extrude(*path, description, speed); | ||||
|     } | ||||
| 
 | ||||
|  | @ -2619,7 +2620,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string | |||
|     for (ExtrusionPath path : multipath.paths) { | ||||
| //    description += ExtrusionLoop::role_to_string(loop.loop_role());
 | ||||
| //    description += ExtrusionEntity::role_to_string(path->role);
 | ||||
|         path.simplify(SCALED_RESOLUTION); | ||||
|         path.simplify(m_scaled_resolution); | ||||
|         gcode += this->_extrude(path, description, speed); | ||||
|     } | ||||
|     if (m_wipe.enable) { | ||||
|  | @ -2647,7 +2648,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des | |||
| std::string GCode::extrude_path(ExtrusionPath path, std::string description, double speed) | ||||
| { | ||||
| //    description += ExtrusionEntity::role_to_string(path.role());
 | ||||
|     path.simplify(SCALED_RESOLUTION); | ||||
|     path.simplify(m_scaled_resolution); | ||||
|     std::string gcode = this->_extrude(path, description, speed); | ||||
|     if (m_wipe.enable) { | ||||
|         m_wipe.path = std::move(path.polyline); | ||||
|  |  | |||
|  | @ -345,6 +345,8 @@ private: | |||
|        methods. */ | ||||
|     Vec2d                               m_origin; | ||||
|     FullPrintConfig                     m_config; | ||||
|     // scaled G-code resolution
 | ||||
|     double                              m_scaled_resolution; | ||||
|     GCodeWriter                         m_writer; | ||||
|     PlaceholderParser                   m_placeholder_parser; | ||||
|     // For random number generator etc.
 | ||||
|  |  | |||
|  | @ -322,7 +322,7 @@ void PerimeterGenerator::process() | |||
|     for (const Surface &surface : this->slices->surfaces) { | ||||
|         // detect how many perimeters must be generated for this island
 | ||||
|         int        loop_number = this->config->perimeters + surface.extra_perimeters - 1;  // 0-indexed loops
 | ||||
|         ExPolygons last        = union_ex(surface.expolygon.simplify_p(SCALED_RESOLUTION)); | ||||
|         ExPolygons last        = union_ex(surface.expolygon.simplify_p(m_scaled_resolution)); | ||||
|         ExPolygons gaps; | ||||
|         if (loop_number >= 0) { | ||||
|             // In case no perimeters are to be generated, loop_number will equal to -1.
 | ||||
|  | @ -533,7 +533,7 @@ void PerimeterGenerator::process() | |||
|         // simplify infill contours according to resolution
 | ||||
|         Polygons pp; | ||||
|         for (ExPolygon &ex : last) | ||||
|             ex.simplify_p(SCALED_RESOLUTION, &pp); | ||||
|             ex.simplify_p(m_scaled_resolution, &pp); | ||||
|         // collapse too narrow infill areas
 | ||||
|         coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE)); | ||||
|         // append infill areas to fill_surfaces
 | ||||
|  |  | |||
|  | @ -50,6 +50,7 @@ public: | |||
|             overhang_flow(flow), solid_infill_flow(flow), | ||||
|             config(config), object_config(object_config), print_config(print_config), | ||||
|             m_spiral_vase(spiral_vase), | ||||
|             m_scaled_resolution(scaled<double>(print_config->gcode_resolution.value)), | ||||
|             loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces), | ||||
|             m_ext_mm3_per_mm(-1), m_mm3_per_mm(-1), m_mm3_per_mm_overhang(-1) | ||||
|         {} | ||||
|  | @ -63,6 +64,7 @@ public: | |||
| 
 | ||||
| private: | ||||
|     bool        m_spiral_vase; | ||||
|     double      m_scaled_resolution; | ||||
|     double      m_ext_mm3_per_mm; | ||||
|     double      m_mm3_per_mm; | ||||
|     double      m_mm3_per_mm_overhang; | ||||
|  |  | |||
|  | @ -444,7 +444,7 @@ static std::vector<std::string> s_Preset_print_options { | |||
|     "ooze_prevention", "standby_temperature_delta", "interface_shells", "extrusion_width", "first_layer_extrusion_width", | ||||
|     "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", | ||||
|     "top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio", "clip_multipart_objects", | ||||
|     "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", | ||||
|     "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", | ||||
|     "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", | ||||
|     "wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits" | ||||
| }; | ||||
|  |  | |||
|  | @ -214,7 +214,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n | |||
|         } else if ( | ||||
|                opt_key == "first_layer_extrusion_width"  | ||||
|             || opt_key == "min_layer_height" | ||||
|             || opt_key == "max_layer_height") { | ||||
|             || opt_key == "max_layer_height" | ||||
|             || opt_key == "gcode_resolution") { | ||||
|             osteps.emplace_back(posPerimeters); | ||||
|             osteps.emplace_back(posInfill); | ||||
|             osteps.emplace_back(posSupportMaterial); | ||||
|  |  | |||
|  | @ -2072,7 +2072,7 @@ void PrintConfigDef::init_fff_params() | |||
|     def->set_default_value(new ConfigOptionInt(0)); | ||||
| 
 | ||||
|     def = this->add("resolution", coFloat); | ||||
|     def->label = L("Resolution"); | ||||
|     def->label = L("Slice resolution"); | ||||
|     def->tooltip = L("Minimum detail resolution, used to simplify the input file for speeding up " | ||||
|                    "the slicing job and reducing memory usage. High-resolution models often carry " | ||||
|                    "more detail than printers can render. Set to zero to disable any simplification " | ||||
|  | @ -2082,6 +2082,18 @@ void PrintConfigDef::init_fff_params() | |||
|     def->mode = comExpert; | ||||
|     def->set_default_value(new ConfigOptionFloat(0)); | ||||
| 
 | ||||
|     def = this->add("gcode_resolution", coFloat); | ||||
|     def->label = L("G-code resolution"); | ||||
|     def->tooltip = L("Maximum deviation of exported G-code paths from their full resolution counterparts. " | ||||
|                      "Very high resolution G-code requires huge amount of RAM to slice and preview, " | ||||
|                      "also a 3D printer may stutter not being able to process a high resolution G-code in a timely manner. " | ||||
|                      "On the other hand, a low resolution G-code will produce a low poly effect and because " | ||||
|                      "the G-code reduction is performed at each layer independently, visible artifacts may be produced."); | ||||
|     def->sidetext = L("mm"); | ||||
|     def->min = 0; | ||||
|     def->mode = comExpert; | ||||
|     def->set_default_value(new ConfigOptionFloat(0.0125)); | ||||
| 
 | ||||
|     def = this->add("retract_before_travel", coFloats); | ||||
|     def->label = L("Minimum travel after retraction"); | ||||
|     def->tooltip = L("Retraction is not triggered when travel moves are shorter than this length."); | ||||
|  | @ -3940,6 +3952,10 @@ void DynamicPrintConfig::normalize_fdm() | |||
|             this->opt<ConfigOptionPercent>("fill_density", true)->value = 0; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (auto *opt_gcode_resolution = this->opt<ConfigOptionFloat>("gcode_resolution", false); opt_gcode_resolution) | ||||
|         // Resolution will be above 1um.
 | ||||
|         opt_gcode_resolution->value = std::max(opt_gcode_resolution->value, 0.001); | ||||
| } | ||||
| 
 | ||||
| void  handle_legacy_sla(DynamicPrintConfig &config) | ||||
|  |  | |||
|  | @ -734,6 +734,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( | |||
|     ((ConfigOptionString,             printer_model)) | ||||
|     ((ConfigOptionString,             printer_notes)) | ||||
|     ((ConfigOptionFloat,              resolution)) | ||||
|     ((ConfigOptionFloat,              gcode_resolution)) | ||||
|     ((ConfigOptionFloats,             retract_before_travel)) | ||||
|     ((ConfigOptionBools,              retract_layer_change)) | ||||
|     ((ConfigOptionFloat,              skirt_distance)) | ||||
|  |  | |||
|  | @ -47,9 +47,6 @@ static constexpr double EPSILON = 1e-4; | |||
| // int32_t fits an interval of (-2147.48mm, +2147.48mm)
 | ||||
| // with int64_t we don't have to worry anymore about the size of the int.
 | ||||
| static constexpr double SCALING_FACTOR = 0.000001; | ||||
| // RESOLUTION, SCALED_RESOLUTION: Used as an error threshold for a Douglas-Peucker polyline simplification algorithm.
 | ||||
| static constexpr double RESOLUTION = 0.0125; | ||||
| #define                 SCALED_RESOLUTION (RESOLUTION / SCALING_FACTOR) | ||||
| static constexpr double PI = 3.141592653589793238; | ||||
| // When extruding a closed loop, the loop is interrupted and shortened a bit to reduce the seam.
 | ||||
| static constexpr double LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER = 0.15; | ||||
|  |  | |||
|  | @ -1650,6 +1650,7 @@ void TabPrint::build() | |||
|         optgroup->append_single_option_line("slice_closing_radius"); | ||||
|         optgroup->append_single_option_line("slicing_mode"); | ||||
|         optgroup->append_single_option_line("resolution"); | ||||
|         optgroup->append_single_option_line("gcode_resolution"); | ||||
|         optgroup->append_single_option_line("xy_size_compensation"); | ||||
|         optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487"); | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vojtech Bubnik
						Vojtech Bubnik