From 0af53949eb9f96077c7326cb05590f2718958462 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 26 Sep 2018 12:37:33 +0200 Subject: [PATCH 1/4] Update on infill api. --- xs/src/libslic3r/Fill/Fill.cpp | 2 +- xs/src/libslic3r/Fill/FillBase.cpp | 22 ++++++++----- xs/src/libslic3r/Fill/FillBase.hpp | 4 ++- xs/src/libslic3r/Fill/FillRectilinear2.cpp | 36 +++++++++++++--------- xs/src/libslic3r/Fill/FillRectilinear2.hpp | 3 +- xs/src/libslic3r/Fill/FillSmooth.cpp | 27 ++++++++++++---- xs/src/libslic3r/Fill/FillSmooth.hpp | 3 +- 7 files changed, 65 insertions(+), 32 deletions(-) diff --git a/xs/src/libslic3r/Fill/Fill.cpp b/xs/src/libslic3r/Fill/Fill.cpp index 40e87cbe4..0158221af 100644 --- a/xs/src/libslic3r/Fill/Fill.cpp +++ b/xs/src/libslic3r/Fill/Fill.cpp @@ -296,7 +296,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out) //params.flow_mult = layerm.region()->config.over_bridge_flow_ratio; } - f->fill_surface_extrusion(&surface, params, flow, out); + f->fill_surface_extrusion(&surface, params, flow, erNone, out.entities); } // add thin fill regions diff --git a/xs/src/libslic3r/Fill/FillBase.cpp b/xs/src/libslic3r/Fill/FillBase.cpp index f8647a0b0..e1eae0244 100644 --- a/xs/src/libslic3r/Fill/FillBase.cpp +++ b/xs/src/libslic3r/Fill/FillBase.cpp @@ -136,7 +136,7 @@ std::pair Fill::_infill_direction(const Surface *surface) const return std::pair(out_angle, out_shift); } -void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out) { +void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) { //add overlap & call fill_surface Polylines polylines = this->fill_surface(surface, params); if (polylines.empty()) @@ -184,16 +184,22 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ /// pass the no_sort attribute to the extrusion path eec->no_sort = this->no_sort(); /// add it into the collection - out.entities.push_back(eec); + out.push_back(eec); + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = (flow.bridge ? erBridgeInfill : + (surface->is_solid() ? + ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : + erInternalInfill)); + } /// push the path extrusion_entities_append_paths( eec->entities, STDMOVE(polylines), - flow.bridge ? - erBridgeInfill : - (surface->is_solid() ? - ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : - erInternalInfill), - flow.mm3_per_mm() * params.flow_mult * multFlow, flow.width * params.flow_mult * multFlow, flow.height); + good_role, + flow.mm3_per_mm() * params.flow_mult * multFlow, + flow.width * params.flow_mult * multFlow, + flow.height); } diff --git a/xs/src/libslic3r/Fill/FillBase.hpp b/xs/src/libslic3r/Fill/FillBase.hpp index e569a4773..79a43a821 100644 --- a/xs/src/libslic3r/Fill/FillBase.hpp +++ b/xs/src/libslic3r/Fill/FillBase.hpp @@ -86,7 +86,9 @@ public: virtual bool no_sort() const { return false; } // This method have to fill the ExtrusionEntityCollection. It call fill_surface by default - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out ); + // if role == erNone or ERCustom, this method have to choose the best role itself, else it must use the argument's role. + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, + const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); // Perform the fill. virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index 3d4186aac..5d56885c0 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -1476,7 +1476,10 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶ //Polylines FillRectilinear2Peri::fill_surface(const Surface *surface, const FillParams ¶ms) { -void FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out) { +void +FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, + const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) +{ ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection(); //you don't want to sort the extrusions: big infill first, small second eecroot->no_sort = true; @@ -1500,15 +1503,22 @@ void FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const eec->no_sort = this->no_sort(); /// add it into the collection eecroot->entities.push_back(eec); + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = flow.bridge ? + erBridgeInfill : + (surface->is_solid() ? + ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : + erInternalInfill); + } /// push the path extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_1), - flow.bridge ? - erBridgeInfill : - (surface->is_solid() ? - ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : - erInternalInfill), - flow.mm3_per_mm() * params.flow_mult, flow.width * params.flow_mult, flow.height); + good_role, + flow.mm3_per_mm() * params.flow_mult, + flow.width * params.flow_mult, + flow.height); Polylines polylines_2; //50% overlap with the new perimeter @@ -1528,14 +1538,12 @@ void FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const /// push the path extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_2), - flow.bridge ? - erBridgeInfill : - (surface->is_solid() ? - ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : - erInternalInfill), - flow.mm3_per_mm() * params.flow_mult, flow.width * params.flow_mult, flow.height); + good_role, + flow.mm3_per_mm() * params.flow_mult, + flow.width * params.flow_mult, + flow.height); - out.entities.push_back(eecroot); + out.push_back(eecroot); } } // namespace Slic3r diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.hpp b/xs/src/libslic3r/Fill/FillRectilinear2.hpp index 53621d139..3457fad95 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.hpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.hpp @@ -76,7 +76,8 @@ public: virtual Fill* clone() const { return new FillRectilinear2Peri(*this); }; virtual ~FillRectilinear2Peri() {} //virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out); + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, + const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); }; diff --git a/xs/src/libslic3r/Fill/FillSmooth.cpp b/xs/src/libslic3r/Fill/FillSmooth.cpp index 59e63c792..7168c5882 100644 --- a/xs/src/libslic3r/Fill/FillSmooth.cpp +++ b/xs/src/libslic3r/Fill/FillSmooth.cpp @@ -19,7 +19,8 @@ namespace Slic3r { } - void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out) + void FillSmooth::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, + const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) { coordf_t init_spacing = this->spacing; @@ -142,9 +143,14 @@ namespace Slic3r { eec = new ExtrusionEntityCollection(); eecroot->entities.push_back(eec); eec->no_sort = false; //can be sorted inside the pass + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = flow.bridge ? erBridgeInfill : rolePass[0]; + } extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_layer1), - flow.bridge ? erBridgeInfill : rolePass[0], + good_role, //reduced flow height for a better view (it's only a gui thing) params.flow_mult * flow.mm3_per_mm() * percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1), (float)(flow.width*percentFlow[0] * (params.fill_exactly ? poylineVolume / extrudedVolume : 1)), (float)flow.height*0.8); @@ -192,11 +198,15 @@ namespace Slic3r { eec = new ExtrusionEntityCollection(); eecroot->entities.push_back(eec); eec->no_sort = false; + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = rolePass[1]; + } // print thin - extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_layer2), - rolePass[1], + good_role, params.flow_mult * flow.mm3_per_mm() * percentFlow[1] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), //min-reduced flow width for a better view (it's only a gui thing) (float)(flow.width*(percentFlow[1] < 0.1 ? 0.1 : percentFlow[1])), (float)flow.height); @@ -244,10 +254,15 @@ namespace Slic3r { eec = new ExtrusionEntityCollection(); eecroot->entities.push_back(eec); eec->no_sort = false; + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = rolePass[2]; + } // print thin extrusion_entities_append_paths( eec->entities, STDMOVE(polylines_layer3), - rolePass[2], //slow (if last) + good_role, //slow (if last) //reduced flow width for a better view (it's only a gui thing) params.flow_mult * flow.mm3_per_mm() * percentFlow[2] * (params.fill_exactly ? volumeToOccupy / extrudedVolume : 1), (float)(flow.width*(percentFlow[2] < 0.1 ? 0.1 : percentFlow[2])), (float)flow.height); @@ -255,7 +270,7 @@ namespace Slic3r { } if (!eecroot->entities.empty()) - out.entities.push_back(eecroot); + out.push_back(eecroot); } diff --git a/xs/src/libslic3r/Fill/FillSmooth.hpp b/xs/src/libslic3r/Fill/FillSmooth.hpp index 3e9300a8f..eb558f088 100644 --- a/xs/src/libslic3r/Fill/FillSmooth.hpp +++ b/xs/src/libslic3r/Fill/FillSmooth.hpp @@ -35,7 +35,8 @@ public: virtual Fill* clone() const { return new FillSmooth(*this); } virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms); - virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, ExtrusionEntityCollection &out ); + virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, + const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out); protected: int nbPass=2; From 389d3ee4d57d55bc65f2bbeb07ec89ed35618fcc Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 26 Sep 2018 15:03:56 +0200 Subject: [PATCH 2/4] Supports on the build plate can have a solid bottom interface for better adhesion: #1165 --- xs/src/libslic3r/GCode.cpp | 4 ++ xs/src/libslic3r/PrintConfig.cpp | 9 +++- xs/src/libslic3r/PrintConfig.hpp | 2 + xs/src/libslic3r/PrintObject.cpp | 3 +- xs/src/libslic3r/SupportMaterial.cpp | 72 +++++++++++++++++----------- xs/src/slic3r/GUI/Preset.cpp | 2 +- xs/src/slic3r/GUI/Tab.cpp | 5 +- 7 files changed, 64 insertions(+), 33 deletions(-) diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 62563ef25..27c838037 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -2241,6 +2241,10 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill for (const ExtrusionEntity *ee : support_fills.entities) { ExtrusionRole role = ee->role(); assert(role == erSupportMaterial || role == erSupportMaterialInterface); + if (const ExtrusionEntityCollection* coll = dynamic_cast(ee)) { + gcode += extrude_support(*coll); + continue; + } const char *label = (role == erSupportMaterial) ? support_label : support_interface_label; const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed; const ExtrusionPath *path = dynamic_cast(ee); diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 479fa6cd6..b23ad421e 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1439,11 +1439,18 @@ PrintConfigDef::PrintConfigDef() def = this->add("printer_settings_id", coString); def->default_value = new ConfigOptionString(""); + def = this->add("support_material_solid_first_layer", coBool); + def->label = L("Solid first layer"); + def->category = L("Support material"); + def->tooltip = L("Use a solid layer instead of a raft for the layer that touch the build plate."); + def->cli = "support-material-solid-first-layer!"; + def->default_value = new ConfigOptionBool(false); + def = this->add("raft_layers", coInt); def->label = L("Raft layers"); def->category = L("Support material"); def->tooltip = L("The object will be raised by this number of layers, and support material " - "will be generated under it."); + "will be generated under it."); def->sidetext = L("layers"); def->cli = "raft-layers=i"; def->min = 0; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 837c4f682..01e5a6fe7 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -349,6 +349,7 @@ public: ConfigOptionEnum support_material_pattern; ConfigOptionFloat support_material_spacing; ConfigOptionFloat support_material_speed; + ConfigOptionBool support_material_solid_first_layer; ConfigOptionBool support_material_synchronize_layers; ConfigOptionInt support_material_threshold; ConfigOptionBool support_material_with_sheath; @@ -387,6 +388,7 @@ protected: OPT_PTR(support_material_pattern); OPT_PTR(support_material_spacing); OPT_PTR(support_material_speed); + OPT_PTR(support_material_solid_first_layer); OPT_PTR(support_material_synchronize_layers); OPT_PTR(support_material_xy_spacing); OPT_PTR(support_material_threshold); diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 91baa3392..f23af7bb2 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -194,7 +194,8 @@ bool PrintObject::invalidate_state_by_config_options(const std::vectorfill_surface(&surface, fill_params), - role, - flow.mm3_per_mm(), flow.width, flow.height); + filler->fill_surface_extrusion(&surface, fill_params, flow, role, dst); } } @@ -1889,13 +1885,9 @@ static inline void fill_expolygons_generate_paths( fill_params.density = density; fill_params.complete = true; fill_params.dont_adjust = true; - for (ExPolygons::iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++ it_expolygon) { + for (ExPolygons::iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++it_expolygon) { Surface surface(stInternal, std::move(*it_expolygon)); - extrusion_entities_append_paths( - dst, - filler->fill_surface(&surface, fill_params), - role, - flow.mm3_per_mm(), flow.width, flow.height); + filler->fill_surface_extrusion(&surface, fill_params, flow, role, dst); } } @@ -2546,7 +2538,8 @@ void PrintObjectSupportMaterial::generate_toolpaths( MyLayer &raft_layer = *raft_layers[support_layer_id]; std::unique_ptr filler_interface = std::unique_ptr(Fill::new_from_type(ipRectilinear)); - std::unique_ptr filler_support = std::unique_ptr(Fill::new_from_type(infill_pattern)); + std::unique_ptr filler_support = std::unique_ptr(Fill::new_from_type(infill_pattern)); + std::unique_ptr filler_dense = std::unique_ptr(Fill::new_from_type(ipRectiWithPerimeter)); filler_interface->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object); @@ -2577,7 +2570,7 @@ void PrintObjectSupportMaterial::generate_toolpaths( if (! to_infill.empty()) { // We don't use $base_flow->spacing because we need a constant spacing // value that guarantees that all layers are correctly aligned. - Fill *filler = filler_support.get(); + Fill *filler = filler_support.get(); filler->angle = raft_angle_base; filler->spacing = m_support_material_flow.spacing(); filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / support_density)); @@ -2599,10 +2592,16 @@ void PrintObjectSupportMaterial::generate_toolpaths( float density = 0.f; if (support_layer_id == 0) { // Base flange. - filler->angle = raft_angle_1st_layer; + if (this->m_object_config->support_material_solid_first_layer.value) { + filler = filler_dense.get(); + density = 1.f; + filler->angle = 0; + } else { + filler->angle = raft_angle_1st_layer; + // 70% of density on the 1st layer. + density = 0.7f; + } filler->spacing = m_first_layer_flow.spacing(); - // 70% of density on the 1st layer. - density = 0.7f; } else if (support_layer_id >= m_slicing_params.base_raft_layers) { filler->angle = raft_angle_interface; // We don't use $base_flow->spacing because we need a constant spacing @@ -2649,7 +2648,8 @@ void PrintObjectSupportMaterial::generate_toolpaths( size_t idx_layer_intermediate = size_t(-1); size_t idx_layer_inteface = size_t(-1); std::unique_ptr filler_interface = std::unique_ptr(Fill::new_from_type(m_slicing_params.soluble_interface ? ipConcentric : ipRectilinear)); - std::unique_ptr filler_support = std::unique_ptr(Fill::new_from_type(infill_pattern)); + std::unique_ptr filler_support = std::unique_ptr(Fill::new_from_type(infill_pattern)); + std::unique_ptr filler_solid = std::unique_ptr(Fill::new_from_type(ipRectiWithPerimeter)); filler_interface->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object); for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) @@ -2722,20 +2722,31 @@ void PrintObjectSupportMaterial::generate_toolpaths( float(layer_ex.layer->height), m_support_material_interface_flow.nozzle_diameter, layer_ex.layer->bridging); - filler_interface->angle = interface_as_base ? + Fill *filler = filler_interface.get(); + float density = interface_density; + //if first alyer and solid first layer : draw concentric with 100% density + if (support_layer.id() == 0 && this->m_object_config->support_material_solid_first_layer.value) { + filler = filler_solid.get(); + density = 1.f; + interface_flow = m_first_layer_flow; + filler->angle = 0; + filler->spacing = interface_flow.spacing(); + } else { + filler->angle = interface_as_base ? // If zero interface layers are configured, use the same angle as for the base layers. angles[support_layer_id % angles.size()] : // Use interface angle for the interface layers. interface_angle; - filler_interface->spacing = m_support_material_interface_flow.spacing(); - filler_interface->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / interface_density)); + filler->spacing = m_support_material_interface_flow.spacing(); + filler->link_max_length = coord_t(scale_(filler_interface->spacing * link_max_length_factor / density)); + } fill_expolygons_generate_paths( // Destination layer_ex.extrusions, // Regions to fill union_ex(layer_ex.polygons_to_extrude(), true), // Filler and its parameters - filler_interface.get(), float(interface_density), + filler, float(density), // Extrusion parameters erSupportMaterialInterface, interface_flow); } @@ -2761,16 +2772,21 @@ void PrintObjectSupportMaterial::generate_toolpaths( offset2_ex(base_layer.polygons_to_extrude(), float(SCALED_EPSILON), float(- SCALED_EPSILON)) : offset2_ex(base_layer.polygons_to_extrude(), float(SCALED_EPSILON), float(- SCALED_EPSILON - 0.5*flow.scaled_width())); if (base_layer.layer->bottom_z < EPSILON) { - // Base flange (the 1st layer). - filler = filler_interface.get(); - filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.)); - density = 0.5f; - flow = m_first_layer_flow; + if (this->m_object_config->support_material_solid_first_layer.value) { + // Base flange (the 1st layer). + filler = filler_solid.get(); + filler->angle = 0; + density = 1.f; + } else { + filler = filler_interface.get(); + filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.)); + density = 0.5f; + filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density)); + } // use the proper spacing for first layer as we don't need to align // its pattern to the other layers - //FIXME When paralellizing, each thread shall have its own copy of the fillers. + flow = m_first_layer_flow; filler->spacing = flow.spacing(); - filler->link_max_length = coord_t(scale_(filler->spacing * link_max_length_factor / density)); } else if (with_sheath) { // Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove. // TODO: use brim ordering algorithm diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index b68223b38..0b195d367 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -306,7 +306,7 @@ const std::vector& Preset::print_options() "elefant_foot_compensation", "xy_size_compensation", "hole_size_compensation", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "only_one_perimeter_top", "single_extruder_multi_material_priming", "compatible_printers", "compatible_printers_condition", "inherits", - "infill_dense", "no_perimeter_unsupported", "min_perimeter_unsupported", "noperi_bridge_only" + "infill_dense", "no_perimeter_unsupported", "min_perimeter_unsupported", "noperi_bridge_only", "support_material_solid_first_layer" }; return s_opts; } diff --git a/xs/src/slic3r/GUI/Tab.cpp b/xs/src/slic3r/GUI/Tab.cpp index 72958d610..fd5674ff6 100644 --- a/xs/src/slic3r/GUI/Tab.cpp +++ b/xs/src/slic3r/GUI/Tab.cpp @@ -863,8 +863,9 @@ void TabPrint::build() optgroup->append_single_option_line("support_material_threshold"); optgroup->append_single_option_line("support_material_enforce_layers"); - optgroup = page->new_optgroup(_(L("Raft"))); - optgroup->append_single_option_line("raft_layers"); + optgroup = page->new_optgroup(_(L("Raft"))); + optgroup->append_single_option_line("support_material_solid_first_layer"); + optgroup->append_single_option_line("raft_layers"); // # optgroup->append_single_option_line(get_option_("raft_contact_distance"); optgroup = page->new_optgroup(_(L("Options for support material and raft"))); From 76b6f9a12be280042b3e14bfb8ed09086c60c8da Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 26 Sep 2018 16:52:50 +0200 Subject: [PATCH 3/4] optimisation/fix for FillRectilinear2Peri --- xs/src/libslic3r/Fill/FillRectilinear2.cpp | 101 +++++++++++++-------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp index 5d56885c0..be1c218ee 100644 --- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp +++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp @@ -1474,8 +1474,6 @@ Polylines FillCubic::fill_surface(const Surface *surface, const FillParams ¶ } -//Polylines FillRectilinear2Peri::fill_surface(const Surface *surface, const FillParams ¶ms) { - void FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, const Flow &flow, const ExtrusionRole &role, ExtrusionEntitiesPtr &out) @@ -1484,10 +1482,10 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP //you don't want to sort the extrusions: big infill first, small second eecroot->no_sort = true; + // === extrude perimeter === Polylines polylines_1; //generate perimeter: - //TODO: better optimize start/end point? - ExPolygons path_perimeter = offset_ex(surface->expolygon, scale_(-this->spacing/2)); + ExPolygons path_perimeter = offset2_ex(surface->expolygon, scale_(-this->spacing), scale_(this->spacing / 2)); for (ExPolygon &expolygon : path_perimeter) { expolygon.contour.make_counter_clockwise(); polylines_1.push_back(expolygon.contour.split_at_index(0)); @@ -1497,53 +1495,78 @@ FillRectilinear2Peri::fill_surface_extrusion(const Surface *surface, const FillP } } - // Save into layer. - auto *eec = new ExtrusionEntityCollection(); - /// pass the no_sort attribute to the extrusion path - eec->no_sort = this->no_sort(); - /// add it into the collection - eecroot->entities.push_back(eec); - //get the role - ExtrusionRole good_role = role; - if (good_role == erNone || good_role == erCustom) { - good_role = flow.bridge ? - erBridgeInfill : - (surface->is_solid() ? - ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : - erInternalInfill); + if (!polylines_1.empty()) { + // Save into layer. + ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); + /// pass the no_sort attribute to the extrusion path + eec->no_sort = this->no_sort(); + /// add it into the collection + eecroot->entities.push_back(eec); + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = flow.bridge ? + erBridgeInfill : + (surface->is_solid() ? + ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : + erInternalInfill); + } + /// push the path + extrusion_entities_append_paths( + eec->entities, + polylines_1, + good_role, + flow.mm3_per_mm() * params.flow_mult, + flow.width * params.flow_mult, + flow.height); } - /// push the path - extrusion_entities_append_paths( - eec->entities, STDMOVE(polylines_1), - good_role, - flow.mm3_per_mm() * params.flow_mult, - flow.width * params.flow_mult, - flow.height); + + // === extrude dense infill === Polylines polylines_2; + bool canFill = true; //50% overlap with the new perimeter ExPolygons path_inner = offset2_ex(surface->expolygon, scale_(-this->spacing * 1.5), scale_(this->spacing)); for (ExPolygon &expolygon : path_inner) { Surface surfInner(*surface, expolygon); if (!fill_surface_by_lines(&surfInner, params, 0.f, 0.f, polylines_2)) { printf("FillRectilinear2::fill_surface() failed to fill a region.\n"); + canFill = false; } } - // Save into layer. - eec = new ExtrusionEntityCollection(); - /// pass the no_sort attribute to the extrusion path - eec->no_sort = this->no_sort(); - /// add it into the collection - eecroot->entities.push_back(eec); - /// push the path - extrusion_entities_append_paths( - eec->entities, STDMOVE(polylines_2), - good_role, - flow.mm3_per_mm() * params.flow_mult, - flow.width * params.flow_mult, - flow.height); + if (canFill && !polylines_2.empty()) { + // Save into layer. + ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); + /// pass the no_sort attribute to the extrusion path + eec->no_sort = this->no_sort(); + /// add it into the collection + eecroot->entities.push_back(eec); + //get the role + ExtrusionRole good_role = role; + if (good_role == erNone || good_role == erCustom) { + good_role = flow.bridge ? + erBridgeInfill : + (surface->is_solid() ? + ((surface->is_top()) ? erTopSolidInfill : erSolidInfill) : + erInternalInfill); + } + /// push the path + extrusion_entities_append_paths( + eec->entities, + polylines_2, + good_role, + flow.mm3_per_mm() * params.flow_mult, + flow.width * params.flow_mult, + flow.height); + } + + // === end === + if (!eecroot->empty()) { + out.push_back(eecroot); + } else { + delete eecroot; + } - out.push_back(eecroot); } } // namespace Slic3r From a383f89a7d7121073690beab9bab36f0ac578d29 Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 26 Sep 2018 16:47:55 +0200 Subject: [PATCH 4/4] bridge fix with no infill: prusa3d/Slic3r#1185 slic3r/Slic3r#4533 supermerill/Slic3r#1 --- xs/src/libslic3r/LayerRegion.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/xs/src/libslic3r/LayerRegion.cpp b/xs/src/libslic3r/LayerRegion.cpp index a409f3885..aee94ab17 100644 --- a/xs/src/libslic3r/LayerRegion.cpp +++ b/xs/src/libslic3r/LayerRegion.cpp @@ -95,9 +95,18 @@ LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* void LayerRegion::process_external_surfaces(const Layer* lower_layer) { const Surfaces &surfaces = this->fill_surfaces.surfaces; - const double margin = scale_(this->region()->config.external_infill_margin.getFloat()); - const double margin_bridged = scale_(this->region()->config.bridged_infill_margin.getFloat()); - + const bool has_infill = this->region()->config.fill_density.value > 0.; + coord_t margin = scale_(this->region()->config.external_infill_margin.getFloat()); + coord_t margin_bridged = scale_(this->region()->config.bridged_infill_margin.getFloat()); + //if no infill, reduce the margin for averythign to only the perimeter + if (!has_infill) { + if ((this->region()->config.perimeters.value > 0)) { + const coord_t perimeter_width = scale_(this->region()->config.perimeter_extrusion_width.get_abs_value(this->layer()->object()->config.layer_height.value)); + const coord_t first_perimeter_width = scale_(this->region()->config.external_perimeter_extrusion_width.get_abs_value(this->layer()->object()->config.layer_height.value)); + margin = first_perimeter_width + perimeter_width * (this->region()->config.perimeters.value - 1); + } else margin = 0; + margin_bridged = margin; + } #ifdef SLIC3R_DEBUG_SLICE_PROCESSING export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-initial"); #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ @@ -122,7 +131,6 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer) { // bottom_polygons are used to trim inflated top surfaces. fill_boundaries.reserve(number_polygons(surfaces)); - bool has_infill = this->region()->config.fill_density.value > 0.; for (const Surface &surface : this->fill_surfaces.surfaces) { if (surface.is_top()) { // Collect the top surfaces, inflate them and trim them by the bottom surfaces. @@ -140,8 +148,15 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer) // Make a copy as the following line uses the move semantics. internal.push_back(surface); polygons_append(fill_boundaries, STDMOVE(surface.expolygon)); - } else if (!surface.is_external()) - internal.push_back(STDMOVE(surface)); + } else{ + if (!surface.is_external()) + internal.push_back(STDMOVE(surface)); + //push surface as perimeter-only inside the fill_boundaries + if (margin_bridged > 0) { + ExPolygons peri_poly = diff_ex(ExPolygons() = { surface.expolygon }, offset_ex(surface.expolygon, -margin_bridged)); + polygons_append(fill_boundaries, peri_poly); + } + } } }