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])
// find compatible regions continue;
LayerRegionPtrs layerms; BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
layerms.push_back(*layerm); done[region_id] = true;
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) { const PrintRegionConfig &config = (*layerm)->region()->config();
LayerRegion* other_layerm = *it;
const PrintRegionConfig &other_config = other_layerm->region()->config(); // find compatible regions
if (config.perimeter_extruder == other_config.perimeter_extruder LayerRegionPtrs layerms;
&& config.perimeters == other_config.perimeters layerms.push_back(*layerm);
&& config.perimeter_speed == other_config.perimeter_speed for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it)
&& config.external_perimeter_speed == other_config.external_perimeter_speed if (! (*it)->slices.empty()) {
&& config.gap_fill_speed == other_config.gap_fill_speed LayerRegion* other_layerm = *it;
&& config.overhangs == other_config.overhangs const PrintRegionConfig &other_config = other_layerm->region()->config();
&& config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width") if (config.perimeter_extruder == other_config.perimeter_extruder
&& config.thin_walls == other_config.thin_walls && config.perimeters == other_config.perimeters
&& config.external_perimeters_first == other_config.external_perimeters_first && config.perimeter_speed == other_config.perimeter_speed
&& config.infill_overlap == other_config.infill_overlap) { && config.external_perimeter_speed == other_config.external_perimeter_speed
layerms.push_back(other_layerm); && config.gap_fill_speed == other_config.gap_fill_speed
done[it - m_regions.begin()] = true; && config.overhangs == other_config.overhangs
} && config.opt_serialize("perimeter_extrusion_width") == other_config.opt_serialize("perimeter_extrusion_width")
} && config.thin_walls == other_config.thin_walls
&& config.external_perimeters_first == other_config.external_perimeters_first
if (layerms.size() == 1) { // optimization && config.infill_overlap == other_config.infill_overlap)
(*layerm)->fill_surfaces.surfaces.clear(); {
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces); other_layerm->perimeters.clear();
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces); other_layerm->fills.clear();
} else { other_layerm->thin_fills.clear();
SurfaceCollection new_slices; layerms.push_back(other_layerm);
// Use the region with highest infill rate, as the make_perimeters() function below decides on the gap fill based on the infill existence. done[it - m_regions.begin()] = true;
LayerRegion *layerm_config = layerms.front(); }
{ }
// group slices (surfaces) according to number of extra perimeters
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ] if (layerms.size() == 1) { // optimization
for (LayerRegion *layerm : layerms) { (*layerm)->fill_surfaces.surfaces.clear();
for (Surface &surface : layerm->slices.surfaces) (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
slices[surface.extra_perimeters].emplace_back(surface); (*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density) } else {
layerm_config = layerm; 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.
// merge the surfaces assigned to each group LayerRegion *layerm_config = layerms.front();
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()); // group slices (surfaces) according to number of extra perimeters
} std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
for (LayerRegion *layerm : layerms) {
// make perimeters for (Surface &surface : layerm->slices.surfaces)
SurfaceCollection fill_surfaces; slices[surface.extra_perimeters].emplace_back(surface);
layerm_config->make_perimeters(new_slices, &fill_surfaces); if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
layerm_config = layerm;
}
// merge the surfaces assigned to each group
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());
}
// make perimeters
SurfaceCollection 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";
} }