From 389d3ee4d57d55bc65f2bbeb07ec89ed35618fcc Mon Sep 17 00:00:00 2001 From: supermerill Date: Wed, 26 Sep 2018 15:03:56 +0200 Subject: [PATCH] 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")));