Fix of weird double extrusions with multiple regions and their

parameters being changed between slicing runs.
This commit is contained in:
bubnikv 2020-03-20 13:37:13 +01:00
parent 38d06d57a0
commit a9fc39491e

View file

@ -112,72 +112,82 @@ void Layer::make_perimeters()
// keep track of regions whose perimeters we have already generated // keep track of regions whose perimeters we have already generated
std::vector<unsigned char> done(m_regions.size(), false); std::vector<unsigned char> done(m_regions.size(), false);
for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) { for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm)
size_t region_id = layerm - m_regions.begin(); if ((*layerm)->slices.empty()) {
if (done[region_id]) (*layerm)->perimeters.clear();
continue; (*layerm)->fills.clear();
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id; (*layerm)->thin_fills.clear();
done[region_id] = true; } else {
const PrintRegionConfig &config = (*layerm)->region()->config(); size_t region_id = layerm - m_regions.begin();
if (done[region_id])
continue;
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
done[region_id] = true;
const PrintRegionConfig &config = (*layerm)->region()->config();
// find compatible regions // find compatible regions
LayerRegionPtrs layerms; LayerRegionPtrs layerms;
layerms.push_back(*layerm); layerms.push_back(*layerm);
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) { for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it)
LayerRegion* other_layerm = *it; if (! (*it)->slices.empty()) {
const PrintRegionConfig &other_config = other_layerm->region()->config(); LayerRegion* other_layerm = *it;
if (config.perimeter_extruder == other_config.perimeter_extruder const PrintRegionConfig &other_config = other_layerm->region()->config();
&& config.perimeters == other_config.perimeters if (config.perimeter_extruder == other_config.perimeter_extruder
&& config.perimeter_speed == other_config.perimeter_speed && config.perimeters == other_config.perimeters
&& config.external_perimeter_speed == other_config.external_perimeter_speed && config.perimeter_speed == other_config.perimeter_speed
&& config.gap_fill_speed == other_config.gap_fill_speed && config.external_perimeter_speed == other_config.external_perimeter_speed
&& config.overhangs == other_config.overhangs && config.gap_fill_speed == other_config.gap_fill_speed
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width") && config.overhangs == other_config.overhangs
&& config.thin_walls == other_config.thin_walls && config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
&& config.external_perimeters_first == other_config.external_perimeters_first && config.thin_walls == other_config.thin_walls
&& config.infill_overlap == other_config.infill_overlap) { && config.external_perimeters_first == other_config.external_perimeters_first
layerms.push_back(other_layerm); && config.infill_overlap == other_config.infill_overlap)
done[it - m_regions.begin()] = true; {
} other_layerm->perimeters.clear();
} other_layerm->fills.clear();
other_layerm->thin_fills.clear();
layerms.push_back(other_layerm);
done[it - m_regions.begin()] = true;
}
}
if (layerms.size() == 1) { // optimization if (layerms.size() == 1) { // optimization
(*layerm)->fill_surfaces.surfaces.clear(); (*layerm)->fill_surfaces.surfaces.clear();
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces); (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces); (*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
} else { } else {
SurfaceCollection new_slices; SurfaceCollection new_slices;
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence. // Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence.
LayerRegion *layerm_config = layerms.front(); LayerRegion *layerm_config = layerms.front();
{ {
// group slices (surfaces) according to number of extra perimeters // group slices (surfaces) according to number of extra perimeters
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ] std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
for (LayerRegion *layerm : layerms) { for (LayerRegion *layerm : layerms) {
for (Surface &surface : layerm->slices.surfaces) for (Surface &surface : layerm->slices.surfaces)
slices[surface.extra_perimeters].emplace_back(surface); slices[surface.extra_perimeters].emplace_back(surface);
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density) if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
layerm_config = layerm; layerm_config = layerm;
} }
// merge the surfaces assigned to each group // merge the surfaces assigned to each group
for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices) for (std::pair<const unsigned short,Surfaces> &surfaces_with_extra_perimeters : slices)
new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front()); new_slices.append(union_ex(surfaces_with_extra_perimeters.second, true), surfaces_with_extra_perimeters.second.front());
} }
// make perimeters // make perimeters
SurfaceCollection fill_surfaces; SurfaceCollection fill_surfaces;
layerm_config->make_perimeters(new_slices, &fill_surfaces); layerm_config->make_perimeters(new_slices, &fill_surfaces);
// assign fill_surfaces to each layer // assign fill_surfaces to each layer
if (!fill_surfaces.surfaces.empty()) { if (!fill_surfaces.surfaces.empty()) {
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
// Separate the fill surfaces. // Separate the fill surfaces.
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices); ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
(*l)->fill_expolygons = expp; (*l)->fill_expolygons = expp;
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front()); (*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
} }
} }
} }
} }
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done"; BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done";
} }