diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 622c612b8..e12aea65b 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -14,7 +14,6 @@ group:Horizontal shells setting:bottom_solid_min_thickness end_line top_bottom_shell_thickness_explanation - setting:solid_over_perimeters setting:enforce_full_fill_volume group:Quality line:Only one perimeter @@ -26,7 +25,10 @@ group:Quality setting:label_width$8:extra_perimeters_overhangs setting:label_width$10:extra_perimeters_odd_layers end_line - setting:ensure_vertical_shell_thickness + line:Ensure vertical shell thickness + setting:label$_:ensure_vertical_shell_thickness + setting:solid_over_perimeters + end_line line:Avoid crossing perimeters setting:label$_:avoid_crossing_perimeters setting:label_width$12:label$Not on first layer:avoid_crossing_not_first_layer diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 52a8612ef..1345ceaab 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -252,6 +252,7 @@ private: void clip_fill_surfaces(); void tag_under_bridge(); void discover_horizontal_shells(); + void clean_surfaces(); void combine_infill(); void _generate_support_material(); std::pair prepare_adaptive_infill_data(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 8d54b5caf..11468c959 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -763,7 +763,7 @@ void PrintConfigDef::init_fff_params() def->category = OptionCategory::perimeter; def->tooltip = L("Add solid infill near sloping surfaces to guarantee the vertical shell thickness " "(top+bottom solid layers)." - "\n!! solid_over_perimeters may erase these surfaces !! So you should deactivate it if you want to use this."); + "\n!! solid_over_perimeters may erase these surfaces !!"); def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); @@ -4022,7 +4022,7 @@ void PrintConfigDef::init_fff_params() " the top/bottom solid layer count, it won't do anything. If this setting is set to 1, it will evict " " all solid fill above/below perimeters. " "\nSet zero to disable." - "\n!! ensure_vertical_shell_thickness may be erased by this setting !!."); + "\n!! ensure_vertical_shell_thickness needs to be activated so this algorithm can work !!."); def->min = 0; def->mode = comAdvanced; def->set_default_value(new ConfigOptionInt(2)); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ffddc14ae..e40c31c63 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -490,10 +490,12 @@ namespace Slic3r { // to close these surfaces reliably. //FIXME Vojtech: Is this a good place to add supporting infills below sloping perimeters? //note: only if not "ensure vertical shell" - //TODO merill: as "ensure_vertical_shell_thickness" is innefective, this should be simplified / streamlined / deleted? this->discover_horizontal_shells(); m_print->throw_if_canceled(); + //as there is some too thin solid surface, please deleted them and merge all of the surfacesthat are contigous. + this->clean_surfaces(); + #ifdef SLIC3R_DEBUG_SLICE_PROCESSING for (size_t region_id = 0; region_id < this->region_volumes.size(); ++region_id) { for (const Layer* layer : m_layers) { @@ -3748,6 +3750,65 @@ static void fix_mesh_connectivity(TriangleMesh &mesh) #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ } + void merge_surfaces(LayerRegion* lregion) { + //merge regions with same type (other things are all the same anyway) + std::map< SurfaceType, std::vector< Surface*>> type2srfs; + for (Surface& surface : lregion->fill_surfaces.surfaces) { + type2srfs[surface.surface_type].push_back(&surface); + } + bool changed = false; + std::map< SurfaceType, ExPolygons> type2newpolys; + for (auto& entry : type2srfs) { + if (entry.second.size() > 2) { + ExPolygons merged = union_ex(to_expolygons(entry.second), true); + if (merged.size() < entry.second.size()) { + changed = true; + type2newpolys[entry.first] = std::move(merged); + } + } + } + if (changed) { + Surfaces newSrfs; + for (auto& entry : type2srfs) { + if (type2newpolys.find(entry.first) == type2newpolys.end()) { + for (Surface* srfPtr : entry.second) { + newSrfs.emplace_back(*srfPtr); + } + } else { + for (ExPolygon& expoly : type2newpolys[entry.first]) { + newSrfs.emplace_back(*entry.second.front(), expoly); + } + } + } + lregion->fill_surfaces.surfaces = std::move(newSrfs); + } + } + + void PrintObject::clean_surfaces() { + tbb::parallel_for(tbb::blocked_range(0, this->layers().size() - 1), + [this](const tbb::blocked_range& range) { + for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) { + for (LayerRegion* lregion : this->layers()[idx_layer]->regions()) { + coord_t extrusion_width = lregion->flow(frInfill).scaled_width(); + merge_surfaces(lregion); + // collapse too thin solid surfaces. + bool changed_type = false; + for (Surface& surface : lregion->fill_surfaces.surfaces) { + if (surface.has_fill_solid() && surface.has_pos_internal()) { + if (offset2_ex(surface.expolygon, -extrusion_width / 2, extrusion_width / 2).empty()) { + //convert to sparse + surface.surface_type = (surface.surface_type ^ SurfaceType::stDensSolid) | SurfaceType::stDensSparse; + changed_type = true; + } + } + } + merge_surfaces(lregion); + + } + } + }); + + } // combine fill surfaces across layers to honor the "infill every N layers" option // Idempotence of this method is guaranteed by the fact that we don't remove things from // fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries. diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index 09d935f58..4e57a63c5 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -35,7 +35,10 @@ inline SurfaceType operator|(SurfaceType a, SurfaceType b) { return static_cast(static_cast(a) | static_cast(b)); } inline SurfaceType operator&(SurfaceType a, SurfaceType b) { - return static_cast(static_cast(a)& static_cast(b)); + return static_cast(static_cast(a) & static_cast(b)); +} +inline SurfaceType operator^(SurfaceType a, SurfaceType b) { + return static_cast(static_cast(a) ^ static_cast(b)); } inline SurfaceType operator|=(SurfaceType& a, SurfaceType b) { a = a | b; return a;