Fix phantom solid surfaces.

move solid_over_perimeters (as it only works with ensure_vertical_shell_thickness activated)
TODO: maybe try to not create too thin solid surfaces in the first place? and really merge same surfaces?
This commit is contained in:
supermerill 2022-02-01 22:38:06 +01:00
parent 994997ab90
commit 878ea577c7
5 changed files with 73 additions and 6 deletions

View File

@ -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

View File

@ -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<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> prepare_adaptive_infill_data();

View File

@ -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));

View File

@ -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<size_t>(0, this->layers().size() - 1),
[this](const tbb::blocked_range<size_t>& 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.

View File

@ -35,7 +35,10 @@ inline SurfaceType operator|(SurfaceType a, SurfaceType b) {
return static_cast<SurfaceType>(static_cast<uint16_t>(a) | static_cast<uint16_t>(b));
}
inline SurfaceType operator&(SurfaceType a, SurfaceType b) {
return static_cast<SurfaceType>(static_cast<uint16_t>(a)& static_cast<uint16_t>(b));
return static_cast<SurfaceType>(static_cast<uint16_t>(a) & static_cast<uint16_t>(b));
}
inline SurfaceType operator^(SurfaceType a, SurfaceType b) {
return static_cast<SurfaceType>(static_cast<uint16_t>(a) ^ static_cast<uint16_t>(b));
}
inline SurfaceType operator|=(SurfaceType& a, SurfaceType b) {
a = a | b; return a;