diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index 754ef315f..83b20d2a7 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -21,7 +21,7 @@ Layer::~Layer() bool Layer::empty() const { for (const LayerRegion *layerm : m_regions) - if (layerm != nullptr && ! layerm->slices.empty()) + if (layerm != nullptr && ! layerm->slices().empty()) // Non empty layer. return false; return true; @@ -39,11 +39,11 @@ void Layer::make_slices() ExPolygons slices; if (m_regions.size() == 1) { // optimization: if we only have one region, take its slices - slices = m_regions.front()->slices; + slices = m_regions.front()->slices(); } else { Polygons slices_p; for (LayerRegion *layerm : m_regions) - polygons_append(slices_p, to_polygons(layerm->slices)); + polygons_append(slices_p, to_polygons(layerm->slices())); slices = union_ex(slices_p); } @@ -71,11 +71,11 @@ void Layer::merge_slices() if (m_regions.size() == 1) { // Optimization, also more robust. Don't merge classified pieces of layerm->slices, // but use the non-split islands of a layer. For a single region print, these shall be equal. - m_regions.front()->slices.set(this->slices.expolygons, stPosInternal | stDensSparse); + m_regions.front()->m_slices.set(this->slices.expolygons, stPosInternal | stDensSparse); } else { for (LayerRegion *layerm : m_regions) // without safety offset, artifacts are generated (GH #2494) - layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stPosInternal | stDensSparse); + layerm->m_slices.set(union_ex(to_polygons(std::move(layerm->m_slices.surfaces)), true), stPosInternal | stDensSparse); } } @@ -90,7 +90,7 @@ ExPolygons Layer::merged(float offset_scaled) const } Polygons polygons; for (LayerRegion *layerm : m_regions) - append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled)); + append(polygons, offset(to_expolygons(layerm->slices().surfaces), offset_scaled)); ExPolygons out = union_ex(polygons); if (offset_scaled2 != 0.f) out = offset_ex(out, offset_scaled2); @@ -145,7 +145,7 @@ void Layer::make_perimeters() if (layerms.size() == 1) { // optimization (*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); } else { SurfaceCollection new_slices; @@ -155,7 +155,7 @@ void Layer::make_perimeters() // group slices (surfaces) according to number of extra perimeters std::map slices; // extra_perimeters => [ surface, surface... ] for (LayerRegion *layerm : layerms) { - for (Surface &surface : layerm->slices.surfaces) + for (const Surface &surface : layerm->slices().surfaces) slices[surface.extra_perimeters].emplace_back(surface); if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density) layerm_config = layerm; @@ -173,7 +173,7 @@ void Layer::make_perimeters() 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); + ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices()); (*l)->fill_expolygons = expp; (*l)->fill_no_overlap_expolygons = (*layerm)->fill_no_overlap_expolygons; (*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front()); @@ -202,8 +202,8 @@ void Layer::make_fills() void Layer::export_region_slices_to_svg(const char *path) const { BoundingBox bbox; - for (const auto *region : m_regions) - for (const auto &surface : region->slices.surfaces) + for (const LayerRegion *region : m_regions) + for (const Surface &surface : region->slices().surfaces) bbox.merge(get_extents(surface.expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); Point legend_pos(bbox.min(0), bbox.max(1)); @@ -211,8 +211,8 @@ void Layer::export_region_slices_to_svg(const char *path) const SVG svg(path, bbox); const float transparency = 0.5f; - for (const auto *region : m_regions) - for (const auto &surface : region->slices.surfaces) + for (const LayerRegion *region : m_regions) + for (const Surface &surface : region->slices().surfaces) svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); export_surface_type_legend_to_svg(svg, legend_pos); svg.Close(); @@ -228,8 +228,8 @@ void Layer::export_region_slices_to_svg_debug(const char *name) const void Layer::export_region_fill_surfaces_to_svg(const char *path) const { BoundingBox bbox; - for (const auto *region : m_regions) - for (const auto &surface : region->slices.surfaces) + for (const LayerRegion *region : m_regions) + for (const Surface &surface : region->slices().surfaces) bbox.merge(get_extents(surface.expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); Point legend_pos(bbox.min(0), bbox.max(1)); @@ -237,8 +237,8 @@ void Layer::export_region_fill_surfaces_to_svg(const char *path) const SVG svg(path, bbox); const float transparency = 0.5f; - for (const auto *region : m_regions) - for (const auto &surface : region->slices.surfaces) + for (const LayerRegion *region : m_regions) + for (const Surface &surface : region->slices().surfaces) svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); export_surface_type_legend_to_svg(svg, legend_pos); svg.Close(); diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index d5ad1c4fa..baa9f7184 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -25,7 +25,8 @@ public: // collection of surfaces generated by slicing the original geometry // divided by type top/bottom/internal - SurfaceCollection slices; + SurfaceCollection m_slices; + const SurfaceCollection& slices() const { return m_slices; } // collection of extrusion paths/loops filling gaps // These fills are generated by the perimeter generator. @@ -63,7 +64,7 @@ public: Flow flow(FlowRole role, bool bridge = false, double width = -1) const; void slices_to_fill_surfaces_clipped(); void prepare_fill_surfaces(); - void make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces); + void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces); void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered); double infill_area_threshold() const; // Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer. @@ -129,7 +130,7 @@ public: // Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices. ExPolygons merged(float offset) const; template bool any_internal_region_slice_contains(const T &item) const { - for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true; + for (const LayerRegion *layerm : m_regions) if (layerm->slices().any_internal_contains(item)) return true; return false; } template bool any_bottom_region_slice_contains(const T &item) const { diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index f3f2328ed..df3656444 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -39,7 +39,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped() Polygons fill_boundaries = to_polygons(this->fill_expolygons); // Collect polygons per surface type. std::map polygons_by_surface; - for (Surface &surface : this->slices.surfaces) { + for (const Surface &surface : this->slices().surfaces) { polygons_append(polygons_by_surface[surface.surface_type], surface.expolygon); } // Trim surfaces by the fill_boundaries. @@ -53,7 +53,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped() } } -void LayerRegion::make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces) +void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces) { this->perimeters.clear(); this->thin_fills.clear(); @@ -438,7 +438,7 @@ void LayerRegion::trim_surfaces(const Polygons &trimming_polygons) for (const Surface &surface : this->slices.surfaces) assert(surface.surface_type == (stPosInternal | stDensSparse)); #endif /* NDEBUG */ - this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stPosInternal | stDensSparse); + this->m_slices.set(intersection_ex(to_polygons(std::move(this->slices().surfaces)), trimming_polygons, false), stPosInternal | stDensSparse); } void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons) @@ -447,25 +447,25 @@ void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_comp for (const Surface &surface : this->slices.surfaces) assert(surface.surface_type == (stPosInternal | stDensSparse)); #endif /* NDEBUG */ - ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces)); + ExPolygons slices_expolygons = to_expolygons(std::move(this->slices().surfaces)); Polygons slices_polygons = to_polygons(slices_expolygons); Polygons tmp = intersection(slices_polygons, trimming_polygons, false); append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step))); - this->slices.set(std::move(union_ex(tmp)), stPosInternal | stDensSparse); + this->m_slices.set(std::move(union_ex(tmp)), stPosInternal | stDensSparse); } void LayerRegion::export_region_slices_to_svg(const char *path) const { BoundingBox bbox; - for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface) - bbox.merge(get_extents(surface->expolygon)); + for (const Surface& surface : this->slices().surfaces) + bbox.merge(get_extents(surface.expolygon)); Point legend_size = export_surface_type_legend_to_svg_box_size(); Point legend_pos(bbox.min(0), bbox.max(1)); bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1))); SVG svg(path, bbox); const float transparency = 0.5f; - for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface) + for (Surfaces::const_iterator surface = this->slices().surfaces.begin(); surface != this->slices().surfaces.end(); ++surface) svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency); for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) svg.draw(surface->expolygon.lines(), surface_type_to_color_name(surface->surface_type)); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 665594b29..c520d3829 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -353,7 +353,7 @@ void Print::_simplify_slices(double distance) for (Layer *layer : object->m_layers) { layer->slices.simplify(distance); for (LayerRegion *layerm : layer->regions()) - layerm->slices.simplify(distance); + layerm->m_slices.simplify(distance); } } } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 5c6563c92..7cbc6792d 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -185,7 +185,6 @@ private: void _smooth_curves(LayerRegion *layerm); std::string _fix_slicing_errors(); void _simplify_slices(double distance); - void _make_perimeters(); bool has_support_material() const; void detect_surfaces_type(); void process_external_surfaces(); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index af08f00b2..1304a1cf3 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -170,7 +170,7 @@ void PrintObject::make_perimeters() m_print->throw_if_canceled(); LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id]; const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id]; - const Polygons upper_layerm_polygons = upper_layerm.slices; + const Polygons upper_layerm_polygons = upper_layerm.slices(); // Filter upper layer polygons in intersection_ppl by their bounding boxes? // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ]; const double total_loop_length = total_length(upper_layerm_polygons); @@ -179,7 +179,7 @@ void PrintObject::make_perimeters() const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width(); const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing(); - for (Surface &slice : layerm.slices.surfaces) { + for (Surface &slice : layerm.m_slices.surfaces) { for (;;) { // compute the total thickness of perimeters const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2 @@ -924,20 +924,21 @@ void PrintObject::detect_surfaces_type() // unless internal shells are requested Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr; Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr; - Layer *under_lower_layer = (idx_layer > 1) ? this->layers()[idx_layer - 2] : nullptr; // collapse very narrow parts (using the safety offset in the diff is not enough) float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f; + Polygons layerm_slices_surfaces = to_polygons(layerm->slices().surfaces); // no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to silce, that's why we need to start from the result of PerimeterGenerator. - // i don't see the need tostart from layerm->slices.surfaces, but i'll keep that "in case of". - Polygons layerm_slices_surfaces = layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled ? to_polygons(layerm->fill_surfaces) : to_polygons(layerm->slices.surfaces); + if (layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled) { + layerm_slices_surfaces = union_(layerm_slices_surfaces, to_polygons(layerm->fill_surfaces)); + } // find top surfaces (difference between current surfaces // of current layer and upper one) Surfaces top; if (upper_layer) { Polygons upper_slices = interface_shells ? - to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) : + to_polygons(upper_layer->get_region(idx_region)->slices().surfaces) : to_polygons(upper_layer->slices); surfaces_append(top, //FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice. @@ -946,7 +947,7 @@ void PrintObject::detect_surfaces_type() } else { // if no upper layer, all surfaces of this one are solid // we clone surfaces because we're going to clear the slices collection - top = layerm->slices.surfaces; + top = layerm->m_slices.surfaces; for (Surface &surface : top) surface.surface_type = stPosTop | stDensSolid; } @@ -985,7 +986,7 @@ void PrintObject::detect_surfaces_type() offset2_ex( diff( intersection(layerm_slices_surfaces, to_polygons(lower_slices)), // supported - to_polygons(lower_layer->get_region(idx_region)->slices.surfaces), + to_polygons(lower_layer->get_region(idx_region)->slices().surfaces), true), -offset, offset), stPosBottom | stDensSolid); @@ -994,7 +995,7 @@ void PrintObject::detect_surfaces_type() } else { // if no lower layer, all surfaces of this one are solid // we clone surfaces because we're going to clear the slices collection - bottom = layerm->slices.surfaces; + bottom = layerm->slices().surfaces; for (Surface &surface : bottom) surface.surface_type = surface_type_bottom_1st; } @@ -1019,14 +1020,13 @@ void PrintObject::detect_surfaces_type() std::vector> expolygons_with_attributes; expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green"))); expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown"))); - expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottomOverBridge), SVG::ExPolygonAttributes("grey"))); - expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces), SVG::ExPolygonAttributes("black"))); + expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices().surfaces), SVG::ExPolygonAttributes("black"))); SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes); } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ // save surfaces to layer - Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces; + Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->m_slices.surfaces; surfaces_out.clear(); // find internal surfaces (difference between top/bottom surfaces and others) @@ -1054,8 +1054,8 @@ void PrintObject::detect_surfaces_type() if (interface_shells) { // Move surfaces_new to layerm->slices.surfaces - for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer) - m_layers[idx_layer]->get_region(idx_region)->slices.surfaces = std::move(surfaces_new[idx_layer]); + for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer) + m_layers[idx_layer]->get_region(idx_region)->m_slices.surfaces = std::move(surfaces_new[idx_layer]); } BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - start"; @@ -1211,16 +1211,16 @@ void PrintObject::discover_vertical_shells() LayerRegion &layerm = *layer.m_regions[idx_region]; float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f; // Top surfaces. - append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing)); + append(cache.top_surfaces, offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing)); append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing)); // Bottom surfaces. const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge }; - append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); + append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); // Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only. // First find the maxium number of perimeters per region slice. unsigned int perimeters = 0; - for (Surface &s : layerm.slices.surfaces) + for (const Surface &s : layerm.slices().surfaces) perimeters = std::max(perimeters, s.extra_perimeters); perimeters += layerm.region()->config().perimeters.value; // Then calculate the infill offset. @@ -1287,11 +1287,11 @@ void PrintObject::discover_vertical_shells() float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f; // Top surfaces. auto &cache = cache_top_botom_regions[idx_layer]; - cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing); + cache.top_surfaces = offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing); append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing)); // Bottom surfaces. const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge }; - cache.bottom_surfaces = offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing); + cache.bottom_surfaces = offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing); append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing)); // Holes over all regions. Only collect them once, they are valid for all idx_region iterations. if (cache.holes.empty()) { @@ -1939,7 +1939,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start"; for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id) - m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse); + m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse); m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end"; } @@ -2018,7 +2018,7 @@ void PrintObject::_slice(const std::vector &layer_height_profile) if (num_volumes > 1) // Merge the islands using a positive / negative offset. expolygons = offset_ex(offset_ex(expolygons, double(scale_(EPSILON))), double( - scale_(EPSILON))); - m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stPosInternal | stDensSparse); + m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons), stPosInternal | stDensSparse); } } }); @@ -2048,16 +2048,16 @@ void PrintObject::_slice(const std::vector &layer_height_profile) Layer *layer = m_layers[layer_id]; LayerRegion *layerm = layer->m_regions[region_id]; LayerRegion *other_layerm = layer->m_regions[other_region_id]; - if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty()) + if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices().empty() || expolygons_by_layer[layer_id].empty()) continue; - Polygons other_slices = to_polygons(other_layerm->slices); + Polygons other_slices = to_polygons(other_layerm->slices()); ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id])); if (my_parts.empty()) continue; // Remove such parts from original region. - other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse); + other_layerm->m_slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse); // Append new parts to our region. - layerm->slices.append(std::move(my_parts), stPosInternal | stDensSparse); + layerm->m_slices.append(std::move(my_parts), stPosInternal | stDensSparse); } } }); @@ -2114,8 +2114,8 @@ end: LayerRegion *layerm = layer->m_regions.front(); // Apply the XY compensation. ExPolygons expolygons = (delta == 0.f) ? - to_expolygons(std::move(layerm->slices.surfaces)) : - offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta); + to_expolygons(std::move(layerm->slices().surfaces)) : + offset_ex(to_expolygons(std::move(layerm->slices().surfaces)), delta); // Apply the elephant foot compensation. if (elephant_foot_compensation != 0) { float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing()); @@ -2130,7 +2130,7 @@ end: expolygons = union_ex(tmp); } } - layerm->slices.set(std::move(expolygons), stPosInternal | stDensSparse); + layerm->m_slices.set(std::move(expolygons), stPosInternal | stDensSparse); } _offset_holes(hole_delta, layer->regions().front()); _smooth_curves(layer->regions().front()); @@ -2143,7 +2143,7 @@ end: Polygons processed; for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) { LayerRegion *layerm = layer->m_regions[region_id]; - ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces)); + ExPolygons slices = to_expolygons(std::move(layerm->slices().surfaces)); if (upscale) slices = offset_ex(std::move(slices), delta); if (region_id > 0 && clip) @@ -2152,7 +2152,7 @@ end: if (clip && (region_id + 1 < layer->m_regions.size())) // Collect the already processed regions to trim the to be processed regions. polygons_append(processed, slices); - layerm->slices.set(std::move(slices), stPosInternal | stDensSparse); + layerm->m_slices.set(std::move(slices), stPosInternal | stDensSparse); } } if (delta < 0.f) { @@ -2193,7 +2193,7 @@ end: void PrintObject::_offset_holes(double hole_delta, LayerRegion *layerm) { if (hole_delta != 0.f) { - ExPolygons polys = to_expolygons(std::move(layerm->slices.surfaces)); + ExPolygons polys = to_expolygons(std::move(layerm->slices().surfaces)); ExPolygons new_polys; for (const ExPolygon &ex_poly : polys) { ExPolygon new_ex_poly(ex_poly); @@ -2226,7 +2226,7 @@ void PrintObject::_offset_holes(double hole_delta, LayerRegion *layerm) { } new_polys.push_back(new_ex_poly); } - layerm->slices.set(std::move(new_polys), stPosInternal | stDensSparse); + layerm->m_slices.set(std::move(new_polys), stPosInternal | stDensSparse); } } @@ -2317,7 +2317,7 @@ void PrintObject::_smooth_curves(LayerRegion *layerm) { if (layerm->region()->config().curve_smoothing_precision.value > 0.f) { ExPolygons new_polys; - for (const Surface &srf : layerm->slices.surfaces) { + for (const Surface &srf : layerm->slices().surfaces) { const ExPolygon &ex_poly = srf.expolygon; ExPolygon new_ex_poly(ex_poly); new_ex_poly.contour = _smooth_curve(new_ex_poly.contour, PI, @@ -2336,7 +2336,7 @@ void PrintObject::_smooth_curves(LayerRegion *layerm) { } new_polys.push_back(new_ex_poly); } - layerm->slices.set(std::move(new_polys), stPosInternal | stDensSparse); + layerm->m_slices.set(std::move(new_polys), stPosInternal | stDensSparse); } } @@ -2591,12 +2591,12 @@ std::string PrintObject::_fix_slicing_errors() const Surfaces *lower_surfaces = nullptr; for (size_t j = idx_layer + 1; j < m_layers.size(); ++ j) if (! m_layers[j]->slicing_errors) { - upper_surfaces = &m_layers[j]->regions()[region_id]->slices.surfaces; + upper_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces; break; } for (int j = int(idx_layer) - 1; j >= 0; -- j) if (! m_layers[j]->slicing_errors) { - lower_surfaces = &m_layers[j]->regions()[region_id]->slices.surfaces; + lower_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces; break; } // Collect outer contours and holes from the valid layers above & below. @@ -2623,7 +2623,7 @@ std::string PrintObject::_fix_slicing_errors() if (lower_surfaces) for (const auto &surface : *lower_surfaces) polygons_append(holes, surface.expolygon.holes); - layerm->slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse); + layerm->m_slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse); } // Update layer slices after repairing the single regions. layer->make_slices(); @@ -2659,115 +2659,13 @@ void PrintObject::_simplify_slices(double distance) m_print->throw_if_canceled(); Layer *layer = m_layers[layer_idx]; for (size_t region_idx = 0; region_idx < layer->m_regions.size(); ++ region_idx) - layer->m_regions[region_idx]->slices.simplify(distance); + layer->m_regions[region_idx]->m_slices.simplify(distance); layer->slices.simplify(distance); } }); BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - end"; } -void PrintObject::_make_perimeters() -{ - if (! this->set_started(posPerimeters)) - return; - - BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info(); - - // merge slices if they were split into types - if (this->typed_slices) { - for (Layer *layer : m_layers) - layer->merge_slices(); - this->typed_slices = false; - this->invalidate_step(posPrepareInfill); - } - - // compare each layer to the one below, and mark those slices needing - // one additional inner perimeter, like the top of domed objects- - - // this algorithm makes sure that at least one perimeter is overlapping - // but we don't generate any extra perimeter if fill density is zero, as they would be floating - // inside the object - infill_only_where_needed should be the method of choice for printing - // hollow objects - for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) { - const PrintRegion ®ion = *m_print->regions()[region_id]; - if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2) - continue; - - BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start"; - tbb::parallel_for( - tbb::blocked_range(0, m_layers.size() - 1), - [this, ®ion, region_id](const tbb::blocked_range& range) { - for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { - LayerRegion &layerm = *m_layers[layer_idx]->regions()[region_id]; - const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->regions()[region_id]; - const Polygons upper_layerm_polygons = upper_layerm.slices; - // Filter upper layer polygons in intersection_ppl by their bounding boxes? - // my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ]; - const double total_loop_length = total_length(upper_layerm_polygons); - const coord_t perimeter_spacing = layerm.flow(frPerimeter).scaled_spacing(); - const Flow ext_perimeter_flow = layerm.flow(frExternalPerimeter); - const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width(); - const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing(); - - for (Surface &slice : layerm.slices.surfaces) { - for (;;) { - // compute the total thickness of perimeters - const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2 - + (region.config().perimeters-1 + slice.extra_perimeters) * perimeter_spacing; - // define a critical area where we don't want the upper slice to fall into - // (it should either lay over our perimeters or outside this area) - const coord_t critical_area_depth = coord_t(perimeter_spacing * 1.5); - const Polygons critical_area = diff( - offset(slice.expolygon, double(- perimeters_thickness)), - offset(slice.expolygon, double(- perimeters_thickness - critical_area_depth)) - ); - // check whether a portion of the upper slices falls inside the critical area - const Polylines intersection = intersection_pl(to_polylines(upper_layerm_polygons), critical_area); - // only add an additional loop if at least 30% of the slice loop would benefit from it - if (total_length(intersection) <= total_loop_length*0.3) - break; - /* - if (0) { - require "Slic3r/SVG.pm"; - Slic3r::SVG::output( - "extra.svg", - no_arrows => 1, - expolygons => union_ex($critical_area), - polylines => [ map $_->split_at_first_point, map $_->p, @{$upper_layerm->slices} ], - ); - } - */ - ++ slice.extra_perimeters; - } - #ifdef DEBUG - if (slice.extra_perimeters > 0) - printf(" adding %d more perimeter(s) at layer %zu\n", slice.extra_perimeters, layer_idx); - #endif - } - } - }); - BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - end"; - } - - BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start"; - tbb::parallel_for( - tbb::blocked_range(0, m_layers.size()), - [this](const tbb::blocked_range& range) { - for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) - m_layers[layer_idx]->make_perimeters(); - } - ); - BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end"; - - /* - simplify slices (both layer and region slices), - we only need the max resolution for perimeters - ### This makes this method not-idempotent, so we keep it disabled for now. - ###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION); - */ - - this->set_done(posPerimeters); -} // Only active if config->infill_only_where_needed. This step trims the sparse infill, // so it acts as an internal support. It maintains all other infill types intact. @@ -2895,7 +2793,7 @@ void PrintObject::discover_horizontal_shells() // (not covered by a layer above / below). // This does not contain the areas covered by perimeters! Polygons solid; - for (const Surface &surface : layerm->slices.surfaces) + for (const Surface &surface : layerm->slices().surfaces) if (surface.surface_type == type) polygons_append(solid, to_polygons(surface.expolygon)); // Infill areas (slices without the perimeters). diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 386a0a3b0..1f14a52d0 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -279,7 +279,6 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) MyLayersPtr intermediate_layers = this->raft_and_intermediate_support_layers( object, bottom_contacts, top_contacts, layer_storage); - // this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.soluble_interface ? 0. : m_support_layer_height_min, 0., m_gap_xy); this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.soluble_interface ? 0. : this->m_slicing_params.gap_support_object, @@ -429,14 +428,14 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t // 1) Count the new polygons first. size_t n_polygons_new = 0; for (const LayerRegion *region : layer.regions()) - for (const Surface &surface : region->slices.surfaces) + for (const Surface &surface : region->slices().surfaces) if (surface.surface_type == surface_type) n_polygons_new += surface.expolygon.holes.size() + 1; // 2) Collect the new polygons. Polygons out; out.reserve(n_polygons_new); for (const LayerRegion *region : layer.regions()) - for (const Surface &surface : region->slices.surfaces) + for (const Surface &surface : region->slices().surfaces) if (surface.surface_type == surface_type) polygons_append(out, surface.expolygon); return out; @@ -791,7 +790,6 @@ namespace SupportMaterialInternal { { for (const ExtrusionEntity *ee : perimeters.entities) { if (ee->is_collection()) { - const ExtrusionEntityCollection * eec = static_cast(ee); for (const ExtrusionEntity *ee2 : static_cast(ee)->entities) { //assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !! if (ee2->is_loop()) @@ -854,15 +852,11 @@ namespace SupportMaterialInternal { } } } - static void collect_bridging_perimeter_areas(const ExtrusionEntityCollection &perimeters, const float expansion_scaled, Polygons &out) + static void collect_bridging_perimeter_areas(const ExtrusionEntitiesPtr &perimeters, const float expansion_scaled, Polygons &out) { - for (const ExtrusionEntity *ee : perimeters.entities) { + for (const ExtrusionEntity *ee : perimeters) { if (ee->is_collection()) { - for (const ExtrusionEntity *ee2 : static_cast(ee)->entities) { - //assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !! - if (ee2->is_loop()) - collect_bridging_perimeter_areas(*static_cast(ee2), expansion_scaled, out); - } + collect_bridging_perimeter_areas(static_cast(ee)->entities, expansion_scaled, out); } else if (ee->is_loop()) collect_bridging_perimeter_areas(*static_cast(ee), expansion_scaled, out); } @@ -1027,7 +1021,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ Polygons contact_polygons; Polygons slices_margin_cached; double slices_margin_cached_offset = -1.; - Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->slices.expolygons); + Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->slices.expolygons); // Offset of the lower layer, to trim the support polygons with to calculate dense supports. double no_interface_offset = 0.; if (layer_id == 0) { @@ -1056,7 +1050,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_ 0.5f * fw); // Overhang polygons for this layer and region. Polygons diff_polygons; - Polygons layerm_polygons = to_polygons(layerm->slices); + Polygons layerm_polygons = to_polygons(layerm->slices()); if (lower_layer_offset == 0.f) { // Support everything. diff_polygons = diff(layerm_polygons, lower_layer_polygons); @@ -1466,7 +1460,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta if (! m_object_config->support_material_buildplate_only) // Find the bottom contact layers above the top surfaces of this layer. task_group.run([this, &object, &top_contacts, contact_idx, &layer, layer_id, &layer_storage, &layer_support_areas, &bottom_contacts, &projection_raw] { - Polygons top = collect_region_slices_by_type(layer, stPosTop| stDensSolid); + Polygons top = collect_region_slices_by_type(layer, stPosTop | stDensSolid); #ifdef SLIC3R_DEBUG { BoundingBox bbox = get_extents(projection_raw); @@ -1538,7 +1532,6 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta } } } - #ifdef SLIC3R_DEBUG Slic3r::SVG::export_expolygons( debug_out_path("support-bottom-contacts-%d-%lf.svg", iRun, layer_new.print_z), @@ -2135,7 +2128,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); if (region->region()->config().overhangs.value) - SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming); + SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming); } if (! some_region_overlaps) break; diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index 79eba28ad..0bb4fabaa 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -140,6 +140,7 @@ public: typedef std::vector Surfaces; typedef std::vector SurfacesPtr; +typedef std::vector SurfacesConstPtr; inline Polygons to_polygons(const Surfaces &src) { @@ -171,6 +172,21 @@ inline Polygons to_polygons(const SurfacesPtr &src) return polygons; } +inline Polygons to_polygons(const SurfacesConstPtr &src) +{ + size_t num = 0; + for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it) + num += (*it)->expolygon.holes.size() + 1; + Polygons polygons; + polygons.reserve(num); + for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it) { + polygons.emplace_back((*it)->expolygon.contour); + for (Polygons::const_iterator ith = (*it)->expolygon.holes.begin(); ith != (*it)->expolygon.holes.end(); ++ith) + polygons.emplace_back(*ith); + } + return polygons; +} + inline ExPolygons to_expolygons(const Surfaces &src) { ExPolygons expolygons; @@ -199,6 +215,15 @@ inline ExPolygons to_expolygons(const SurfacesPtr &src) return expolygons; } +inline ExPolygons to_expolygons(const SurfacesConstPtr &src) +{ + ExPolygons expolygons; + expolygons.reserve(src.size()); + for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it) + expolygons.emplace_back((*it)->expolygon); + return expolygons; +} + // Count a nuber of polygons stored inside the vector of expolygons. // Useful for allocating space for polygons when converting expolygons to polygons. inline size_t number_polygons(const Surfaces &surfaces) diff --git a/src/libslic3r/SurfaceCollection.cpp b/src/libslic3r/SurfaceCollection.cpp index 4fe98c697..de375bd0c 100644 --- a/src/libslic3r/SurfaceCollection.cpp +++ b/src/libslic3r/SurfaceCollection.cpp @@ -54,34 +54,34 @@ SurfaceCollection::group(std::vector *retval) } } -SurfacesPtr -SurfaceCollection::filter_by_type(const SurfaceType type) +SurfacesConstPtr +SurfaceCollection::filter_by_type(const SurfaceType type) const { - SurfacesPtr ss; - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { - if (surface->surface_type == type) ss.push_back(&*surface); + SurfacesConstPtr ss; + for (const Surface & surface : this->surfaces) { + if (surface.surface_type == type) ss.push_back(&surface); } return ss; } -SurfacesPtr -SurfaceCollection::filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed) +SurfacesConstPtr +SurfaceCollection::filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed) const { - SurfacesPtr ss; - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { - if ((surface->surface_type & allowed) == allowed && (surface->surface_type & not_allowed) == 0) ss.push_back(&*surface); + SurfacesConstPtr ss; + for (const Surface & surface : this->surfaces) { + if ((surface.surface_type & allowed) == allowed && (surface.surface_type & not_allowed) == 0) ss.push_back(&surface); } return ss; } -SurfacesPtr -SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) +SurfacesConstPtr +SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) const { - SurfacesPtr ss; - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { + SurfacesConstPtr ss; + for (const Surface & surface : this->surfaces) { for (int i = 0; i < ntypes; ++ i) { - if (surface->surface_type == types[i]) { - ss.push_back(&*surface); + if (surface.surface_type == types[i]) { + ss.push_back(&surface); break; } } @@ -90,21 +90,21 @@ SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) } void -SurfaceCollection::filter_by_type(const SurfaceType type, Polygons* polygons) +SurfaceCollection::filter_by_type(const SurfaceType type, Polygons* polygons) const { - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { - if (surface->surface_type == type) { - Polygons pp = surface->expolygon; + for (const Surface & surface : this->surfaces) { + if (surface.surface_type == type) { + Polygons pp = surface.expolygon; polygons->insert(polygons->end(), pp.begin(), pp.end()); } } } void -SurfaceCollection::filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed) +SurfaceCollection::filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed) const { - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { - if ((surface->surface_type & flags_needed) == flags_needed && (surface->surface_type & flags_not_allowed)==0) { - Polygons pp = surface->expolygon; + for (const Surface & surface : this->surfaces) { + if ((surface.surface_type & flags_needed) == flags_needed && (surface.surface_type & flags_not_allowed)==0) { + Polygons pp = surface.expolygon; polygons->insert(polygons->end(), pp.begin(), pp.end()); } } diff --git a/src/libslic3r/SurfaceCollection.hpp b/src/libslic3r/SurfaceCollection.hpp index 9998e4b9c..0dc7b7fd9 100644 --- a/src/libslic3r/SurfaceCollection.hpp +++ b/src/libslic3r/SurfaceCollection.hpp @@ -27,17 +27,17 @@ public: for (const Surface &surface : this->surfaces) if (surface.has_pos_bottom() && surface.expolygon.contains(item)) return true; return false; } - SurfacesPtr filter_by_type(const SurfaceType type); - SurfacesPtr filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed = stNone); - SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes); + SurfacesConstPtr filter_by_type(const SurfaceType type) const; + SurfacesConstPtr filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed = stNone) const; + SurfacesConstPtr filter_by_types(const SurfaceType *types, int ntypes) const; void keep_type(const SurfaceType type); void keep_type_flag(const SurfaceType flags_needed, const SurfaceType flags_to_remove = stNone); void keep_types(const SurfaceType *types, int ntypes); void keep_types_flag(const SurfaceType flags_to_keep, const SurfaceType flags_to_remove = stNone); void remove_type(const SurfaceType type); void remove_types(const SurfaceType *types, int ntypes); - void filter_by_type(const SurfaceType type, Polygons* polygons); - void filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed = stNone); + void filter_by_type(const SurfaceType type, Polygons* polygons) const; + void filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed = stNone) const; void clear() { surfaces.clear(); } bool empty() const { return surfaces.empty(); }