From ef74fffcba879a8f82ce0965bedc835ce12d2caa Mon Sep 17 00:00:00 2001 From: Wang YB <94800665+Gradbb@users.noreply.github.com> Date: Wed, 22 Nov 2023 13:23:00 +0800 Subject: [PATCH] update xy compensation --- src/libslic3r/Preset.cpp | 3 +- src/libslic3r/Print.hpp | 2 + src/libslic3r/PrintApply.cpp | 9 +- src/libslic3r/PrintConfig.cpp | 23 ++++- src/libslic3r/PrintConfig.hpp | 3 + src/libslic3r/PrintObject.cpp | 5 +- src/libslic3r/PrintObjectSlice.cpp | 134 +++++++++++++++++++++++--- src/slic3r/GUI/ConfigManipulation.cpp | 29 ++++++ src/slic3r/GUI/Tab.cpp | 6 +- 9 files changed, 196 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 755fbb5..b580420 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -479,7 +479,8 @@ static std::vector 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", - "elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", + //w11 + "elefant_foot_compensation", "xy_size_compensation", "xy_contour_compensation", "xy_hole_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width", "mmu_segmented_region_interlocking_depth", "wipe_tower_extruder", "wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits", "perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 0594919..b561450 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -379,6 +379,8 @@ private: void slice_volumes(); // Has any support (not counting the raft). + //w11 + ExPolygons _shrink_contour_holes(double contour_delta, double hole_delta, const ExPolygons &polys) const; void detect_surfaces_type(); void process_external_surfaces(); void discover_vertical_shells(); diff --git a/src/libslic3r/PrintApply.cpp b/src/libslic3r/PrintApply.cpp index 429d644..d0060ff 100644 --- a/src/libslic3r/PrintApply.cpp +++ b/src/libslic3r/PrintApply.cpp @@ -848,7 +848,8 @@ static PrintObjectRegions* generate_print_object_regions( const PrintRegionConfig &default_region_config, const Transform3d &trafo, size_t num_extruders, - const float xy_size_compensation, + //w11 + const float xy_contour_compensation, const std::vector &painting_extruders) { // Reuse the old object or generate a new one. @@ -879,8 +880,9 @@ static PrintObjectRegions* generate_print_object_regions( layer_ranges_regions.push_back({ range.layer_height_range, range.config }); } + //w11 const bool is_mm_painted = num_extruders > 1 && std::any_of(model_volumes.cbegin(), model_volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); }); - update_volume_bboxes(layer_ranges_regions, out->cached_volume_ids, model_volumes, out->trafo_bboxes, is_mm_painted ? 0.f : std::max(0.f, xy_size_compensation)); + update_volume_bboxes(layer_ranges_regions, out->cached_volume_ids, model_volumes, out->trafo_bboxes, is_mm_painted ? 0.f : std::max(0.f, xy_contour_compensation)); std::vector region_set; auto get_create_region = [®ion_set, &all_regions](PrintRegionConfig &&config) -> PrintRegion* { @@ -1403,7 +1405,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_ m_default_region_config, model_object_status.print_instances.front().trafo, num_extruders, - print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_size_compensation.value), + //w11 + print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_contour_compensation.value), painting_extruders); } for (auto it = it_print_object; it != it_print_object_end; ++it) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index a0dabae..6a0aa1a 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3386,7 +3386,8 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionInt(0)); - def = this->add("xy_size_compensation", coFloat); + //w11 + def = this->add("xy_size_compensation", coFloat); def->label = L("XY Size Compensation"); def->category = L("Advanced"); def->tooltip = L("The object will be grown/shrunk in the XY plane by the configured value " @@ -3395,6 +3396,26 @@ void PrintConfigDef::init_fff_params() def->sidetext = L("mm"); def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0)); + //w11 + def = this->add("xy_hole_compensation", coFloat); + def->label = L("X-Y hole compensation"); + def->category = L("Advanced"); + def->tooltip = L("Holes of object will be grown or shrunk in XY plane by the configured value. " + "Positive value makes holes bigger. Negative value makes holes smaller. " + "This function is used to adjust size slightly when the object has assembling issue"); + def->sidetext = L("mm"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0)); + + def = this->add("xy_contour_compensation", coFloat); + def->label = L("X-Y contour compensation"); + def->category = L("Advanced"); + def->tooltip = L("Contour of object will be grown or shrunk in XY plane by the configured value. " + "Positive value makes contour bigger. Negative value makes contour smaller. " + "This function is used to adjust size slightly when the object has assembling issue"); + def->sidetext = L("mm"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0)); def = this->add("z_offset", coFloat); def->label = L("Z offset"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f60b5a0..7a46b2a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -570,6 +570,9 @@ PRINT_CONFIG_CLASS_DEFINE( // The rest ((ConfigOptionBool, thick_bridges)) ((ConfigOptionFloat, xy_size_compensation)) + //w11 + ((ConfigOptionFloat, xy_hole_compensation)) + ((ConfigOptionFloat, xy_contour_compensation)) ((ConfigOptionBool, wipe_into_objects)) //w11 ((ConfigOptionBool, detect_narrow_internal_solid_infill)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index af8a820..824e7d5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -679,7 +679,10 @@ bool PrintObject::invalidate_state_by_config_options( } else if ( opt_key == "elefant_foot_compensation" || opt_key == "support_material_contact_distance" - || opt_key == "xy_size_compensation") { + //w11 + || opt_key == "xy_size_compensation" + || opt_key == "xy_hole_compensation" + || opt_key == "xy_contour_compensation") { steps.emplace_back(posSlice); } else if (opt_key == "support_material") { steps.emplace_back(posSupportMaterial); diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 6f6080c..29859f8 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -151,7 +151,9 @@ static std::vector slice_volumes_inner( const size_t num_extruders = print_config.nozzle_diameter.size(); const bool is_mm_painted = num_extruders > 1 && std::any_of(model_volumes.cbegin(), model_volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); }); - const auto extra_offset = is_mm_painted ? 0.f : std::max(0.f, float(print_object_config.xy_size_compensation.value)); + //w11 + //const auto extra_offset = is_mm_painted ? 0.f : std::max(0.f, float(print_object_config.xy_size_compensation.value)); + const auto extra_offset = 0.f; for (const ModelVolume *model_volume : model_volumes) if (model_volume_needs_slicing(*model_volume)) { @@ -728,7 +730,9 @@ void PrintObject::slice_volumes() // If XY Size compensation is also enabled, notify the user that XY Size compensation // would not be used because the object is multi-material painted. - if (m_config.xy_size_compensation.value != 0.f) { + //w11 + //if (m_config.xy_size_compensation.value != 0.f) { + if (m_config.xy_hole_compensation.value != 0.f || m_config.xy_contour_compensation.value != 0.f) { this->active_step_add_warning( PrintStateBase::WarningLevel::CRITICAL, _u8L("An object has enabled XY Size compensation which will not be used because it is also multi-material painted.\nXY Size " @@ -746,6 +750,9 @@ void PrintObject::slice_volumes() // Compensation value, scaled. Only applying the negative scaling here, as the positive scaling has already been applied during slicing. const size_t num_extruders = print->config().nozzle_diameter.size(); const auto xy_compensation_scaled = (num_extruders > 1 && this->is_mm_painted()) ? scaled(0.f) : scaled(std::min(m_config.xy_size_compensation.value, 0.)); + //w11 + const auto xy_hole_scaled = (num_extruders > 1 && this->is_mm_painted()) ? scaled(0.f) : scaled(m_config.xy_hole_compensation.value); + const auto xy_contour_scaled = (num_extruders > 1 && this->is_mm_painted()) ? scaled(0.f) : scaled(m_config.xy_contour_compensation.value); const float elephant_foot_compensation_scaled = (m_config.raft_layers == 0) ? // Only enable Elephant foot compensation if printing directly on the print bed. float(scale_(m_config.elefant_foot_compensation.value)) : @@ -754,7 +761,9 @@ void PrintObject::slice_volumes() ExPolygons lslices_1st_layer; tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), - [this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer](const tbb::blocked_range& range) { + //w11 + //[this, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer](const tbb::blocked_range& range) { + [this, xy_hole_scaled, xy_contour_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer](const tbb::blocked_range& range) { for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) { m_print->throw_if_canceled(); Layer *layer = m_layers[layer_id]; @@ -767,7 +776,9 @@ void PrintObject::slice_volumes() if (elfoot > 0) { // Apply the elephant foot compensation and store the 1st layer slices without the Elephant foot compensation applied. lslices_1st_layer = to_expolygons(std::move(layerm->m_slices.surfaces)); - float delta = xy_compensation_scaled; + //w11 + //float delta = xy_compensation_scaled; + float delta = 0.15; if (delta > elfoot) { delta -= elfoot; elfoot = 0.f; @@ -779,16 +790,44 @@ void PrintObject::slice_volumes() (delta == 0.f) ? lslices_1st_layer : offset_ex(lslices_1st_layer, delta), layerm->flow(frExternalPerimeter), unscale(elfoot))), stInternal); - if (xy_compensation_scaled < 0.f) - lslices_1st_layer = offset_ex(std::move(lslices_1st_layer), xy_compensation_scaled); - } else if (xy_compensation_scaled < 0.f) { + //w11 + if (m_config.xy_size_compensation.value < 0.f) + lslices_1st_layer = offset_ex(std::move(lslices_1st_layer), m_config.xy_size_compensation.value); + lslices_1st_layer = to_expolygons(std::move(layerm->m_slices.surfaces)); + if (xy_contour_scaled > 0 || xy_hole_scaled > 0) { + lslices_1st_layer = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), std::max(0.f, xy_hole_scaled), + lslices_1st_layer); + } + if (xy_contour_scaled < 0 || xy_hole_scaled < 0) { + lslices_1st_layer = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), std::min(0.f, xy_hole_scaled), + lslices_1st_layer); + } + layerm->m_slices.set(union_ex(Slic3r::elephant_foot_compensation(lslices_1st_layer, + layerm->flow(frExternalPerimeter), + unscale(elfoot))), + stInternal); + } /*else (xy_compensation_scaled < 0.f) { // Apply the XY compensation. layerm->m_slices.set( offset_ex(to_expolygons(std::move(layerm->m_slices.surfaces)), xy_compensation_scaled), - stInternal); + stInternal);*/ + //w11 + else { + if (xy_contour_scaled != 0.0f || xy_hole_scaled != 0.0f) { + ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces)); + if (xy_contour_scaled > 0 || xy_hole_scaled > 0) { + expolygons = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), std::max(0.f, xy_hole_scaled), + expolygons); + } + if (xy_contour_scaled < 0 || xy_hole_scaled < 0) { + expolygons = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), std::min(0.f, xy_hole_scaled), + expolygons); + } + layerm->m_slices.set(std::move(expolygons), stInternal); + } } } else { - if (xy_compensation_scaled < 0.f || elfoot > 0.f) { + /* if (xy_compensation_scaled < 0.f || elfoot > 0.f) { // Apply the negative XY compensation. Polygons trimming; static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); @@ -800,7 +839,50 @@ void PrintObject::slice_volumes() trimming = offset(layer->merged(float(SCALED_EPSILON)), xy_compensation_scaled - float(SCALED_EPSILON)); for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) layer->m_regions[region_id]->trim_surfaces(trimming); - } + }*/ + //w11 + float max_growth = std::max(xy_hole_scaled, xy_contour_scaled); + float min_growth = std::min(xy_hole_scaled, xy_contour_scaled); + ExPolygons merged_poly_for_holes_growing; + if (max_growth > 0) { + merged_poly_for_holes_growing = layer->merged(float(SCALED_EPSILON)); + merged_poly_for_holes_growing = _shrink_contour_holes(std::max(0.f, xy_contour_scaled), + std::max(0.f, xy_hole_scaled), + union_ex(merged_poly_for_holes_growing)); + + Polygons processed; + for (size_t region_id = 0; region_id < layer->regions().size(); ++region_id) { + ExPolygons slices = to_expolygons(std::move(layer->m_regions[region_id]->m_slices.surfaces)); + if (max_growth > 0.f) { + slices = intersection_ex(offset_ex(slices, max_growth), merged_poly_for_holes_growing); + } + + if (region_id > 0) + slices = diff_ex(to_polygons(std::move(slices)), processed); + if (region_id + 1 < layer->regions().size()) + polygons_append(processed, slices); + layer->m_regions[region_id]->m_slices.set(std::move(slices), stInternal); + } + } + if (min_growth < 0.f || elfoot > 0.f) { + ExPolygons trimming; + static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5); + if (elfoot > 0.f) { + lslices_1st_layer = offset_ex(layer->merged(eps), -eps); + trimming = Slic3r::elephant_foot_compensation(lslices_1st_layer, + layer->m_regions.front()->flow(frExternalPerimeter), + unscale(elfoot)); + } else { + trimming = layer->merged(float(SCALED_EPSILON)); + } + if (min_growth < 0.0f) + trimming = _shrink_contour_holes(std::min(0.f, xy_contour_scaled), std::min(0.f, xy_hole_scaled), trimming); + for (size_t region_id = 0; region_id < layer->regions().size(); ++region_id) { + ExPolygons contour_exp = to_expolygons(std::move(layer->regions()[region_id]->m_slices.surfaces)); + + layer->regions()[region_id]->m_slices.set(intersection_ex(contour_exp, to_polygons(trimming)), stInternal); + } + } } // Merge all regions' slices to get islands sorted topologically, chain them by a shortest path in separate index list layer->make_slices(); @@ -821,7 +903,37 @@ void PrintObject::slice_volumes() m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Slicing volumes - make_slices in parallel - end"; } - +//w11 +ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double hole_delta, const ExPolygons &polys) const +{ + ExPolygons new_ex_polys; + for (const ExPolygon &ex_poly : polys) { + Polygons contours; + Polygons holes; + for (const Polygon &hole : ex_poly.holes) { + if (hole_delta != 0) { + for (Polygon &newHole : offset(hole, -hole_delta)) { + newHole.make_counter_clockwise(); + holes.emplace_back(std::move(newHole)); + } + } else { + holes.push_back(hole); + holes.back().make_counter_clockwise(); + } + } + if (contour_delta != 0) { + Polygons new_contours = offset(ex_poly.contour, contour_delta); + if (new_contours.size() == 0) + continue; + contours.insert(contours.end(), std::make_move_iterator(new_contours.begin()), std::make_move_iterator(new_contours.end())); + } else { + contours.push_back(ex_poly.contour); + } + ExPolygons temp = diff_ex(union_(contours), union_(holes)); + new_ex_polys.insert(new_ex_polys.end(), std::make_move_iterator(temp.begin()), std::make_move_iterator(temp.end())); + } + return union_ex(new_ex_polys); +} std::vector PrintObject::slice_support_volumes(const ModelVolumeType model_volume_type) const { auto it_volume = this->model_object()->volumes.begin(); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 8126576..4c9436e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -181,6 +181,35 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con m_support_material_overhangs_queried = false; } + //w11 + if (abs(config->option("xy_hole_compensation")->value) > 2) { + const wxString msg_text = _(L("This setting is only used for model size tunning with small value in some cases.\n" + "For example, when model size has small error and hard to be assembled.\n" + "For large size tuning, please use model scale function.\n\n" + "The value will be reset to 0.")); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); + DynamicPrintConfig new_conf = *config; + is_msg_dlg_already_exist = true; + dialog.ShowModal(); + new_conf.set_key_value("xy_hole_compensation", new ConfigOptionFloat(0)); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } + + if (abs(config->option("xy_contour_compensation")->value) > 2) { + const wxString msg_text = _(L("This setting is only used for model size tunning with small value in some cases.\n" + "For example, when model size has small error and hard to be assembled.\n" + "For large size tuning, please use model scale function.\n\n" + "The value will be reset to 0.")); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxOK); + DynamicPrintConfig new_conf = *config; + is_msg_dlg_already_exist = true; + dialog.ShowModal(); + new_conf.set_key_value("xy_contour_compensation", new ConfigOptionFloat(0)); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } + if (config->option("fill_density")->value == 100) { const int fill_pattern = config->option>("fill_pattern")->value; if (bool correct_100p_fill = config->option_def("top_fill_pattern")->enum_def->enum_to_index(fill_pattern).has_value(); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6c649dd..cefda89 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1655,7 +1655,11 @@ void TabPrint::build() 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"); + //w11 + //optgroup->append_single_option_line("xy_size_compensation"); + optgroup->append_single_option_line("xy_hole_compensation"); + optgroup->append_single_option_line("xy_contour_compensation"); + //optgroup->append_single_option_line("xy_size_compensation"); optgroup->append_single_option_line("elefant_foot_compensation", "elephant-foot-compensation_114487"); optgroup = page->new_optgroup(L("Arachne perimeter generator"));