From 3ec2f077e5e43bfc21e18b3faac9211685731bfb Mon Sep 17 00:00:00 2001 From: supermerill Date: Thu, 20 Aug 2020 01:57:54 +0200 Subject: [PATCH] #399 add an other pattern for brim ear: rectilinear with perimeter. If you have problem with adhesion of the ear. also some fixes about brim invalidation. --- resources/ui_layout/print.ui | 1 + src/libslic3r/Fill/FillRectilinear2.cpp | 4 +- src/libslic3r/Print.cpp | 150 ++++++++++++++++-------- src/libslic3r/PrintConfig.cpp | 17 +++ src/libslic3r/PrintConfig.hpp | 2 + src/libslic3r/PrintObject.cpp | 9 ++ src/slic3r/GUI/ConfigManipulation.cpp | 1 + src/slic3r/GUI/Field.cpp | 4 +- src/slic3r/GUI/GUI.cpp | 3 +- src/slic3r/GUI/OptionsGroup.cpp | 3 +- src/slic3r/GUI/Preset.cpp | 1 + 11 files changed, 137 insertions(+), 58 deletions(-) diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index a61d9c702..3a5d0e2bd 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -154,6 +154,7 @@ group:Brim line:Brim ears setting:brim_ears setting:width$3:brim_ears_max_angle + setting:brim_ears_pattern end_line setting:brim_offset diff --git a/src/libslic3r/Fill/FillRectilinear2.cpp b/src/libslic3r/Fill/FillRectilinear2.cpp index 54df23f0b..2d498a168 100644 --- a/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/src/libslic3r/Fill/FillRectilinear2.cpp @@ -898,7 +898,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP surface->expolygon, - rotate_vector.first, scale_(0 /*this->overlap*/ - (0.5 - INFILL_OVERLAP_OVER_SPACING) * this->spacing), - scale_(0 /*this->overlap*/ - 0.5 * this->spacing)); + scale_(0 /*this->overlap*/ - (params.full_infill() && params.fill_exactly ? 0.5 + INFILL_OVERLAP_OVER_SPACING : 0.5) * this->spacing)); if (poly_with_offset.n_contours_inner == 0) { // Not a single infill line fits. //Prusa: maybe one shall trigger the gap fill here? @@ -909,7 +909,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP BoundingBox bounding_box = poly_with_offset.bounding_box_src(); // define flow spacing according to requested density - if (params.full_infill() && !params.dont_adjust) { + if (params.full_infill() && !params.dont_adjust || line_spacing == 0 ) { //it's == this->_adjust_solid_spacing(bounding_box.size()(0), line_spacing) because of the init_spacing line_spacing = scale_(this->spacing); } else { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 91208bcc8..0547e2327 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -5,6 +5,7 @@ #include "ClipperUtils.hpp" #include "Extruder.hpp" #include "Flow.hpp" +#include "Fill/FillBase.hpp" #include "Geometry.hpp" #include "I18N.hpp" #include "ShortestPath.hpp" @@ -196,8 +197,11 @@ bool Print::invalidate_state_by_config_options(const std::vector &obj_group : obj_groups) { if (obj_group.front()->config().brim_ears.value == obj->config().brim_ears.value && obj_group.front()->config().brim_ears_max_angle.value == obj->config().brim_ears_max_angle.value + && obj_group.front()->config().brim_ears_pattern.value == obj->config().brim_ears_pattern.value && obj_group.front()->config().brim_inside_holes.value == obj->config().brim_inside_holes.value && obj_group.front()->config().brim_offset.value == obj->config().brim_offset.value && obj_group.front()->config().brim_width.value == obj->config().brim_width.value @@ -2281,61 +2286,102 @@ void Print::_make_brim_ears(const Flow &flow, const PrintObjectPtrs &objects, Ex brimmable_areas = diff_ex(brimmable_areas, unbrimmable, true); this->throw_if_canceled(); - //create loops (same as standard brim) - Polygons loops; - islands = offset_ex(islands, -0.5f * double(flow.scaled_spacing())); - for (size_t i = 0; i < num_loops; ++i) { - this->throw_if_canceled(); - islands = offset_ex(islands, double(flow.scaled_spacing()), jtSquare); - for (ExPolygon &expoly : islands) { - Polygon poly = expoly.contour; - poly.points.push_back(poly.points.front()); - Points p = MultiPoint::_douglas_peucker(poly.points, SCALED_RESOLUTION); - p.pop_back(); - poly.points = std::move(p); - loops.push_back(poly); + + if (brim_config.brim_ears_pattern.value == InfillPattern::ipConcentric) { + + //create loops (same as standard brim) + Polygons loops; + islands = offset_ex(islands, -0.5f * double(flow.scaled_spacing())); + for (size_t i = 0; i < num_loops; ++i) { + this->throw_if_canceled(); + islands = offset_ex(islands, double(flow.scaled_spacing()), jtSquare); + for (ExPolygon &expoly : islands) { + Polygon poly = expoly.contour; + poly.points.push_back(poly.points.front()); + Points p = MultiPoint::_douglas_peucker(poly.points, SCALED_RESOLUTION); + p.pop_back(); + poly.points = std::move(p); + loops.push_back(poly); + } } - } - //order path with least travel possible - loops = union_pt_chained(loops, false); + //order path with least travel possible + loops = union_pt_chained(loops, false); - //create ear pattern - coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing()); - Polygon point_round; - for (size_t i = 0; i < POLY_SIDES; i++) { - double angle = (2.0 * PI * i) / POLY_SIDES; - point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle)); + //create ear pattern + coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing()); + Polygon point_round; + for (size_t i = 0; i < POLY_SIDES; i++) { + double angle = (2.0 * PI * i) / POLY_SIDES; + point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle)); + } + + //create ears + Polygons mouse_ears; + ExPolygons mouse_ears_ex; + for (Point pt : pt_ears) { + mouse_ears.push_back(point_round); + mouse_ears.back().translate(pt); + mouse_ears_ex.emplace_back(); + mouse_ears_ex.back().contour = mouse_ears.back(); + } + + //intersection + Polylines lines = intersection_pl(loops, mouse_ears); + this->throw_if_canceled(); + + //reorder & extrude them + Polylines lines_sorted = _reorder_brim_polyline(lines, out, flow); + + //push into extrusions + extrusion_entities_append_paths( + out.entities, + lines_sorted, + erSkirt, + float(flow.mm3_per_mm()), + float(flow.width), + float(this->skirt_first_layer_height()) + ); + + ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex); + unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end()); + } else { + + + //create ear pattern + coord_t size_ear = (scale_((brim_config.brim_width.value - brim_config.brim_offset.value)) - flow.scaled_spacing()); + Polygon point_round; + for (size_t i = 0; i < POLY_SIDES; i++) { + double angle = (2.0 * PI * i) / POLY_SIDES; + point_round.points.emplace_back(size_ear * cos(angle), size_ear * sin(angle)); + } + + //create ears + ExPolygons mouse_ears_ex; + for (Point pt : pt_ears) { + mouse_ears_ex.emplace_back(); + mouse_ears_ex.back().contour = point_round; + mouse_ears_ex.back().contour.translate(pt); + } + + ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex); + + std::unique_ptr filler = std::unique_ptr(Fill::new_from_type(ipRectiWithPerimeter)); + filler->angle = 0; + + FillParams fill_params; + fill_params.density = 1.f; + fill_params.fill_exactly = true; + fill_params.flow = &flow; + fill_params.role = erSkirt; + filler->init_spacing(flow.spacing(), fill_params); + for (const ExPolygon &expoly : new_brim_area) { + Surface surface(stPosInternal | stDensSparse, expoly); + filler->fill_surface_extrusion(&surface, fill_params, out.entities); + } + + unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end()); } - //create ears - Polygons mouse_ears; - ExPolygons mouse_ears_ex; - for (Point pt : pt_ears) { - mouse_ears.push_back(point_round); - mouse_ears.back().translate(pt); - mouse_ears_ex.emplace_back(); - mouse_ears_ex.back().contour = mouse_ears.back(); - } - - //intersection - Polylines lines = intersection_pl(loops, mouse_ears); - this->throw_if_canceled(); - - //reorder & extrude them - Polylines lines_sorted = _reorder_brim_polyline(lines, out, flow); - - //push into extrusions - extrusion_entities_append_paths( - out.entities, - lines_sorted, - erSkirt, - float(flow.mm3_per_mm()), - float(flow.width), - float(this->skirt_first_layer_height()) - ); - - ExPolygons new_brim_area = intersection_ex(brimmable_areas, mouse_ears_ex); - unbrimmable.insert(unbrimmable.end(), new_brim_area.begin(), new_brim_area.end()); } void Print::_make_brim_interior(const Flow &flow, const PrintObjectPtrs &objects, ExPolygons &unbrimmable_areas, ExtrusionEntityCollection &out) { diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index c7f3b20ae..b784ff09b 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -352,6 +352,19 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(125)); + def = this->add("brim_ears_pattern", coEnum); + def->label = L("Pattern"); + def->full_label = L("Ear pattern"); + def->category = OptionCategory::infill; + def->tooltip = L("Pattern for the ear. The concentric id the default one." + " The rectilinear has a perimeter around it, you can try it if the concentric has too many problems to stick to the build plate."); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("concentric"); + def->enum_values.push_back("rectilinear"); + def->enum_labels.push_back(L("Concentric")); + def->enum_labels.push_back(L("Rectilinear")); + def->set_default_value(new ConfigOptionEnum(ipConcentric)); + def = this->add("brim_offset", coFloat); def->label = L("brim offset"); def->category = OptionCategory::skirtBrim; @@ -4736,6 +4749,10 @@ std::string FullPrintConfig::validate() if (!print_config_def.get("solid_fill_pattern")->has_enum_value(this->solid_fill_pattern.serialize())) return "Invalid value for --solid-fill-pattern"; + // --brim-ears-pattern + if (!print_config_def.get("brim_ears_pattern")->has_enum_value(this->brim_ears_pattern.serialize())) + return "Invalid value for --brim-ears-pattern"; + // --fill-density if (fabs(this->fill_density.value - 100.) < EPSILON && (! print_config_def.get("top_fill_pattern")->has_enum_value(this->fill_pattern.serialize()) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c0c45f873..8639bb68d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -490,6 +490,7 @@ public: ConfigOptionFloat brim_width_interior; ConfigOptionBool brim_ears; ConfigOptionFloat brim_ears_max_angle; + ConfigOptionEnum brim_ears_pattern; ConfigOptionFloat brim_offset; ConfigOptionBool clip_multipart_objects; ConfigOptionBool dont_support_bridges; @@ -555,6 +556,7 @@ protected: OPT_PTR(brim_width_interior); OPT_PTR(brim_ears); OPT_PTR(brim_ears_max_angle); + OPT_PTR(brim_ears_pattern); OPT_PTR(brim_offset); OPT_PTR(clip_multipart_objects); OPT_PTR(dont_support_bridges); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 0c0f2690f..5b80a3ee2 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -757,6 +757,15 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorinvalidate_step(psWipeTower); invalidated |= m_print->invalidate_step(psGCodeExport); + } else if ( + opt_key == "brim_inside_holes" + || opt_key == "brim_width" + || opt_key == "brim_width_interior" + || opt_key == "brim_offset" + || opt_key == "brim_ears" + || opt_key == "brim_ears_max_angle" + || opt_key == "brim_ears_pattern") { + invalidated |= m_print->invalidate_step(psBrim); } else { // for legacy, if we can't handle this option let's invalidate all steps this->invalidate_all_steps(); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index e159320b1..f64af515e 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -376,6 +376,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("brim_ears", config->opt_float("brim_width") > 0); toggle_field("brim_inside_holes", config->opt_float("brim_width") > 0 && config->opt_float("brim_width_interior") == 0); toggle_field("brim_ears_max_angle", have_brim && config->opt_bool("brim_ears")); + toggle_field("brim_ears_pattern", have_brim && config->opt_bool("brim_ears")); bool have_raft = config->opt_int("raft_layers") > 0; bool have_support_material = config->opt_bool("support_material") || have_raft; diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 462180bea..ef5be5877 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -986,7 +986,7 @@ void Choice::set_value(const boost::any& value, bool change_event) case coEnum: { int val = boost::any_cast(value); if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern" - || m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern") + || m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern" || m_opt_id == "brim_ears_pattern") { val = idx_from_enum_value(val); } else if (m_opt_id.compare("perimeter_loop_seam") == 0) { @@ -1073,7 +1073,7 @@ boost::any& Choice::get_value() { int ret_enum = field->GetSelection(); if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern" - || m_opt_id == "support_material_interface_pattern" || m_opt_id == "fill_pattern") + || m_opt_id == "support_material_interface_pattern" || m_opt_id == "fill_pattern" || m_opt_id == "brim_ears_pattern") convert_to_enum_value(ret_enum); else if (m_opt_id.compare("gcode_flavor") == 0) convert_to_enum_value(ret_enum); diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 8d634d0f6..d3449b835 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -187,7 +187,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt if (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "solid_fill_pattern" || - opt_key == "fill_pattern") + opt_key == "fill_pattern" || + opt_key == "brim_ears_pattern") config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); else if (opt_key.compare("complete_objects_sort") == 0) config.set_key_value(opt_key, new ConfigOptionEnum(boost::any_cast(value))); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 5b38b4f88..7d61d343c 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -746,7 +746,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config if (opt_key == "top_fill_pattern" || opt_key == "bottom_fill_pattern" || opt_key == "solid_fill_pattern" || - opt_key == "fill_pattern" ) { + opt_key == "fill_pattern" || + opt_key == "brim_ears_pattern" ) { ret = static_cast(config.option>(opt_key)->value); } else if (opt_key.compare("complete_objects_sort") == 0 ) { diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index d89f66843..664a21eaf 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -485,6 +485,7 @@ const std::vector& Preset::print_options() "brim_width_interior", "brim_ears", "brim_ears_max_angle", + "brim_ears_pattern", "brim_offset", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "support_material_pattern", "support_material_with_sheath", "support_material_spacing",