SurfaceCollection::operator ExPolygons() const { return to_expolygons(surfaces); }
// Here the perimeters are created cummulatively for all layer regions sharing the same parameters influencing the perimeters. // The perimeter paths and the thin fills (ExtrusionEntityCollection) are assigned to the first compatible layer region. // The resulting fill surface is split back among the originating regions. void Layer::make_perimeters() { BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id(); // keep track of regions whose perimeters we have already generated std::set<size_t> done; for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) { size_t region_id = layerm - m_regions.begin(); if (done.find(region_id) != done.end()) continue; BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id; done.insert(region_id); const PrintRegionConfig &config = (*layerm)->region()->config(); // find compatible regions LayerRegionPtrs layerms; layerms.push_back(*layerm); for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) { LayerRegion* other_layerm = *it; const PrintRegionConfig &other_config = other_layerm->region()->config(); if (config.perimeter_extruder == other_config.perimeter_extruder && config.perimeters == other_config.perimeters && config.perimeter_speed == other_config.perimeter_speed && config.external_perimeter_speed == other_config.external_perimeter_speed && config.gap_fill_speed == other_config.gap_fill_speed && config.overhangs == other_config.overhangs && config.serialize("perimeter_extrusion_width").compare(other_config.serialize("perimeter_extrusion_width")) == 0 && config.thin_walls == other_config.thin_walls && config.external_perimeters_first == other_config.external_perimeters_first) { layerms.push_back(other_layerm); done.insert(it - m_regions.begin()); } } if (layerms.size() == 1) { // optimization (*layerm)->fill_surfaces.surfaces.clear(); (*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces); (*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces); } else { SurfaceCollection new_slices; { // group slices (surfaces) according to number of extra perimeters std::map<unsigned short,Surfaces> slices; // extra_perimeters => [ surface, surface... ] for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { for (Surfaces::iterator s = (*l)->slices.surfaces.begin(); s != (*l)->slices.surfaces.end(); ++s) { slices[s->extra_perimeters].push_back(*s); } } // merge the surfaces assigned to each group for (std::map<unsigned short,Surfaces>::const_iterator it = slices.begin(); it != slices.end(); ++it) new_slices.append(union_ex(it->second, true), it->second.front()); } // make perimeters SurfaceCollection fill_surfaces; (*layerm)->make_perimeters(new_slices, &fill_surfaces); // assign fill_surfaces to each layer if (!fill_surfaces.surfaces.empty()) { for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { // Separate the fill surfaces. ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices); (*l)->fill_expolygons = expp; (*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front()); } } } } BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done"; }