diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 62d886785..061cf1423 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -53,7 +53,7 @@ static ExPolygons get_print_object_bottom_layer_expolygons(const PrintObject &pr { ExPolygons ex_polygons; for (LayerRegion *region : print_object.layers().front()->regions()) - Slic3r::append(ex_polygons, closing_ex(region->slices.surfaces, float(SCALED_EPSILON))); + Slic3r::append(ex_polygons, closing_ex(region->slices().surfaces, float(SCALED_EPSILON))); return ex_polygons; } diff --git a/src/libslic3r/Color.cpp b/src/libslic3r/Color.cpp index 4d3bc6793..6d8daa00a 100644 --- a/src/libslic3r/Color.cpp +++ b/src/libslic3r/Color.cpp @@ -218,7 +218,7 @@ ColorRGBA ColorRGBA::operator * (float value) const for (size_t i = 0; i < 3; ++i) { ret.m_data[i] = std::clamp(value * m_data[i], 0.0f, 1.0f); } - ret.m_data[3] = this->m_data[3]; + ret.m_data[3] = m_data[3]; return ret; } diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index 1ecda7dd5..a344bb4a9 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -44,7 +44,14 @@ public: } ~ExtrusionEntityCollection() override { clear(); } explicit operator ExtrusionPaths() const; - + + ExtrusionEntitiesPtr::const_iterator cbegin() const { return this->entities.cbegin(); } + ExtrusionEntitiesPtr::const_iterator cend() const { return this->entities.cend(); } + ExtrusionEntitiesPtr::const_iterator begin() const { return this->entities.cbegin(); } + ExtrusionEntitiesPtr::const_iterator end() const { return this->entities.cend(); } + ExtrusionEntitiesPtr::iterator begin() { return this->entities.begin(); } + ExtrusionEntitiesPtr::iterator end() { return this->entities.end(); } + bool is_collection() const override { return true; } ExtrusionRole role() const override { ExtrusionRole out = erNone; @@ -102,6 +109,9 @@ public: { Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; } Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const { Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; } + size_t size() const { return entities.size(); } + // Recursively count paths and loops contained in this collection. + // this->items_count() >= this->size() size_t items_count() const; /// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections. /// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy). diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 8278db960..5ae71616c 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -121,8 +121,8 @@ std::vector group_fills(const Layer &layer) bool has_internal_voids = false; for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) { const LayerRegion &layerm = *layer.regions()[region_id]; - region_to_surface_params[region_id].assign(layerm.fill_surfaces.size(), nullptr); - for (const Surface &surface : layerm.fill_surfaces.surfaces) + region_to_surface_params[region_id].assign(layerm.fill_surfaces().size(), nullptr); + for (const Surface &surface : layerm.fill_surfaces()) if (surface.surface_type == stInternalVoid) has_internal_voids = true; else { @@ -180,7 +180,7 @@ std::vector group_fills(const Layer &layer) auto it_params = set_surface_params.find(params); if (it_params == set_surface_params.end()) it_params = set_surface_params.insert(it_params, params); - region_to_surface_params[region_id][&surface - &layerm.fill_surfaces.surfaces.front()] = &(*it_params); + region_to_surface_params[region_id][&surface - &layerm.fill_surfaces().surfaces.front()] = &(*it_params); } } @@ -192,9 +192,9 @@ std::vector group_fills(const Layer &layer) for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) { const LayerRegion &layerm = *layer.regions()[region_id]; - for (const Surface &surface : layerm.fill_surfaces.surfaces) + for (const Surface &surface : layerm.fill_surfaces()) if (surface.surface_type != stInternalVoid) { - const SurfaceFillParams *params = region_to_surface_params[region_id][&surface - &layerm.fill_surfaces.surfaces.front()]; + const SurfaceFillParams *params = region_to_surface_params[region_id][&surface - &layerm.fill_surfaces().surfaces.front()]; if (params != nullptr) { SurfaceFill &fill = surface_fills[params->idx]; if (fill.region_id == size_t(-1)) { @@ -325,7 +325,7 @@ void export_group_fills_to_svg(const char *path, const std::vector void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) { for (LayerRegion *layerm : m_regions) - layerm->fills.clear(); + layerm->m_fills.clear(); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING @@ -420,7 +420,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: } // Save into layer. ExtrusionEntityCollection* eec = nullptr; - m_regions[surface_fill.region_id]->fills.entities.push_back(eec = new ExtrusionEntityCollection()); + m_regions[surface_fill.region_id]->m_fills.entities.push_back(eec = new ExtrusionEntityCollection()); // Only concentric fills are not sorted. eec->no_sort = f->no_sort(); if (params.use_arachne) { @@ -453,16 +453,16 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: // The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection. // Why the paths are unpacked? for (LayerRegion *layerm : m_regions) - for (const ExtrusionEntity *thin_fill : layerm->thin_fills.entities) { + for (const ExtrusionEntity *thin_fill : layerm->thin_fills().entities) { ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection()); - layerm->fills.entities.push_back(&collection); + layerm->m_fills.entities.push_back(&collection); collection.entities.push_back(thin_fill->clone()); } #ifndef NDEBUG for (LayerRegion *layerm : m_regions) - for (size_t i = 0; i < layerm->fills.entities.size(); ++ i) - assert(dynamic_cast(layerm->fills.entities[i]) != nullptr); + for (const ExtrusionEntity *e : layerm->fills()) + assert(dynamic_cast(e) != nullptr); #endif } @@ -539,7 +539,7 @@ void Layer::make_ironing() double default_layer_height = this->object()->config().layer_height; for (LayerRegion *layerm : m_regions) - if (! layerm->slices.empty()) { + if (! layerm->slices().empty()) { IroningParams ironing_params; const PrintRegionConfig &config = layerm->region().config(); if (config.ironing && @@ -602,7 +602,7 @@ void Layer::make_ironing() if (iron_everything) { // Check whether there is any non-solid hole in the regions. bool internal_infill_solid = region_config.fill_density.value > 95.; - for (const Surface &surface : ironing_params.layerm->fill_surfaces.surfaces) + for (const Surface &surface : ironing_params.layerm->fill_surfaces()) if ((! internal_infill_solid && surface.surface_type == stInternal) || surface.surface_type == stInternalBridge || surface.surface_type == stInternalVoid) { // Some fill region is not quite solid. Don't iron over the whole surface. iron_completely = false; @@ -611,10 +611,10 @@ void Layer::make_ironing() } if (iron_completely) { // Iron everything. This is likely only good for solid transparent objects. - for (const Surface &surface : ironing_params.layerm->slices.surfaces) + for (const Surface &surface : ironing_params.layerm->slices()) polygons_append(polys, surface.expolygon); } else { - for (const Surface &surface : ironing_params.layerm->slices.surfaces) + for (const Surface &surface : ironing_params.layerm->slices()) if (surface.surface_type == stTop || (iron_everything && surface.surface_type == stBottom)) // stBottomBridge is not being ironed on purpose, as it would likely destroy the bridges. polygons_append(polys, surface.expolygon); @@ -622,7 +622,7 @@ void Layer::make_ironing() if (iron_everything && ! iron_completely) { // Add solid fill surfaces. This may not be ideal, as one will not iron perimeters touching these // solid fill surfaces, but it is likely better than nothing. - for (const Surface &surface : ironing_params.layerm->fill_surfaces.surfaces) + for (const Surface &surface : ironing_params.layerm->fill_surfaces()) if (surface.surface_type == stInternalSolid) polygons_append(infills, surface.expolygon); } @@ -659,7 +659,7 @@ void Layer::make_ironing() if (! polylines.empty()) { // Save into layer. ExtrusionEntityCollection *eec = nullptr; - ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection()); + ironing_params.layerm->m_fills.entities.push_back(eec = new ExtrusionEntityCollection()); // Don't sort the ironing infill lines as they are monotonicly ordered. eec->no_sort = true; extrusion_entities_append_paths( diff --git a/src/libslic3r/Fill/FillAdaptive.cpp b/src/libslic3r/Fill/FillAdaptive.cpp index 29b343db0..f935d0edf 100644 --- a/src/libslic3r/Fill/FillAdaptive.cpp +++ b/src/libslic3r/Fill/FillAdaptive.cpp @@ -316,9 +316,9 @@ std::pair adaptive_fill_line_spacing(const PrintObject &print_ob for (const Layer *layer : print_object.layers()) for (size_t region_id = 0; region_id < layer->regions().size(); ++ region_id) { RegionFillData &rd = region_fill_data[region_id]; - if (rd.has_adaptive_infill == Tristate::Maybe && ! layer->regions()[region_id]->fill_surfaces.empty()) + if (rd.has_adaptive_infill == Tristate::Maybe && ! layer->regions()[region_id]->fill_surfaces().empty()) rd.has_adaptive_infill = Tristate::Yes; - if (rd.has_support_infill == Tristate::Maybe && ! layer->regions()[region_id]->fill_surfaces.empty()) + if (rd.has_support_infill == Tristate::Maybe && ! layer->regions()[region_id]->fill_surfaces().empty()) rd.has_support_infill = Tristate::Yes; } diff --git a/src/libslic3r/Fill/Lightning/Generator.cpp b/src/libslic3r/Fill/Lightning/Generator.cpp index bd83bcfff..185cb60af 100644 --- a/src/libslic3r/Fill/Lightning/Generator.cpp +++ b/src/libslic3r/Fill/Lightning/Generator.cpp @@ -62,7 +62,7 @@ void Generator::generateInitialInternalOverhangs(const PrintObject &print_object throw_on_cancel_callback(); Polygons infill_area_here; for (const LayerRegion* layerm : print_object.get_layer(layer_nr)->regions()) - for (const Surface& surface : layerm->fill_surfaces.surfaces) + for (const Surface& surface : layerm->fill_surfaces()) if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid) append(infill_area_here, to_polygons(surface.expolygon)); @@ -93,7 +93,7 @@ void Generator::generateTrees(const PrintObject &print_object, const std::functi for (int layer_id = int(print_object.layers().size()) - 1; layer_id >= 0; layer_id--) { throw_on_cancel_callback(); for (const LayerRegion *layerm : print_object.get_layer(layer_id)->regions()) - for (const Surface &surface : layerm->fill_surfaces.surfaces) + for (const Surface &surface : layerm->fill_surfaces()) if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid) append(infill_outlines[layer_id], to_polygons(surface.expolygon)); diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index e2bd6ef65..c45b6daa9 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -849,7 +849,7 @@ namespace DoExport { region.config().get_abs_value("small_perimeter_speed") == 0 || region.config().get_abs_value("external_perimeter_speed") == 0 || region.config().get_abs_value("bridge_speed") == 0) - mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm()); + mm3_per_mm.push_back(layerm->perimeters().min_mm3_per_mm()); if (region.config().get_abs_value("infill_speed") == 0 || region.config().get_abs_value("solid_infill_speed") == 0 || region.config().get_abs_value("top_solid_infill_speed") == 0 || @@ -866,7 +866,7 @@ namespace DoExport { return min; }; - mm3_per_mm.push_back(min_mm3_per_mm_no_ironing(layerm->fills)); + mm3_per_mm.push_back(min_mm3_per_mm_no_ironing(layerm->fills())); } } } @@ -1502,7 +1502,7 @@ void GCode::process_layers( } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&spiral_vase = *this->m_spiral_vase](LayerResult in) -> LayerResult { + [&spiral_vase = *m_spiral_vase](LayerResult in) -> LayerResult { if (in.nop_layer_result) return in; @@ -1510,18 +1510,18 @@ void GCode::process_layers( return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush}; }); const auto pressure_equalizer = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&pressure_equalizer = *this->m_pressure_equalizer](LayerResult in) -> LayerResult { + [&pressure_equalizer = *m_pressure_equalizer](LayerResult in) -> LayerResult { return pressure_equalizer.process_layer(std::move(in)); }); const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer](LayerResult in) -> std::string { + [&cooling_buffer = *m_cooling_buffer](LayerResult in) -> std::string { if (in.nop_layer_result) return in.gcode; return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); const auto find_replace = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&self = *this->m_find_replace](std::string s) -> std::string { + [&self = *m_find_replace](std::string s) -> std::string { return self.process_layer(std::move(s)); }); const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -1584,24 +1584,24 @@ void GCode::process_layers( } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&spiral_vase = *this->m_spiral_vase](LayerResult in)->LayerResult { + [&spiral_vase = *m_spiral_vase](LayerResult in)->LayerResult { if (in.nop_layer_result) return in; spiral_vase.enable(in.spiral_vase_enable); return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush }; }); const auto pressure_equalizer = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&pressure_equalizer = *this->m_pressure_equalizer](LayerResult in) -> LayerResult { + [&pressure_equalizer = *m_pressure_equalizer](LayerResult in) -> LayerResult { return pressure_equalizer.process_layer(std::move(in)); }); const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer](LayerResult in)->std::string { + [&cooling_buffer = *m_cooling_buffer](LayerResult in)->std::string { if (in.nop_layer_result) return in.gcode; return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); const auto find_replace = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&self = *this->m_find_replace](std::string s) -> std::string { + [&self = *m_find_replace](std::string s) -> std::string { return self.process_layer(std::move(s)); }); const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, @@ -2108,8 +2108,8 @@ LayerResult GCode::process_layer( if (enable) { for (const LayerRegion *layer_region : layer.regions()) if (size_t(layer_region->region().config().bottom_solid_layers.value) > layer.id() || - layer_region->perimeters.items_count() > 1u || - layer_region->fills.items_count() > 0) { + layer_region->perimeters().items_count() > 1u || + layer_region->fills().items_count() > 0) { enable = false; break; } @@ -2252,20 +2252,11 @@ LayerResult GCode::process_layer( // option // (Still, we have to keep track of regions because we need to apply their config) size_t n_slices = layer.lslices.size(); - const std::vector &layer_surface_bboxes = layer.lslices_bboxes; + const LayerSlices &layer_surfaces = layer.lslices_ex; // Traverse the slices in an increasing order of bounding box size, so that the islands inside another islands are tested first, // so we can just test a point inside ExPolygon::contour and we may skip testing the holes. - std::vector slices_test_order; - slices_test_order.reserve(n_slices); - for (size_t i = 0; i < n_slices; ++ i) - slices_test_order.emplace_back(i); - std::sort(slices_test_order.begin(), slices_test_order.end(), [&layer_surface_bboxes](size_t i, size_t j) { - const Vec2d s1 = layer_surface_bboxes[i].size().cast(); - const Vec2d s2 = layer_surface_bboxes[j].size().cast(); - return s1.x() * s1.y() < s2.x() * s2.y(); - }); - auto point_inside_surface = [&layer, &layer_surface_bboxes](const size_t i, const Point &point) { - const BoundingBox &bbox = layer_surface_bboxes[i]; + auto point_inside_surface = [&layer, &layer_surfaces](const size_t i, const Point &point) { + const BoundingBox &bbox = layer_surfaces[i].bbox; return point(0) >= bbox.min(0) && point(0) < bbox.max(0) && point(1) >= bbox.min(1) && point(1) < bbox.max(1) && layer.lslices[i].contour.contains(point); @@ -2284,7 +2275,7 @@ LayerResult GCode::process_layer( // The process is almost the same for perimeters and infills - we will do it in a cycle that repeats twice: std::vector printing_extruders; for (const ObjectByExtruder::Island::Region::Type entity_type : { ObjectByExtruder::Island::Region::INFILL, ObjectByExtruder::Island::Region::PERIMETERS }) { - for (const ExtrusionEntity *ee : (entity_type == ObjectByExtruder::Island::Region::INFILL) ? layerm->fills.entities : layerm->perimeters.entities) { + for (const ExtrusionEntity *ee : (entity_type == ObjectByExtruder::Island::Region::INFILL) ? layerm->fills() : layerm->perimeters()) { // extrusions represents infill or perimeter extrusions of a single island. assert(dynamic_cast(ee) != nullptr); const auto *extrusions = static_cast(ee); @@ -2329,7 +2320,9 @@ LayerResult GCode::process_layer( layers.size(), n_slices+1); for (size_t i = 0; i <= n_slices; ++ i) { bool last = i == n_slices; - size_t island_idx = last ? n_slices : slices_test_order[i]; + // Traverse lslices back to front: lslices are produced by traversing ClipperLib::PolyTree, emitting parent contour before its children. + // Therefore traversing layer_surfaces back to front will traverse children contours before their parents. + size_t island_idx = last ? n_slices : layer_surfaces.size() - i - 1; if (// extrusions->first_point does not fit inside any slice last || // extrusions->first_point fits inside ith slice diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp index 9edb35ee8..c866e13e4 100644 --- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp +++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp @@ -487,7 +487,7 @@ static float get_perimeter_spacing(const Layer &layer) size_t regions_count = 0; float perimeter_spacing = 0.f; for (const LayerRegion *layer_region : layer.regions()) - if (layer_region != nullptr && !layer_region->slices.empty()) { + if (layer_region != nullptr && ! layer_region->slices().empty()) { perimeter_spacing += layer_region->flow(frPerimeter).scaled_spacing(); ++regions_count; } @@ -508,7 +508,7 @@ static float get_perimeter_spacing_external(const Layer &layer) for (const PrintObject *object : layer.object()->print()->objects()) if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l) for (const LayerRegion *layer_region : l->regions()) - if (layer_region != nullptr && !layer_region->slices.empty()) { + if (layer_region != nullptr && ! layer_region->slices().empty()) { perimeter_spacing += layer_region->flow(frPerimeter).scaled_spacing(); ++ regions_count; } @@ -527,7 +527,7 @@ static float get_external_perimeter_width(const Layer &layer) size_t regions_count = 0; float perimeter_width = 0.f; for (const LayerRegion *layer_region : layer.regions()) - if (layer_region != nullptr && !layer_region->slices.empty()) { + if (layer_region != nullptr && ! layer_region->slices().empty()) { perimeter_width += float(layer_region->flow(frExternalPerimeter).scaled_width()); ++regions_count; } @@ -1070,14 +1070,14 @@ static ExPolygons get_boundary(const Layer &layer) // Collect all top layers that will not be crossed. size_t polygons_count = 0; for (const LayerRegion *layer_region : layer.regions()) - for (const Surface &surface : layer_region->fill_surfaces.surfaces) + for (const Surface &surface : layer_region->fill_surfaces()) if (surface.is_top()) ++polygons_count; if (polygons_count > 0) { ExPolygons top_layer_polygons; top_layer_polygons.reserve(polygons_count); for (const LayerRegion *layer_region : layer.regions()) - for (const Surface &surface : layer_region->fill_surfaces.surfaces) + for (const Surface &surface : layer_region->fill_surfaces()) if (surface.is_top()) top_layer_polygons.emplace_back(surface.expolygon); top_layer_polygons = union_ex(top_layer_polygons); diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index c82fd38e5..d9492cb2a 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2735,8 +2735,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) if (volume_extruded_filament != 0.) m_used_filaments.increase_caches(volume_extruded_filament, - this->m_extruder_id, area_filament_cross_section * this->m_parking_position, - area_filament_cross_section * this->m_extra_loading_move); + m_extruder_id, area_filament_cross_section * m_parking_position, + area_filament_cross_section * m_extra_loading_move); const EMoveType type = move_type(delta_pos); if (type == EMoveType::Extrude) { @@ -4303,7 +4303,7 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code) m_used_filaments.process_color_change_cache(); if (code == CustomGCode::ToolChange) - m_used_filaments.process_extruder_cache(this->m_extruder_id); + m_used_filaments.process_extruder_cache(m_extruder_id); } void GCodeProcessor::simulate_st_synchronize(float additional_time) diff --git a/src/libslic3r/GCode/PressureEqualizer.cpp b/src/libslic3r/GCode/PressureEqualizer.cpp index 7135c0a5c..c8a9618ef 100644 --- a/src/libslic3r/GCode/PressureEqualizer.cpp +++ b/src/libslic3r/GCode/PressureEqualizer.cpp @@ -690,7 +690,7 @@ inline bool is_just_line_with_extrude_set_speed_tag(const std::string &line) void PressureEqualizer::push_line_to_output(const size_t line_idx, const float new_feedrate, const char *comment) { - const GCodeLine &line = this->m_gcode_lines[line_idx]; + const GCodeLine &line = m_gcode_lines[line_idx]; if (line_idx > 0 && output_buffer_length > 0) { const std::string prev_line_str = std::string(output_buffer.begin() + int(this->output_buffer_prev_length), output_buffer.begin() + int(this->output_buffer_length) + 1); diff --git a/src/libslic3r/GCode/PrintExtents.cpp b/src/libslic3r/GCode/PrintExtents.cpp index a86411519..9a01dc8a6 100644 --- a/src/libslic3r/GCode/PrintExtents.cpp +++ b/src/libslic3r/GCode/PrintExtents.cpp @@ -113,8 +113,8 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object break; BoundingBoxf bbox_this; for (const LayerRegion *layerm : layer->regions()) { - bbox_this.merge(extrusionentity_extents(layerm->perimeters)); - for (const ExtrusionEntity *ee : layerm->fills.entities) + bbox_this.merge(extrusionentity_extents(layerm->perimeters())); + for (const ExtrusionEntity *ee : layerm->fills()) // fill represents infill extrusions of a single island. bbox_this.merge(extrusionentity_extents(*dynamic_cast(ee))); } diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 1d7fd5b3c..c92ff8212 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -401,7 +401,7 @@ struct GlobalModelInfo { Polygons extract_perimeter_polygons(const Layer *layer, std::vector &corresponding_regions_out) { Polygons polygons; for (const LayerRegion *layer_region : layer->regions()) { - for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { + for (const ExtrusionEntity *ex_entity : layer_region->perimeters()) { if (ex_entity->is_collection()) { //collection of inner, outer, and overhang perimeters for (const ExtrusionEntity *perimeter : static_cast(ex_entity)->entities) { ExtrusionRole role = perimeter->role(); @@ -1060,7 +1060,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) { size_t regions_with_perimeter = 0; for (const LayerRegion *region : po->layers()[layer_idx]->regions()) { - if (region->perimeters.entities.size() > 0) { + if (region->perimeters().size() > 0) { regions_with_perimeter++; } }; diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index c5554c2fa..6c5d0667a 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -226,12 +226,12 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto for (const LayerRegion *layerm : layer->regions()) { const PrintRegion ®ion = layerm->region(); - if (! layerm->perimeters.entities.empty()) { + if (! layerm->perimeters().empty()) { bool something_nonoverriddable = true; if (m_print_config_ptr) { // in this case complete_objects is false (see ToolOrdering constructors) something_nonoverriddable = false; - for (const auto& eec : layerm->perimeters.entities) // let's check if there are nonoverriddable entities + for (const ExtrusionEntity *eec : layerm->perimeters()) // let's check if there are nonoverriddable entities if (!layer_tools.wiping_extrusions().is_overriddable_and_mark(dynamic_cast(*eec), *m_print_config_ptr, object, region)) something_nonoverriddable = true; } @@ -245,7 +245,7 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto bool has_infill = false; bool has_solid_infill = false; bool something_nonoverriddable = false; - for (const ExtrusionEntity *ee : layerm->fills.entities) { + for (const ExtrusionEntity *ee : layerm->fills()) { // fill represents infill extrusions of a single island. const auto *fill = dynamic_cast(ee); ExtrusionRole role = fill->entities.empty() ? erNone : fill->entities.front()->role(); @@ -692,7 +692,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int bool wipe_into_infill_only = ! object->config().wipe_into_objects && region.config().wipe_into_infill; if (print.config().infill_first != perimeters_done || wipe_into_infill_only) { - for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections + for (const ExtrusionEntity* ee : layerm->fills()) { // iterate through all infill Collections auto* fill = dynamic_cast(ee); if (!is_overriddable(*fill, print.config(), *object, region)) @@ -716,7 +716,7 @@ float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int // Now the same for perimeters - see comments above for explanation: if (object->config().wipe_into_objects && print.config().infill_first == perimeters_done) { - for (const ExtrusionEntity* ee : layerm->perimeters.entities) { + for (const ExtrusionEntity* ee : layerm->perimeters()) { auto* fill = dynamic_cast(ee); if (is_overriddable(*fill, print.config(), *object, region) && !is_entity_overridden(fill, copy) && fill->total_volume() > min_infill_volume) { set_extruder_override(fill, copy, new_extruder, num_of_copies); @@ -762,7 +762,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print) if (!region.config().wipe_into_infill && !object->config().wipe_into_objects) continue; - for (const ExtrusionEntity* ee : layerm->fills.entities) { // iterate through all infill Collections + for (const ExtrusionEntity* ee : layerm->fills()) { // iterate through all infill Collections auto* fill = dynamic_cast(ee); if (!is_overriddable(*fill, print.config(), *object, region) @@ -785,7 +785,7 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print) } // Now the same for perimeters - see comments above for explanation: - for (const ExtrusionEntity* ee : layerm->perimeters.entities) { // iterate through all perimeter Collections + for (const ExtrusionEntity* ee : layerm->perimeters()) { // iterate through all perimeter Collections auto* fill = dynamic_cast(ee); if (is_overriddable(*fill, print.config(), *object, region) && ! is_entity_overridden(fill, copy)) set_extruder_override(fill, copy, (print.config().infill_first ? last_nonsoluble_extruder : first_nonsoluble_extruder), num_of_copies); diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index d273fde96..3bd2566a5 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -22,7 +22,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; @@ -40,11 +40,11 @@ void Layer::make_slices() ExPolygons slices; if (m_regions.size() == 1) { // optimization: if we only have one region, take its slices - slices = to_expolygons(m_regions.front()->slices.surfaces); + slices = to_expolygons(m_regions.front()->slices().surfaces); } else { Polygons slices_p; for (LayerRegion *layerm : m_regions) - polygons_append(slices_p, to_polygons(layerm->slices.surfaces)); + polygons_append(slices_p, to_polygons(layerm->slices().surfaces)); slices = union_safety_offset_ex(slices_p); } @@ -65,6 +65,245 @@ void Layer::make_slices() this->lslices.emplace_back(std::move(slices[i])); } +// used by Layer::build_up_down_graph() +[[nodiscard]] static ClipperLib_Z::Paths expolygons_to_zpaths(const ExPolygons &expolygons, coord_t isrc) +{ + size_t num_paths = 0; + for (const ExPolygon &expolygon : expolygons) + num_paths += expolygon.num_contours(); + + ClipperLib_Z::Paths out; + out.reserve(num_paths); + + for (const ExPolygon &expolygon : expolygons) { + for (size_t icontour = 0; icontour < expolygon.num_contours(); ++ icontour) { + const Polygon &contour = expolygon.contour_or_hole(icontour); + out.emplace_back(); + ClipperLib_Z::Path &path = out.back(); + path.reserve(contour.size()); + for (const Point &p : contour.points) + path.push_back({ p.x(), p.y(), isrc }); + } + ++ isrc; + } + + return out; +} + +// used by Layer::build_up_down_graph() +static void connect_layer_slices( + Layer &below, + Layer &above, + const ClipperLib_Z::PolyTree &polytree, + const std::vector> &intersections, + const coord_t offset_below, + const coord_t offset_above, + const coord_t offset_end) +{ + class Visitor { + public: + Visitor(const std::vector> &intersections, + Layer &below, Layer &above, const coord_t offset_below, const coord_t offset_above, const coord_t offset_end) : + m_intersections(intersections), m_below(below), m_above(above), m_offset_below(offset_below), m_offset_above(offset_above), m_offset_end(offset_end) {} + + void visit(const ClipperLib_Z::PolyNode &polynode) + { + if (polynode.Contour.size() >= 3) { + int32_t i = 0, j = 0; + double area = 0; + for (int icontour = 0; icontour <= polynode.ChildCount(); ++ icontour) { + const ClipperLib_Z::Path &contour = icontour == 0 ? polynode.Contour : polynode.Childs[icontour - 1]->Contour; + if (contour.size() >= 3) { + area = ClipperLib_Z::Area(contour); + int32_t i = contour.front().z(); + int32_t j = i; + if (i < 0) { + std::tie(i, j) = m_intersections[-i - 1]; + } else { + for (const ClipperLib_Z::IntPoint& pt : contour) { + j = pt.z(); + if (j < 0) { + std::tie(i, j) = m_intersections[-j - 1]; + goto end; + } + else if (i != j) + goto end; + } + } + } + } + end: + bool found = false; + if (i == j) { + // The contour is completely inside another contour. + Point pt(polynode.Contour.front().x(), polynode.Contour.front().y()); + if (i < m_offset_above) { + // Index of an island below. Look-it up in the island above. + assert(i >= m_offset_below); + i -= m_offset_below; + for (int l = int(m_above.lslices_ex.size()) - 1; l >= 0; -- l) { + LayerSlice &lslice = m_above.lslices_ex[l]; + if (lslice.bbox.contains(pt) && m_above.lslices[l].contains(pt)) { + found = true; + j = l; + break; + } + } + } else { + // Index of an island above. Look-it up in the island below. + assert(j < m_offset_end); + j -= m_offset_below; + for (int l = int(m_below.lslices_ex.size()) - 1; l >= 0; -- l) { + LayerSlice &lslice = m_below.lslices_ex[l]; + if (lslice.bbox.contains(pt) && m_below.lslices[l].contains(pt)) { + found = true; + i = l; + break; + } + } + } + } else { + if (i > j) + std::swap(i, j); + assert(i >= m_offset_below); + assert(i < m_offset_above); + i -= m_offset_below; + assert(j >= m_offset_above); + assert(j < m_offset_end); + j -= m_offset_above; + found = true; + } + if (found) { + // Subtract area of holes from the area of outer contour. + for (int icontour = 0; icontour < polynode.ChildCount(); ++ icontour) + area -= ClipperLib_Z::Area(polynode.Childs[icontour]->Contour); + // Store the links and area into the contours. + LayerSlice::Links &links_below = m_below.lslices_ex[i].overlaps_above; + LayerSlice::Links &links_above = m_above.lslices_ex[i].overlaps_below; + LayerSlice::Link key{ j }; + auto it_below = std::lower_bound(links_below.begin(), links_below.end(), key, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; }); + if (it_below != links_below.end() && it_below->slice_idx == j) { + it_below->area += area; + } else { + auto it_above = std::lower_bound(links_above.begin(), links_above.end(), key, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; }); + if (it_above != links_above.end() && it_above->slice_idx == i) { + it_above->area += area; + } else { + // Insert into one of the two vectors. + bool take_below = false; + if (links_below.size() < LayerSlice::LinksStaticSize) + take_below = false; + else if (links_above.size() >= LayerSlice::LinksStaticSize) { + size_t shift_below = links_below.end() - it_below; + size_t shift_above = links_above.end() - it_above; + take_below = shift_below < shift_above; + } + if (take_below) + links_below.insert(it_below, { j, float(area) }); + else + links_above.insert(it_above, { i, float(area) }); + } + } + } + } + for (int i = 0; i < polynode.ChildCount(); ++ i) + for (int j = 0; j < polynode.Childs[i]->ChildCount(); ++ j) + this->visit(*polynode.Childs[i]->Childs[j]); + } + + private: + const std::vector> &m_intersections; + Layer &m_below; + Layer &m_above; + const coord_t m_offset_below; + const coord_t m_offset_above; + const coord_t m_offset_end; + } visitor(intersections, below, above, offset_below, offset_above, offset_end); + + for (int i = 0; i < polytree.ChildCount(); ++ i) + visitor.visit(*polytree.Childs[i]); + +#ifndef NDEBUG + // Verify that only one directional link is stored: either from bottom slice up or from upper slice down. + for (int32_t islice = 0; islice < below.lslices_ex.size(); ++ islice) { + LayerSlice::Links &links1 = below.lslices_ex[islice].overlaps_above; + for (LayerSlice::Link &link1 : links1) { + LayerSlice::Links &links2 = above.lslices_ex[link1.slice_idx].overlaps_below; + assert(! std::binary_search(links2.begin(), links2.end(), link1, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; })); + } + } + for (int32_t islice = 0; islice < above.lslices_ex.size(); ++ islice) { + LayerSlice::Links &links1 = above.lslices_ex[islice].overlaps_above; + for (LayerSlice::Link &link1 : links1) { + LayerSlice::Links &links2 = below.lslices_ex[link1.slice_idx].overlaps_below; + assert(! std::binary_search(links2.begin(), links2.end(), link1, [](auto &l, auto &r){ return l.slice_idx < r.slice_idx; })); + } + } +#endif // NDEBUG + + // Scatter the links, but don't sort them yet. + for (int32_t islice = 0; islice < below.lslices_ex.size(); ++ islice) + for (LayerSlice::Link &link : below.lslices_ex[islice].overlaps_above) + above.lslices_ex[link.slice_idx].overlaps_below.push_back({ islice, link.area }); + for (int32_t islice = 0; islice < above.lslices_ex.size(); ++ islice) + for (LayerSlice::Link &link : above.lslices_ex[islice].overlaps_below) + below.lslices_ex[link.slice_idx].overlaps_above.push_back({ islice, link.area }); + // Sort the links. + for (LayerSlice &lslice : below.lslices_ex) + std::sort(lslice.overlaps_above.begin(), lslice.overlaps_above.end(), [](const LayerSlice::Link &l, const LayerSlice::Link &r){ return l.slice_idx < r.slice_idx; }); + for (LayerSlice &lslice : above.lslices_ex) + std::sort(lslice.overlaps_below.begin(), lslice.overlaps_below.end(), [](const LayerSlice::Link &l, const LayerSlice::Link &r){ return l.slice_idx < r.slice_idx; }); +} + +void Layer::build_up_down_graph(Layer& below, Layer& above) +{ + coord_t paths_below_offset = 0; + ClipperLib_Z::Paths paths_below = expolygons_to_zpaths(below.lslices, paths_below_offset); + coord_t paths_above_offset = paths_below_offset + coord_t(below.lslices.size()); + ClipperLib_Z::Paths paths_above = expolygons_to_zpaths(above.lslices, paths_above_offset); + coord_t paths_end = paths_above_offset + coord_t(above.lslices.size()); + + class ZFill { + public: + ZFill() = default; + void reset() { m_intersections.clear(); } + void operator()( + const ClipperLib_Z::IntPoint& e1bot, const ClipperLib_Z::IntPoint& e1top, + const ClipperLib_Z::IntPoint& e2bot, const ClipperLib_Z::IntPoint& e2top, + ClipperLib_Z::IntPoint& pt) { + coord_t srcs[4]{ e1bot.z(), e1top.z(), e2bot.z(), e2top.z() }; + coord_t* begin = srcs; + coord_t* end = srcs + 4; + std::sort(begin, end); + end = std::unique(begin, end); + assert(begin + 2 == end); + if (begin + 1 == end) + pt.z() = *begin; + else if (begin + 2 <= end) { + // store a -1 based negative index into the "intersections" vector here. + m_intersections.emplace_back(srcs[0], srcs[1]); + pt.z() = -coord_t(m_intersections.size()); + } + } + const std::vector>& intersections() const { return m_intersections; } + + private: + std::vector> m_intersections; + } zfill; + + ClipperLib_Z::Clipper clipper; + ClipperLib_Z::PolyTree result; + clipper.ZFillFunction( + [&zfill](const ClipperLib_Z::IntPoint &e1bot, const ClipperLib_Z::IntPoint &e1top, + const ClipperLib_Z::IntPoint &e2bot, const ClipperLib_Z::IntPoint &e2top, ClipperLib_Z::IntPoint &pt) + { return zfill(e1bot, e1top, e2bot, e2top, pt); }); + clipper.AddPaths(paths_below, ClipperLib_Z::ptSubject, true); + clipper.AddPaths(paths_above, ClipperLib_Z::ptClip, true); + clipper.Execute(ClipperLib_Z::ctIntersection, result, ClipperLib_Z::pftNonZero, ClipperLib_Z::pftNonZero); + + connect_layer_slices(below, above, result, zfill.intersections(), paths_below_offset, paths_above_offset, paths_end); +} + static inline bool layer_needs_raw_backup(const Layer *layer) { return ! (layer->regions().size() == 1 && (layer->id() > 0 || layer->object()->config().elefant_foot_compensation.value == 0)); @@ -74,10 +313,10 @@ void Layer::backup_untyped_slices() { if (layer_needs_raw_backup(this)) { for (LayerRegion *layerm : m_regions) - layerm->raw_slices = to_expolygons(layerm->slices.surfaces); + layerm->m_raw_slices = to_expolygons(layerm->slices().surfaces); } else { assert(m_regions.size() == 1); - m_regions.front()->raw_slices.clear(); + m_regions.front()->m_raw_slices.clear(); } } @@ -85,10 +324,10 @@ void Layer::restore_untyped_slices() { if (layer_needs_raw_backup(this)) { for (LayerRegion *layerm : m_regions) - layerm->slices.set(layerm->raw_slices, stInternal); + layerm->m_slices.set(layerm->m_raw_slices, stInternal); } else { assert(m_regions.size() == 1); - m_regions.front()->slices.set(this->lslices, stInternal); + m_regions.front()->m_slices.set(this->lslices, stInternal); } } @@ -101,13 +340,13 @@ void Layer::restore_untyped_slices_no_extra_perimeters() if (layer_needs_raw_backup(this)) { for (LayerRegion *layerm : m_regions) if (! layerm->region().config().extra_perimeters.value) - layerm->slices.set(layerm->raw_slices, stInternal); + layerm->m_slices.set(layerm->m_raw_slices, stInternal); } else { assert(m_regions.size() == 1); LayerRegion *layerm = m_regions.front(); // This optimization is correct, as extra_perimeters are only reused by prepare_infill() with multi-regions. //if (! layerm->region().config().extra_perimeters.value) - layerm->slices.set(this->lslices, stInternal); + layerm->m_slices.set(this->lslices, stInternal); } } @@ -125,7 +364,7 @@ ExPolygons Layer::merged(float offset_scaled) const const PrintRegionConfig &config = layerm->region().config(); // Our users learned to bend Slic3r to produce empty volumes to act as subtracters. Only add the region if it is non-empty. if (config.bottom_solid_layers > 0 || config.top_solid_layers > 0 || config.fill_density > 0. || config.perimeters > 0) - append(polygons, offset(layerm->slices.surfaces, offset_scaled)); + append(polygons, offset(layerm->slices().surfaces, offset_scaled)); } ExPolygons out = union_ex(polygons); if (offset_scaled2 != 0.f) @@ -143,11 +382,12 @@ void Layer::make_perimeters() // keep track of regions whose perimeters we have already generated std::vector done(m_regions.size(), false); + LayerRegionPtrs layerms; for (LayerRegionPtrs::iterator layerm = m_regions.begin(); layerm != m_regions.end(); ++ layerm) - if ((*layerm)->slices.empty()) { - (*layerm)->perimeters.clear(); - (*layerm)->fills.clear(); - (*layerm)->thin_fills.clear(); + if ((*layerm)->slices().empty()) { + (*layerm)->m_perimeters.clear(); + (*layerm)->m_fills.clear(); + (*layerm)->m_thin_fills.clear(); } else { size_t region_id = layerm - m_regions.begin(); if (done[region_id]) @@ -157,10 +397,10 @@ void Layer::make_perimeters() const PrintRegionConfig &config = (*layerm)->region().config(); // find compatible regions - LayerRegionPtrs layerms; + layerms.clear(); layerms.push_back(*layerm); for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) - if (! (*it)->slices.empty()) { + if (! (*it)->slices().empty()) { LayerRegion* other_layerm = *it; const PrintRegionConfig &other_config = other_layerm->region().config(); if (config.perimeter_extruder == other_config.perimeter_extruder @@ -178,18 +418,20 @@ void Layer::make_perimeters() && config.fuzzy_skin_thickness == other_config.fuzzy_skin_thickness && config.fuzzy_skin_point_dist == other_config.fuzzy_skin_point_dist) { - other_layerm->perimeters.clear(); - other_layerm->fills.clear(); - other_layerm->thin_fills.clear(); + other_layerm->m_perimeters.clear(); + other_layerm->m_fills.clear(); + other_layerm->m_thin_fills.clear(); layerms.push_back(other_layerm); done[it - m_regions.begin()] = true; } } + SurfaceCollection fill_surfaces; 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); + (*layerm)->m_fill_expolygons.clear(); + (*layerm)->m_fill_surfaces.clear(); + (*layerm)->make_perimeters((*layerm)->slices(), &fill_surfaces); + (*layerm)->m_fill_expolygons = to_expolygons(fill_surfaces.surfaces); } else { 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. @@ -198,29 +440,25 @@ 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 (const Surface &surface : layerm->slices.surfaces) + for (const Surface &surface : layerm->slices()) slices[surface.extra_perimeters].emplace_back(surface); if (layerm->region().config().fill_density > layerm_config->region().config().fill_density) layerm_config = layerm; + layerm->m_fill_surfaces.clear(); + layerm->m_fill_expolygons.clear(); } // merge the surfaces assigned to each group for (std::pair &surfaces_with_extra_perimeters : slices) new_slices.append(offset_ex(surfaces_with_extra_perimeters.second, ClipperSafetyOffset), 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 - if (!fill_surfaces.surfaces.empty()) { - for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) { - // Separate the fill surfaces. - ExPolygons expp = intersection_ex(fill_surfaces.surfaces, (*l)->slices.surfaces); - (*l)->fill_expolygons = expp; - (*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front()); - } - } + if (! fill_surfaces.empty()) { + // Separate the fill surfaces. + for (LayerRegion *l : layerms) + l->m_fill_expolygons = intersection_ex(fill_surfaces.surfaces, l->slices().surfaces); + } } } BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << " - Done"; @@ -230,7 +468,7 @@ 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 auto &surface : region->slices()) 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)); @@ -239,7 +477,7 @@ 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 auto &surface : region->slices()) svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); export_surface_type_legend_to_svg(svg, legend_pos); svg.Close(); @@ -256,7 +494,7 @@ 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 auto &surface : region->slices()) 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)); @@ -265,7 +503,7 @@ 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 auto &surface : region->slices()) svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); export_surface_type_legend_to_svg(svg, legend_pos); svg.Close(); @@ -281,9 +519,9 @@ void Layer::export_region_fill_surfaces_to_svg_debug(const char *name) const BoundingBox get_extents(const LayerRegion &layer_region) { BoundingBox bbox; - if (!layer_region.slices.surfaces.empty()) { - bbox = get_extents(layer_region.slices.surfaces.front()); - for (auto it = layer_region.slices.surfaces.cbegin() + 1; it != layer_region.slices.surfaces.cend(); ++it) + if (! layer_region.slices().empty()) { + bbox = get_extents(layer_region.slices().surfaces.front()); + for (auto it = layer_region.slices().surfaces.cbegin() + 1; it != layer_region.slices().surfaces.cend(); ++ it) bbox.merge(get_extents(*it)); } return bbox; diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index e11c740e6..9a1a77aea 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -2,10 +2,13 @@ #define slic3r_Layer_hpp_ #include "libslic3r.h" +#include "BoundingBox.hpp" #include "Flow.hpp" #include "SurfaceCollection.hpp" #include "ExtrusionEntityCollection.hpp" +#include + namespace Slic3r { class ExPolygon; @@ -25,50 +28,38 @@ namespace FillLightning { class Generator; }; -namespace FillLightning { - class Generator; -}; - class LayerRegion { public: - Layer* layer() { return m_layer; } - const Layer* layer() const { return m_layer; } - const PrintRegion& region() const { return *m_region; } + [[nodiscard]] Layer* layer() { return m_layer; } + [[nodiscard]] const Layer* layer() const { return m_layer; } + [[nodiscard]] const PrintRegion& region() const { return *m_region; } // collection of surfaces generated by slicing the original geometry // divided by type top/bottom/internal - SurfaceCollection slices; - // Backed up slices before they are split into top/bottom/internal. - // Only backed up for multi-region layers or layers with elephant foot compensation. - //FIXME Review whether not to simplify the code by keeping the raw_slices all the time. - ExPolygons raw_slices; + [[nodiscard]] const SurfaceCollection& slices() const { return m_slices; } + + [[nodiscard]] const ExPolygons& fill_expolygons() const { return m_fill_expolygons; } + + // collection of surfaces generated by slicing the original geometry + // divided by type top/bottom/internal + [[nodiscard]] const SurfaceCollection& fill_surfaces() const { return m_fill_surfaces; } // collection of extrusion paths/loops filling gaps // These fills are generated by the perimeter generator. // They are not printed on their own, but they are copied to this->fills during infill generation. - ExtrusionEntityCollection thin_fills; - - // Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature") - // and for re-starting of infills. - ExPolygons fill_expolygons; - // collection of surfaces for infill generation - SurfaceCollection fill_surfaces; - - // collection of expolygons representing the bridged areas (thus not - // needing support material) -// Polygons bridged; + [[nodiscard]] const ExtrusionEntityCollection& thin_fills() const { return m_thin_fills; } // collection of polylines representing the unsupported bridge edges - Polylines unsupported_bridge_edges; + [[nodiscard]] const Polylines& unsupported_bridge_edges() const { return m_unsupported_bridge_edges; } // ordered collection of extrusion paths/loops to build all perimeters // (this collection contains only ExtrusionEntityCollection objects) - ExtrusionEntityCollection perimeters; + [[nodiscard]] const ExtrusionEntityCollection& perimeters() const { return m_perimeters; } // ordered collection of extrusion paths to fill surfaces // (this collection contains only ExtrusionEntityCollection objects) - ExtrusionEntityCollection fills; + [[nodiscard]] const ExtrusionEntityCollection& fills() const { return m_fills; } Flow flow(FlowRole role) const; Flow flow(FlowRole role, double layer_height) const; @@ -92,20 +83,165 @@ public: void export_region_fill_surfaces_to_svg_debug(const char *name) const; // Is there any valid extrusion assigned to this LayerRegion? - bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); } + bool has_extrusions() const { return ! this->perimeters().empty() || ! this->fills().empty(); } protected: friend class Layer; friend class PrintObject; LayerRegion(Layer *layer, const PrintRegion *region) : m_layer(layer), m_region(region) {} - ~LayerRegion() {} + ~LayerRegion() = default; private: - Layer *m_layer; - const PrintRegion *m_region; + // Modifying m_slices + friend std::string fix_slicing_errors(LayerPtrs&, const std::function&); + template + friend void apply_mm_segmentation(PrintObject& print_object, ThrowOnCancel throw_on_cancel); + + Layer *m_layer; + const PrintRegion *m_region; + + // Backed up slices before they are split into top/bottom/internal. + // Only backed up for multi-region layers or layers with elephant foot compensation. + //FIXME Review whether not to simplify the code by keeping the raw_slices all the time. + ExPolygons m_raw_slices; + +//FIXME make m_slices public for unit tests +public: + // collection of surfaces generated by slicing the original geometry + // divided by type top/bottom/internal + SurfaceCollection m_slices; + +private: + // Unspecified fill polygons, used for overhang detection ("ensure vertical wall thickness feature") + // and for re-starting of infills. + ExPolygons m_fill_expolygons; + + // collection of surfaces for infill generation + SurfaceCollection m_fill_surfaces; + + // collection of extrusion paths/loops filling gaps + // These fills are generated by the perimeter generator. + // They are not printed on their own, but they are copied to this->fills during infill generation. + ExtrusionEntityCollection m_thin_fills; + + // collection of polylines representing the unsupported bridge edges + Polylines m_unsupported_bridge_edges; + + // ordered collection of extrusion paths/loops to build all perimeters + // (this collection contains only ExtrusionEntityCollection objects) + ExtrusionEntityCollection m_perimeters; + + // ordered collection of extrusion paths to fill surfaces + // (this collection contains only ExtrusionEntityCollection objects) + ExtrusionEntityCollection m_fills; + + // collection of expolygons representing the bridged areas (thus not + // needing support material) +// Polygons bridged; }; +// Range of two indices, providing support for range based loops. +template +class IndexRange +{ +public: + IndexRange(T ibegin, T iend) : m_begin(ibegin), m_end(iend) {} + IndexRange() = default; + + T begin() const { assert(m_begin <= m_end); return m_begin; }; + T end() const { assert(m_begin <= m_end); return m_end; }; + + bool empty() const { assert(m_begin <= m_end); return m_begin >= m_end; } + T size() const { assert(m_begin <= m_end); return m_end - m_begin; } + +private: + // Index of the first extrusion in LayerRegion. + T m_begin { 0 }; + // Index of the last extrusion in LayerRegion. + T m_end { 0 }; +}; + +class LayerExtrusionRange : public IndexRange +{ +public: + LayerExtrusionRange(uint32_t iregion, uint32_t ibegin, uint32_t iend) : m_region(iregion), IndexRange(ibegin, iend) {} + LayerExtrusionRange() = default; + + // Index of LayerRegion in Layer. + uint32_t region() const { return m_region; }; + +private: + // Index of LayerRegion in Layer. + uint32_t m_region { 0 }; +}; + +static constexpr const size_t LayerExtrusionRangesStaticSize = 1; +using LayerExtrusionRanges = +#ifdef NDEBUG + // To reduce memory allocation in release mode. + boost::container::small_vector; +#else // NDEBUG + // To ease debugging. + std::vector; +#endif // NDEBUG + +using ExPolygonRange = IndexRange(); + +// LayerSlice contains one or more LayerIsland objects, +// each LayerIsland containing a set of perimeter extrusions extruded with one particular PrintRegionConfig parameters +// and one or multiple +struct LayerIsland +{ + // Perimeter extrusions in LayerRegion belonging to this island. + LayerExtrusionRange perimeters; + // Infill + gapfill extrusions in LayerRegion belonging to this island. + LayerExtrusionRanges fills; + // Region that is to be filled with the fills above. + ExPolygonRange fill_expolygons; + // Centroid of this island used for path planning. + Point centroid; + + bool has_extrusions() const { return ! this->perimeters.empty() || ! this->fills.empty(); } +}; + +static constexpr const size_t LayerIslandsStaticSize = 1; +using LayerIslands = +#ifdef NDEBUG + // To reduce memory allocation in release mode. + boost::container::small_vector; +#else // NDEBUG + // To ease debugging. + std::vector; +#endif // NDEBUG + +// +struct LayerSlice +{ + struct Link { + int32_t slice_idx; + float area; + }; + static constexpr const size_t LinksStaticSize = 4; + using Links = +#ifdef NDEBUG + // To reduce memory allocation in release mode. + boost::container::small_vector; +#else // NDEBUG + // To ease debugging. + std::vector; +#endif // NDEBUG + + BoundingBox bbox; + Links overlaps_above; + Links overlaps_below; + LayerIslands islands; + + bool has_extrusions() const { for (const LayerIsland &island : islands) if (island.has_extrusions()) return true; return false; } +}; + +using LayerSlices = std::vector; + class Layer { public: @@ -131,8 +267,8 @@ public: // order will be applied by the G-code generator to the extrusions fitting into these lslices. // These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important // that the 1st lslice is not compensated by the Elephant foot compensation algorithm. - ExPolygons lslices; - std::vector lslices_bboxes; + ExPolygons lslices; + LayerSlices lslices_ex; size_t region_count() const { return m_regions.size(); } const LayerRegion* get_region(int idx) const { return m_regions[idx]; } @@ -142,6 +278,8 @@ public: // Test whether whether there are any slices assigned to this layer. bool empty() const; void make_slices(); + // After creating the slices on all layers, chain the islands overlapping in Z. + static void build_up_down_graph(Layer &below, Layer &above); // Backup and restore raw sliced regions if needed. //FIXME Review whether not to simplify the code by keeping the raw_slices all the time. void backup_untyped_slices(); @@ -151,11 +289,11 @@ 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 { - for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_bottom_contains(item)) return true; + for (const LayerRegion *layerm : m_regions) if (layerm->slices().any_bottom_contains(item)) return true; return false; } void make_perimeters(); @@ -172,6 +310,7 @@ public: // Is there any valid extrusion assigned to this LayerRegion? virtual bool has_extrusions() const { for (auto layerm : m_regions) if (layerm->has_extrusions()) return true; return false; } +// virtual bool has_extrusions() const { for (const LayerSlice &lslice : lslices_ex) if (lslice.has_extrusions()) return true; return false; } protected: friend class PrintObject; diff --git a/src/libslic3r/LayerRegion.cpp b/src/libslic3r/LayerRegion.cpp index 1996a58b5..b0bfc961e 100644 --- a/src/libslic3r/LayerRegion.cpp +++ b/src/libslic3r/LayerRegion.cpp @@ -43,30 +43,26 @@ Flow LayerRegion::bridging_flow(FlowRole role) const } } -// Fill in layerm->fill_surfaces by trimming the layerm->slices by the cummulative layerm->fill_surfaces. +// Fill in layerm->fill_surfaces by trimming the layerm->slices by layerm->fill_expolygons. void LayerRegion::slices_to_fill_surfaces_clipped() { - // Note: this method should be idempotent, but fill_surfaces gets modified - // in place. However we're now only using its boundaries (which are invariant) - // so we're safe. This guarantees idempotence of prepare_infill() also in case - // that combine_infill() turns some fill_surface into VOID surfaces. // Collect polygons per surface type. - std::array by_surface; - for (Surface &surface : this->slices.surfaces) + std::array, size_t(stCount)> by_surface; + for (const Surface &surface : this->slices()) by_surface[size_t(surface.surface_type)].emplace_back(&surface); // Trim surfaces by the fill_boundaries. - this->fill_surfaces.surfaces.clear(); + m_fill_surfaces.surfaces.clear(); for (size_t surface_type = 0; surface_type < size_t(stCount); ++ surface_type) { - const SurfacesPtr &this_surfaces = by_surface[surface_type]; + const std::vector &this_surfaces = by_surface[surface_type]; if (! this_surfaces.empty()) - this->fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons), SurfaceType(surface_type)); + m_fill_surfaces.append(intersection_ex(this_surfaces, this->fill_expolygons()), SurfaceType(surface_type)); } } void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces) { - this->perimeters.clear(); - this->thin_fills.clear(); + m_perimeters.clear(); + m_thin_fills.clear(); const PrintConfig &print_config = this->layer()->object()->print()->config(); const PrintRegionConfig ®ion_config = this->region().config(); @@ -87,8 +83,8 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec spiral_vase, // output: - &this->perimeters, - &this->thin_fills, + &m_perimeters, + &m_thin_fills, fill_surfaces ); @@ -131,7 +127,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly // Internal surfaces, not grown. Surfaces internal; // Areas, where an infill of various types (top, bottom, bottom bride, sparse, void) could be placed. - Polygons fill_boundaries = to_polygons(this->fill_expolygons); + Polygons fill_boundaries = to_polygons(this->fill_expolygons()); Polygons lower_layer_covered_tmp; // Collect top surfaces and internal surfaces. @@ -141,7 +137,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly { // Voids are sparse infills if infill rate is zero. Polygons voids; - for (const Surface &surface : this->fill_surfaces.surfaces) { + for (const Surface &surface : this->fill_surfaces()) { if (surface.is_top()) { // Collect the top surfaces, inflate them and trim them by the bottom surfaces. // This gives the priority to bottom surfaces. @@ -292,7 +288,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly bridges[idx_last].bridge_angle = bd.angle; if (this->layer()->object()->has_support()) { // polygons_append(this->bridged, bd.coverage()); - append(this->unsupported_bridge_edges, bd.unsupported_edges()); + append(m_unsupported_bridge_edges, bd.unsupported_edges()); } } else if (custom_angle > 0) { // Bridge was not detected (likely it is only supported at one side). Still it is a surface filled in @@ -365,7 +361,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly surfaces_append(new_surfaces, std::move(new_expolys), s1); } - this->fill_surfaces.surfaces = std::move(new_surfaces); + m_fill_surfaces.surfaces = std::move(new_surfaces); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING export_region_fill_surfaces_to_svg_debug("3_process_external_surfaces-final"); @@ -389,12 +385,12 @@ void LayerRegion::prepare_fill_surfaces() // For Lightning infill, infill_only_where_needed is ignored because both // do a similar thing, and their combination doesn't make much sense. if (! spiral_vase && this->region().config().top_solid_layers == 0) { - for (Surface &surface : this->fill_surfaces.surfaces) + for (Surface &surface : m_fill_surfaces) if (surface.is_top()) surface.surface_type = this->layer()->object()->config().infill_only_where_needed && this->region().config().fill_pattern != ipLightning ? stInternalVoid : stInternal; } if (this->region().config().bottom_solid_layers == 0) { - for (Surface &surface : this->fill_surfaces.surfaces) + for (Surface &surface : m_fill_surfaces) if (surface.is_bottom()) // (surface.surface_type == stBottom) surface.surface_type = stInternal; } @@ -403,7 +399,7 @@ void LayerRegion::prepare_fill_surfaces() if (! spiral_vase && this->region().config().fill_density.value > 0) { // scaling an area requires two calls! double min_area = scale_(scale_(this->region().config().solid_infill_below_area.value)); - for (Surface &surface : this->fill_surfaces.surfaces) + for (Surface &surface : m_fill_surfaces) if (surface.surface_type == stInternal && surface.area() <= min_area) surface.surface_type = stInternalSolid; } @@ -423,38 +419,38 @@ double LayerRegion::infill_area_threshold() const void LayerRegion::trim_surfaces(const Polygons &trimming_polygons) { #ifndef NDEBUG - for (const Surface &surface : this->slices.surfaces) + for (const Surface &surface : this->slices()) assert(surface.surface_type == stInternal); #endif /* NDEBUG */ - this->slices.set(intersection_ex(this->slices.surfaces, trimming_polygons), stInternal); + m_slices.set(intersection_ex(this->slices().surfaces, trimming_polygons), stInternal); } void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons) { #ifndef NDEBUG - for (const Surface &surface : this->slices.surfaces) + for (const Surface &surface : this->slices()) assert(surface.surface_type == stInternal); #endif /* NDEBUG */ - Polygons tmp = intersection(this->slices.surfaces, trimming_polygons); - append(tmp, diff(this->slices.surfaces, opening(this->slices.surfaces, elephant_foot_compensation_perimeter_step))); - this->slices.set(union_ex(tmp), stInternal); + Polygons tmp = intersection(this->slices().surfaces, trimming_polygons); + append(tmp, diff(this->slices().surfaces, opening(this->slices().surfaces, elephant_foot_compensation_perimeter_step))); + m_slices.set(union_ex(tmp), stInternal); } 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()) + 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) - 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)); + for (const Surface &surface : this->slices()) + svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); + for (const Surface &surface : this->fill_surfaces()) + svg.draw(surface.expolygon.lines(), surface_type_to_color_name(surface.surface_type)); export_surface_type_legend_to_svg(svg, legend_pos); svg.Close(); } @@ -470,15 +466,15 @@ void LayerRegion::export_region_slices_to_svg_debug(const char *name) const void LayerRegion::export_region_fill_surfaces_to_svg(const char *path) const { BoundingBox bbox; - for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) - bbox.merge(get_extents(surface->expolygon)); + for (const Surface &surface : this->fill_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 (const Surface &surface : this->fill_surfaces.surfaces) { + for (const Surface &surface : this->fill_surfaces()) { svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency); svg.draw_outline(surface.expolygon, "black", "blue", scale_(0.05)); } diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 21b53c40d..661c2d0fd 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -713,7 +713,7 @@ struct MMU_Graph [[nodiscard]] const Vec2d &point_double() const { return m_point_double; } [[nodiscard]] const Point &point() const { return m_point; } - bool operator==(const CPoint &rhs) const { return this->m_point_double == rhs.m_point_double && this->m_contour_idx == rhs.m_contour_idx && this->m_point_idx == rhs.m_point_idx; } + bool operator==(const CPoint &rhs) const { return m_point_double == rhs.m_point_double && m_contour_idx == rhs.m_contour_idx && m_point_idx == rhs.m_point_idx; } }; struct CPointAccessor { const Point* operator()(const CPoint &pt) const { return &pt.point(); }}; typedef ClosestPointInRadiusLookup CPointLookupType; @@ -1697,7 +1697,7 @@ std::vector> multi_material_segmentation_by_painting(con throw_on_cancel_callback(); ExPolygons ex_polygons; for (LayerRegion *region : layers[layer_idx]->regions()) - for (const Surface &surface : region->slices.surfaces) + for (const Surface &surface : region->slices()) Slic3r::append(ex_polygons, offset_ex(surface.expolygon, float(10 * SCALED_EPSILON))); // All expolygons are expanded by SCALED_EPSILON, merged, and then shrunk again by SCALED_EPSILON // to ensure that very close polygons will be merged. diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index f0a81a71a..74ba2e0f5 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -418,7 +418,7 @@ public: size_t first_compatible_idx(PreferedCondition prefered_condition) const { size_t i = m_default_suppressed ? m_num_default_presets : 0; - size_t n = this->m_presets.size(); + size_t n = m_presets.size(); size_t i_compatible = n; int match_quality = -1; for (; i < n; ++ i) diff --git a/src/libslic3r/PrintBase.cpp b/src/libslic3r/PrintBase.cpp index b60401e96..b0aa7bd1e 100644 --- a/src/libslic3r/PrintBase.cpp +++ b/src/libslic3r/PrintBase.cpp @@ -103,7 +103,7 @@ std::string PrintBase::output_filepath(const std::string &path, const std::strin void PrintBase::status_update_warnings(int step, PrintStateBase::WarningLevel /* warning_level */, const std::string &message, const PrintObjectBase* print_object) { - if (this->m_status_callback) { + if (m_status_callback) { auto status = print_object ? SlicingStatus(*print_object, step) : SlicingStatus(*this, step); m_status_callback(status); } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index bdcb034ab..d3ac219b0 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -157,7 +157,7 @@ void PrintObject::make_perimeters() m_print->throw_if_canceled(); LayerRegion &layerm = *m_layers[layer_idx]->get_region(region_id); const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->get_region(region_id); - const Polygons upper_layerm_polygons = to_polygons(upper_layerm.slices.surfaces); + const Polygons upper_layerm_polygons = to_polygons(upper_layerm.slices().surfaces); // 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); @@ -166,7 +166,8 @@ 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) { + // slice is not const because slice.extra_perimeters is being incremented. + 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 @@ -418,7 +419,7 @@ void PrintObject::generate_support_spots() BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start"; m_print->set_status(75, L("Searching support spots")); - if (this->m_config.support_material && !this->m_config.support_material_auto && + if (m_config.support_material && !m_config.support_material_auto && std::all_of(this->model_object()->volumes.begin(), this->model_object()->volumes.end(), [](const ModelVolume* mv){return mv->supported_facets.empty();}) ) { @@ -500,7 +501,7 @@ std::pair PrintObject::prepare m_print->throw_if_canceled(); const Layer *layer = this->layers()[idx_layer]; for (const LayerRegion *layerm : layer->regions()) - for (const Surface &surface : layerm->fill_surfaces.surfaces) + for (const Surface &surface : layerm->fill_surfaces()) if (surface.surface_type == stInternalBridge) append(out, triangulate_expolygon_3d(surface.expolygon, layer->bottom_z())); } @@ -883,13 +884,13 @@ void PrintObject::detect_surfaces_type() Surfaces top; if (upper_layer) { ExPolygons upper_slices = interface_shells ? - diff_ex(layerm->slices.surfaces, upper_layer->m_regions[region_id]->slices.surfaces, ApplySafetyOffset::Yes) : - diff_ex(layerm->slices.surfaces, upper_layer->lslices, ApplySafetyOffset::Yes); + diff_ex(layerm->slices().surfaces, upper_layer->m_regions[region_id]->slices().surfaces, ApplySafetyOffset::Yes) : + diff_ex(layerm->slices().surfaces, upper_layer->lslices, ApplySafetyOffset::Yes); surfaces_append(top, opening_ex(upper_slices, offset), stTop); } 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->slices().surfaces; for (Surface &surface : top) surface.surface_type = stTop; } @@ -910,7 +911,7 @@ void PrintObject::detect_surfaces_type() surfaces_append( bottom, opening_ex( - diff_ex(layerm->slices.surfaces, lower_layer->lslices, ApplySafetyOffset::Yes), + diff_ex(layerm->slices().surfaces, lower_layer->lslices, ApplySafetyOffset::Yes), offset), surface_type_bottom_other); // if user requested internal shells, we need to identify surfaces @@ -922,8 +923,8 @@ void PrintObject::detect_surfaces_type() bottom, opening_ex( diff_ex( - intersection(layerm->slices.surfaces, lower_layer->lslices), // supported - lower_layer->m_regions[region_id]->slices.surfaces, + intersection(layerm->slices().surfaces, lower_layer->lslices), // supported + lower_layer->m_regions[region_id]->slices().surfaces, ApplySafetyOffset::Yes), offset), stBottom); @@ -932,7 +933,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 = stBottom; } @@ -961,13 +962,13 @@ void PrintObject::detect_surfaces_type() #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->slices().surfaces; Surfaces surfaces_backup; if (! interface_shells) { surfaces_backup = std::move(surfaces_out); surfaces_out.clear(); } - const Surfaces &surfaces_prev = interface_shells ? layerm->slices.surfaces : surfaces_backup; + const Surfaces &surfaces_prev = interface_shells ? layerm->slices().surfaces : surfaces_backup; // find internal surfaces (difference between top/bottom surfaces and others) { @@ -993,15 +994,15 @@ void PrintObject::detect_surfaces_type() if (interface_shells) { // Move surfaces_new to layerm->slices.surfaces for (size_t idx_layer = 0; idx_layer < num_layers; ++ idx_layer) - m_layers[idx_layer]->m_regions[region_id]->slices.surfaces = std::move(surfaces_new[idx_layer]); + m_layers[idx_layer]->m_regions[region_id]->m_slices.set(std::move(surfaces_new[idx_layer])); } if (spiral_vase) { if (num_layers > 1) // Turn the last bottom layer infill to a top infill, so it will be extruded with a proper pattern. - m_layers[num_layers - 1]->m_regions[region_id]->slices.set_type(stTop); + m_layers[num_layers - 1]->m_regions[region_id]->m_slices.set_type(stTop); for (size_t i = num_layers; i < m_layers.size(); ++ i) - m_layers[i]->m_regions[region_id]->slices.set_type(stInternal); + m_layers[i]->m_regions[region_id]->m_slices.set_type(stInternal); } BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << region_id << " - clipping in parallel - start"; @@ -1048,7 +1049,7 @@ void PrintObject::process_external_surfaces() bool expansions = false; bool voids = false; for (const LayerRegion *layerm : layer->regions()) { - for (const Surface &surface : layerm->fill_surfaces.surfaces) { + for (const Surface &surface : layerm->fill_surfaces()) { if (surface.surface_type == stInternal) voids = true; else @@ -1073,7 +1074,7 @@ void PrintObject::process_external_surfaces() Polygons voids; for (const LayerRegion *layerm : m_layers[layer_idx]->regions()) { if (layerm->region().config().fill_density.value == 0.) - for (const Surface &surface : layerm->fill_surfaces.surfaces) + for (const Surface &surface : layerm->fill_surfaces()) // Shrink the holes, let the layer above expand slightly inside the unsupported areas. polygons_append(voids, offset(surface.expolygon, unsupported_width)); } @@ -1102,7 +1103,7 @@ void PrintObject::process_external_surfaces() m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Processing external surfaces for region " << region_id << " in parallel - end"; } -} +} // void PrintObject::process_external_surfaces() void PrintObject::discover_vertical_shells() { @@ -1170,15 +1171,15 @@ void PrintObject::discover_vertical_shells() LayerRegion &layerm = *layer.m_regions[region_id]; float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f; // Top surfaces. - append(cache.top_surfaces, offset(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing)); - append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing)); + append(cache.top_surfaces, offset(layerm.slices().filter_by_type(stTop), min_perimeter_infill_spacing)); + append(cache.top_surfaces, offset(layerm.fill_surfaces().filter_by_type(stTop), min_perimeter_infill_spacing)); // Bottom surfaces. - append(cache.bottom_surfaces, offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing)); - append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing)); + append(cache.bottom_surfaces, offset(layerm.slices().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing)); + append(cache.bottom_surfaces, offset(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()) perimeters = std::max(perimeters, s.extra_perimeters); perimeters += layerm.region().config().perimeters.value; // Then calculate the infill offset. @@ -1189,7 +1190,7 @@ void PrintObject::discover_vertical_shells() 0.5f * float(extflow.scaled_width() + extflow.scaled_spacing()) + (float(perimeters) - 1.f) * flow.scaled_spacing()); perimeter_min_spacing = std::min(perimeter_min_spacing, float(std::min(extflow.scaled_spacing(), flow.scaled_spacing()))); } - polygons_append(cache.holes, to_polygons(layerm.fill_expolygons)); + polygons_append(cache.holes, to_polygons(layerm.fill_expolygons())); } // Save some computing time by reducing the number of polygons. cache.top_surfaces = union_(cache.top_surfaces); @@ -1242,15 +1243,15 @@ 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(layerm.slices.filter_by_type(stTop), min_perimeter_infill_spacing); - append(cache.top_surfaces, offset(layerm.fill_surfaces.filter_by_type(stTop), min_perimeter_infill_spacing)); + cache.top_surfaces = offset(layerm.slices().filter_by_type(stTop), min_perimeter_infill_spacing); + append(cache.top_surfaces, offset(layerm.fill_surfaces().filter_by_type(stTop), min_perimeter_infill_spacing)); // Bottom surfaces. - cache.bottom_surfaces = offset(layerm.slices.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing); - append(cache.bottom_surfaces, offset(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing)); + cache.bottom_surfaces = offset(layerm.slices().filter_by_types(surfaces_bottom, 2), min_perimeter_infill_spacing); + append(cache.bottom_surfaces, offset(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 region_id iterations. if (cache.holes.empty()) { for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) - polygons_append(cache.holes, to_polygons(layer.regions()[region_id]->fill_expolygons)); + polygons_append(cache.holes, to_polygons(layer.regions()[region_id]->fill_expolygons())); } } }); @@ -1407,14 +1408,14 @@ void PrintObject::discover_vertical_shells() // Trim the shells region by the internal & internal void surfaces. const SurfaceType surfaceTypesInternal[] = { stInternal, stInternalVoid, stInternalSolid }; - const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces.filter_by_types(surfaceTypesInternal, 3)); + const Polygons polygonsInternal = to_polygons(layerm->fill_surfaces().filter_by_types(surfaceTypesInternal, 3)); shell = intersection(shell, polygonsInternal, ApplySafetyOffset::Yes); polygons_append(shell, diff(polygonsInternal, holes)); if (shell.empty()) continue; // Append the internal solids, so they will be merged with the new ones. - polygons_append(shell, to_polygons(layerm->fill_surfaces.filter_by_type(stInternalSolid))); + polygons_append(shell, to_polygons(layerm->fill_surfaces().filter_by_type(stInternalSolid))); // These regions will be filled by a rectilinear full infill. Currently this type of infill // only fills regions, which fit at least a single line. To avoid gaps in the sparse infill, @@ -1461,8 +1462,8 @@ void PrintObject::discover_vertical_shells() #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ // Trim the internal & internalvoid by the shell. - Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces.filter_by_type(stInternal), shell); - Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces.filter_by_type(stInternalVoid), shell); + Slic3r::ExPolygons new_internal = diff_ex(layerm->fill_surfaces().filter_by_type(stInternal), shell); + Slic3r::ExPolygons new_internal_void = diff_ex(layerm->fill_surfaces().filter_by_type(stInternalVoid), shell); #ifdef SLIC3R_DEBUG_SLICE_PROCESSING { @@ -1474,10 +1475,10 @@ void PrintObject::discover_vertical_shells() // Assign resulting internal surfaces to layer. const SurfaceType surfaceTypesKeep[] = { stTop, stBottom, stBottomBridge }; - layerm->fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType)); - layerm->fill_surfaces.append(new_internal, stInternal); - layerm->fill_surfaces.append(new_internal_void, stInternalVoid); - layerm->fill_surfaces.append(new_internal_solid, stInternalSolid); + layerm->m_fill_surfaces.keep_types(surfaceTypesKeep, sizeof(surfaceTypesKeep)/sizeof(SurfaceType)); + layerm->m_fill_surfaces.append(new_internal, stInternal); + layerm->m_fill_surfaces.append(new_internal_void, stInternalVoid); + layerm->m_fill_surfaces.append(new_internal_solid, stInternalSolid); } // for each layer }); m_print->throw_if_canceled(); @@ -1491,7 +1492,7 @@ void PrintObject::discover_vertical_shells() } #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ } // for each region -} +} // void PrintObject::discover_vertical_shells() // This method applies bridge flow to the first internal solid layer above sparse infill. void PrintObject::bridge_over_infill() @@ -1514,7 +1515,7 @@ void PrintObject::bridge_over_infill() for (Layer *layer : m_layers) { Polygons sum; for (const LayerRegion *layerm : layer->m_regions) - layerm->fill_surfaces.filter_by_type(stInternal, &sum); + layerm->fill_surfaces().filter_by_type(stInternal, &sum); internals.emplace_back(std::move(sum)); } @@ -1531,7 +1532,7 @@ void PrintObject::bridge_over_infill() // Extract the stInternalSolid surfaces that might be transformed into bridges. ExPolygons internal_solid; - layerm->fill_surfaces.remove_type(stInternalSolid, &internal_solid); + layerm->m_fill_surfaces.remove_type(stInternalSolid, &internal_solid); if (internal_solid.empty()) // No internal solid -> no new bridges for this layer region. continue; @@ -1563,7 +1564,7 @@ void PrintObject::bridge_over_infill() if (to_bridge_pp.empty()) { // Restore internal_solid surfaces. for (ExPolygon &ex : internal_solid) - layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex))); + layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex))); continue; } // convert into ExPolygons @@ -1579,9 +1580,9 @@ void PrintObject::bridge_over_infill() to_bridge = intersection_ex(to_bridge, internal_solid, ApplySafetyOffset::Yes); // build the new collection of fill_surfaces for (ExPolygon &ex : to_bridge) - layerm->fill_surfaces.surfaces.push_back(Surface(stInternalBridge, std::move(ex))); + layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalBridge, std::move(ex))); for (ExPolygon &ex : not_to_bridge) - layerm->fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex))); + layerm->m_fill_surfaces.surfaces.push_back(Surface(stInternalSolid, std::move(ex))); /* # exclude infill from the layers below if needed # see discussion at https://github.com/alexrj/Slic3r/issues/240 @@ -1622,7 +1623,7 @@ void PrintObject::bridge_over_infill() m_print->throw_if_canceled(); } }); -} +} // void PrintObject::bridge_over_infill() static void clamp_exturder_to_default(ConfigOptionInt &opt, size_t num_extruders) { @@ -1829,7 +1830,7 @@ void PrintObject::clip_fill_surfaces() // Solid surfaces to be supported. Polygons overhangs; for (const LayerRegion *layerm : layer->m_regions) - for (const Surface &surface : layerm->fill_surfaces.surfaces) { + for (const Surface &surface : layerm->fill_surfaces()) { Polygons polygons = to_polygons(surface.expolygon); if (surface.is_solid()) polygons_append(overhangs, polygons); @@ -1838,7 +1839,7 @@ void PrintObject::clip_fill_surfaces() Polygons lower_layer_fill_surfaces; Polygons lower_layer_internal_surfaces; for (const LayerRegion *layerm : lower_layer->m_regions) - for (const Surface &surface : layerm->fill_surfaces.surfaces) { + for (const Surface &surface : layerm->fill_surfaces()) { Polygons polygons = to_polygons(surface.expolygon); if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid) polygons_append(lower_layer_internal_surfaces, polygons); @@ -1873,12 +1874,12 @@ void PrintObject::clip_fill_surfaces() continue; SurfaceType internal_surface_types[] = { stInternal, stInternalVoid }; Polygons internal; - for (Surface &surface : layerm->fill_surfaces.surfaces) + for (Surface &surface : layerm->m_fill_surfaces.surfaces) if (surface.surface_type == stInternal || surface.surface_type == stInternalVoid) polygons_append(internal, std::move(surface.expolygon)); - layerm->fill_surfaces.remove_types(internal_surface_types, 2); - layerm->fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal); - layerm->fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid); + layerm->m_fill_surfaces.remove_types(internal_surface_types, 2); + layerm->m_fill_surfaces.append(intersection_ex(internal, upper_internal, ApplySafetyOffset::Yes), stInternal); + layerm->m_fill_surfaces.append(diff_ex (internal, upper_internal, ApplySafetyOffset::Yes), stInternalVoid); // If there are voids it means that our internal infill is not adjacent to // perimeters. In this case it would be nice to add a loop around infill to // make it more robust and nicer. TODO. @@ -1888,7 +1889,7 @@ void PrintObject::clip_fill_surfaces() } m_print->throw_if_canceled(); } -} +} // void PrintObject::clip_fill_surfaces() void PrintObject::discover_horizontal_shells() { @@ -1904,7 +1905,7 @@ void PrintObject::discover_horizontal_shells() (i % region_config.solid_infill_every_layers) == 0) { // Insert a solid internal layer. Mark stInternal surfaces as stInternalSolid or stInternalBridge. SurfaceType type = (region_config.fill_density == 100 || region_config.solid_infill_every_layers == 1) ? stInternalSolid : stInternalBridge; - for (Surface &surface : layerm->fill_surfaces.surfaces) + for (Surface &surface : layerm->m_fill_surfaces.surfaces) if (surface.surface_type == stInternal) surface.surface_type = type; } @@ -1935,11 +1936,11 @@ 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()) if (surface.surface_type == type) polygons_append(solid, to_polygons(surface.expolygon)); // Infill areas (slices without the perimeters). - for (const Surface &surface : layerm->fill_surfaces.surfaces) + for (const Surface &surface : layerm->fill_surfaces()) if (surface.surface_type == type) polygons_append(solid, to_polygons(surface.expolygon)); if (solid.empty()) @@ -1972,7 +1973,7 @@ void PrintObject::discover_horizontal_shells() Polygons new_internal_solid; { Polygons internal; - for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces) + for (const Surface &surface : neighbor_layerm->fill_surfaces()) if (surface.surface_type == stInternal || surface.surface_type == stInternalSolid) polygons_append(internal, to_polygons(surface.expolygon)); new_internal_solid = intersection(solid, internal, ApplySafetyOffset::Yes); @@ -2028,7 +2029,7 @@ void PrintObject::discover_horizontal_shells() // additional area in the next shell too // make sure our grown surfaces don't exceed the fill area Polygons internal; - for (const Surface &surface : neighbor_layerm->fill_surfaces.surfaces) + for (const Surface &surface : neighbor_layerm->fill_surfaces()) if (surface.is_internal() && !surface.is_bridge()) polygons_append(internal, to_polygons(surface.expolygon)); polygons_append(new_internal_solid, @@ -2047,16 +2048,16 @@ void PrintObject::discover_horizontal_shells() // internal-solid are the union of the existing internal-solid surfaces // and new ones - SurfaceCollection backup = std::move(neighbor_layerm->fill_surfaces); + SurfaceCollection backup = std::move(neighbor_layerm->m_fill_surfaces); polygons_append(new_internal_solid, to_polygons(backup.filter_by_type(stInternalSolid))); ExPolygons internal_solid = union_ex(new_internal_solid); // assign new internal-solid surfaces to layer - neighbor_layerm->fill_surfaces.set(internal_solid, stInternalSolid); + neighbor_layerm->m_fill_surfaces.set(internal_solid, stInternalSolid); // subtract intersections from layer surfaces to get resulting internal surfaces Polygons polygons_internal = to_polygons(std::move(internal_solid)); ExPolygons internal = diff_ex(backup.filter_by_type(stInternal), polygons_internal, ApplySafetyOffset::Yes); // assign resulting internal surfaces to layer - neighbor_layerm->fill_surfaces.append(internal, stInternal); + neighbor_layerm->m_fill_surfaces.append(internal, stInternal); polygons_append(polygons_internal, to_polygons(std::move(internal))); // assign top and bottom surfaces to layer SurfaceType surface_types_solid[] = { stTop, stBottom, stBottomBridge }; @@ -2064,7 +2065,7 @@ void PrintObject::discover_horizontal_shells() std::vector top_bottom_groups; backup.group(&top_bottom_groups); for (SurfacesPtr &group : top_bottom_groups) - neighbor_layerm->fill_surfaces.append( + neighbor_layerm->m_fill_surfaces.append( diff_ex(group, polygons_internal), // Use an existing surface as a template, it carries the bridge angle etc. *group.front()); @@ -2083,7 +2084,7 @@ void PrintObject::discover_horizontal_shells() } // for each layer } // for each region #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ -} +} // void PrintObject::discover_horizontal_shells() // 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 @@ -2141,10 +2142,10 @@ void PrintObject::combine_infill() layerms.emplace_back(m_layers[i]->regions()[region_id]); // We need to perform a multi-layer intersection, so let's split it in pairs. // Initialize the intersection with the candidates of the lowest layer. - ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces.filter_by_type(stInternal)); + ExPolygons intersection = to_expolygons(layerms.front()->fill_surfaces().filter_by_type(stInternal)); // Start looping from the second layer and intersect the current intersection with it. for (size_t i = 1; i < layerms.size(); ++ i) - intersection = intersection_ex(layerms[i]->fill_surfaces.filter_by_type(stInternal), intersection); + intersection = intersection_ex(layerms[i]->fill_surfaces().filter_by_type(stInternal), intersection); double area_threshold = layerms.front()->infill_area_threshold(); if (! intersection.empty() && area_threshold > 0.) intersection.erase(std::remove_if(intersection.begin(), intersection.end(), @@ -2173,9 +2174,9 @@ void PrintObject::combine_infill() for (ExPolygon &expoly : intersection) polygons_append(intersection_with_clearance, offset(expoly, clearance_offset)); for (LayerRegion *layerm : layerms) { - Polygons internal = to_polygons(std::move(layerm->fill_surfaces.filter_by_type(stInternal))); - layerm->fill_surfaces.remove_type(stInternal); - layerm->fill_surfaces.append(diff_ex(internal, intersection_with_clearance), stInternal); + Polygons internal = to_polygons(std::move(layerm->fill_surfaces().filter_by_type(stInternal))); + layerm->m_fill_surfaces.remove_type(stInternal); + layerm->m_fill_surfaces.append(diff_ex(internal, intersection_with_clearance), stInternal); if (layerm == layerms.back()) { // Apply surfaces back with adjusted depth to the uppermost layer. Surface templ(stInternal, ExPolygon()); @@ -2183,17 +2184,17 @@ void PrintObject::combine_infill() for (LayerRegion *layerm2 : layerms) templ.thickness += layerm2->layer()->height; templ.thickness_layers = (unsigned short)layerms.size(); - layerm->fill_surfaces.append(intersection, templ); + layerm->m_fill_surfaces.append(intersection, templ); } else { // Save void surfaces. - layerm->fill_surfaces.append( + layerm->m_fill_surfaces.append( intersection_ex(internal, intersection_with_clearance), stInternalVoid); } } } } -} +} // void PrintObject::combine_infill() void PrintObject::_generate_support_material() { diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 4b91714e5..f5ba3b9d7 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -432,12 +432,12 @@ std::string fix_slicing_errors(LayerPtrs &layers, const std::function &t const Surfaces *lower_surfaces = nullptr; for (size_t j = idx_layer + 1; j < layers.size(); ++ j) if (! layers[j]->slicing_errors) { - upper_surfaces = &layers[j]->regions()[region_id]->slices.surfaces; + upper_surfaces = &layers[j]->regions()[region_id]->slices().surfaces; break; } for (int j = int(idx_layer) - 1; j >= 0; -- j) if (! layers[j]->slicing_errors) { - lower_surfaces = &layers[j]->regions()[region_id]->slices.surfaces; + lower_surfaces = &layers[j]->regions()[region_id]->slices().surfaces; break; } // Collect outer contours and holes from the valid layers above & below. @@ -464,7 +464,7 @@ std::string fix_slicing_errors(LayerPtrs &layers, const std::function &t if (lower_surfaces) for (const auto &surface : *lower_surfaces) polygons_append(holes, surface.expolygon.holes); - layerm->slices.set(diff_ex(union_(outer), holes), stInternal); + layerm->m_slices.set(diff_ex(union_(outer), holes), stInternal); } // Update layer slices after repairing the single regions. layer->make_slices(); @@ -517,17 +517,26 @@ void PrintObject::slice() // Update bounding boxes, back up raw slices of complex models. tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), - [this](const tbb::blocked_range& range) { + [this](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { m_print->throw_if_canceled(); Layer &layer = *m_layers[layer_idx]; - layer.lslices_bboxes.clear(); - layer.lslices_bboxes.reserve(layer.lslices.size()); + layer.lslices_ex.clear(); + layer.lslices_ex.reserve(layer.lslices.size()); for (const ExPolygon &expoly : layer.lslices) - layer.lslices_bboxes.emplace_back(get_extents(expoly)); + layer.lslices_ex.push_back({ get_extents(expoly) }); layer.backup_untyped_slices(); } }); + // Interlink the lslices into a Z graph. + tbb::parallel_for( + tbb::blocked_range(1, m_layers.size()), + [this](const tbb::blocked_range &range) { + for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) { + m_print->throw_if_canceled(); + Layer::build_up_down_graph(*m_layers[layer_idx - 1], *m_layers[layer_idx]); + } + }); if (m_layers.empty()) throw Slic3r::SlicingError("No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n"); this->set_done(posSlice); @@ -579,9 +588,9 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance // layer_range.painted_regions are sorted by extruder ID and parent PrintObject region ID. auto it_painted_region = layer_range.painted_regions.begin(); for (int region_id = 0; region_id < int(layer->region_count()); ++ region_id) - if (LayerRegion &layerm = *layer->get_region(region_id); ! layerm.slices.surfaces.empty()) { + if (LayerRegion &layerm = *layer->get_region(region_id); ! layerm.slices().empty()) { assert(layerm.region().print_object_region_id() == region_id); - const BoundingBox bbox = get_extents(layerm.slices.surfaces); + const BoundingBox bbox = get_extents(layerm.slices().surfaces); assert(it_painted_region < layer_range.painted_regions.end()); // Find the first it_painted_region which overrides this region. for (; layer_range.volume_regions[it_painted_region->parent].region->print_object_region_id() < region_id; ++ it_painted_region) @@ -604,7 +613,7 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance } // Steal from this region. int target_region_id = it_painted_region->region->print_object_region_id(); - ExPolygons stolen = intersection_ex(layerm.slices.surfaces, segmented.expolygons); + ExPolygons stolen = intersection_ex(layerm.slices().surfaces, segmented.expolygons); if (! stolen.empty()) { ByRegion &dst = by_region[target_region_id]; if (dst.expolygons.empty()) { @@ -622,7 +631,7 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance } if (! self_trimmed) { // Trim slices of this LayerRegion with all the MMU regions. - Polygons mine = to_polygons(std::move(layerm.slices.surfaces)); + Polygons mine = to_polygons(std::move(layerm.slices().surfaces)); for (auto &segmented : by_extruder) if (&segmented - by_extruder.data() + 1 != self_extruder_id && segmented.bbox.defined && bbox.overlap(segmented.bbox)) { mine = diff(mine, segmented.expolygons); @@ -653,7 +662,7 @@ static inline void apply_mm_segmentation(PrintObject &print_object, ThrowOnCance if (src.needs_merge) // Multiple regions were merged into one. src.expolygons = closing_ex(src.expolygons, float(scale_(10 * EPSILON))); - layer->get_region(region_id)->slices.set(std::move(src.expolygons), stInternal); + layer->get_region(region_id)->m_slices.set(std::move(src.expolygons), stInternal); } } }); @@ -693,7 +702,7 @@ void PrintObject::slice_volumes() for (size_t region_id = 0; region_id < region_slices.size(); ++ region_id) { std::vector &by_layer = region_slices[region_id]; for (size_t layer_id = 0; layer_id < by_layer.size(); ++ layer_id) - m_layers[layer_id]->regions()[region_id]->slices.append(std::move(by_layer[layer_id]), stInternal); + m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(by_layer[layer_id]), stInternal); } region_slices.clear(); @@ -754,14 +763,14 @@ void PrintObject::slice_volumes() LayerRegion *layerm = layer->m_regions.front(); if (elfoot > 0) { // Apply the elephant foot compensation and store the 1st layer slices without the Elephant foot compensation applied. - lslices_1st_layer = to_expolygons(std::move(layerm->slices.surfaces)); + lslices_1st_layer = to_expolygons(std::move(layerm->m_slices.surfaces)); float delta = xy_compensation_scaled; if (delta > elfoot) { delta -= elfoot; elfoot = 0.f; } else if (delta > 0) elfoot -= delta; - layerm->slices.set( + layerm->m_slices.set( union_ex( Slic3r::elephant_foot_compensation( (delta == 0.f) ? lslices_1st_layer : offset_ex(lslices_1st_layer, delta), @@ -771,8 +780,8 @@ void PrintObject::slice_volumes() lslices_1st_layer = offset_ex(std::move(lslices_1st_layer), xy_compensation_scaled); } else if (xy_compensation_scaled < 0.f) { // Apply the XY compensation. - layerm->slices.set( - offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), xy_compensation_scaled), + layerm->m_slices.set( + offset_ex(to_expolygons(std::move(layerm->m_slices.surfaces)), xy_compensation_scaled), stInternal); } } else { diff --git a/src/libslic3r/SLA/DefaultSupportTree.cpp b/src/libslic3r/SLA/DefaultSupportTree.cpp index 8634fc3bb..9e21fca45 100644 --- a/src/libslic3r/SLA/DefaultSupportTree.cpp +++ b/src/libslic3r/SLA/DefaultSupportTree.cpp @@ -180,7 +180,7 @@ bool DefaultSupportTree::interconnect(const Pillar &pillar, Vec3d eupper = pillar.endpoint(); Vec3d elower = nextpillar.endpoint(); - double zmin = ground_level(this->m_sm) + m_sm.cfg.base_height_mm; + double zmin = ground_level(m_sm) + m_sm.cfg.base_height_mm; eupper.z() = std::max(eupper.z(), zmin); elower.z() = std::max(elower.z(), zmin); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index c4a4efbf2..7242bee3e 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -650,14 +650,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()) 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()) if (surface.surface_type == surface_type) polygons_append(out, surface.expolygon); return out; @@ -1213,9 +1213,9 @@ namespace SupportMaterialInternal { static bool has_bridging_extrusions(const Layer &layer) { for (const LayerRegion *region : layer.regions()) { - if (SupportMaterialInternal::has_bridging_perimeters(region->perimeters)) + if (SupportMaterialInternal::has_bridging_perimeters(region->perimeters())) return true; - if (region->fill_surfaces.has(stBottomBridge) && has_bridging_fills(region->fills)) + if (region->fill_surfaces().has(stBottomBridge) && has_bridging_fills(region->fills())) return true; } return false; @@ -1287,7 +1287,7 @@ namespace SupportMaterialInternal { // Trim the perimeters of this layer by the lower layer to get the unsupported pieces of perimeters. overhang_perimeters = diff_pl(overhang_perimeters, lower_grown_slices); #else - Polylines overhang_perimeters = diff_pl(layerm.perimeters.as_polylines(), lower_grown_slices); + Polylines overhang_perimeters = diff_pl(layerm.perimeters().as_polylines(), lower_grown_slices); #endif // only consider straight overhangs @@ -1311,7 +1311,7 @@ namespace SupportMaterialInternal { bool supported[2] = { false, false }; for (size_t i = 0; i < lower_layer.lslices.size() && ! (supported[0] && supported[1]); ++ i) for (int j = 0; j < 2; ++ j) - if (! supported[j] && lower_layer.lslices_bboxes[i].contains(pts[j]) && lower_layer.lslices[i].contains(pts[j])) + if (! supported[j] && lower_layer.lslices_ex[i].bbox.contains(pts[j]) && lower_layer.lslices[i].contains(pts[j])) supported[j] = true; if (supported[0] && supported[1]) // Offset a polyline into a thick line. @@ -1321,7 +1321,7 @@ namespace SupportMaterialInternal { } // remove the entire bridges and only support the unsupported edges //FIXME the brided regions are already collected as layerm.bridged. Use it? - for (const Surface &surface : layerm.fill_surfaces.surfaces) + for (const Surface &surface : layerm.fill_surfaces()) if (surface.surface_type == stBottomBridge && surface.bridge_angle != -1) polygons_append(bridges, surface.expolygon); //FIXME add the gap filled areas. Extrude the gaps with a bridge flow? @@ -1329,14 +1329,14 @@ namespace SupportMaterialInternal { //FIXME add supports at regular intervals to support long bridges! bridges = diff(bridges, // Offset unsupported edges into polygons. - offset(layerm.unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)); + offset(layerm.unsupported_bridge_edges(), scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)); // Remove bridged areas from the supported areas. contact_polygons = diff(contact_polygons, bridges, ApplySafetyOffset::Yes); #ifdef SLIC3R_DEBUG static int iRun = 0; SVG::export_expolygons(debug_out_path("support-top-contacts-remove-bridges-run%d.svg", iRun ++), - { { { union_ex(offset(layerm.unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)) }, { "unsupported_bridge_edges", "orange", 0.5f } }, + { { { union_ex(offset(layerm.unsupported_bridge_edges(), scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)) }, { "unsupported_bridge_edges", "orange", 0.5f } }, { { union_ex(contact_polygons) }, { "contact_polygons", "blue", 0.5f } }, { { union_ex(bridges) }, { "bridges", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ @@ -1487,7 +1487,7 @@ static inline std::tuple detect_overhangs( 0.5f * fw); // Overhang polygons for this layer and region. Polygons diff_polygons; - Polygons layerm_polygons = to_polygons(layerm->slices.surfaces); + Polygons layerm_polygons = to_polygons(layerm->slices().surfaces); if (lower_layer_offset == 0.f) { // Support everything. diff_polygons = diff(layerm_polygons, lower_layer_polygons); @@ -2858,10 +2858,10 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( break; some_region_overlaps = true; polygons_append(polygons_trimming, - offset(region->fill_surfaces.filter_by_type(stBottomBridge), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); + offset(region->fill_surfaces().filter_by_type(stBottomBridge), gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS)); if (region->region().config().overhangs.value) // Add bridging perimeters. - SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming); + SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters(), gap_xy_scaled, polygons_trimming); } if (! some_region_overlaps) break; diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 09b2bc5ae..8dd4a013d 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -1039,12 +1039,12 @@ std::tuple> check_extrusions_and_build_graph(c // PREPARE BASE LAYER const Layer *layer = po->layers()[0]; for (const LayerRegion *layer_region : layer->regions()) { - for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { + for (const ExtrusionEntity *ex_entity : layer_region->perimeters()) { for (const ExtrusionEntity *perimeter : static_cast(ex_entity)->entities) { push_lines(perimeter, layer_lines); } // perimeter } // ex_entity - for (const ExtrusionEntity *ex_entity : layer_region->fills.entities) { + for (const ExtrusionEntity *ex_entity : layer_region->fills()) { for (const ExtrusionEntity *fill : static_cast(ex_entity)->entities) { push_lines(fill, layer_lines); } // fill @@ -1083,13 +1083,13 @@ std::tuple> check_extrusions_and_build_graph(c for (size_t layer_idx = 1; layer_idx < po->layer_count(); ++layer_idx) { const Layer *layer = po->layers()[layer_idx]; for (const LayerRegion *layer_region : layer->regions()) { - for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { + for (const ExtrusionEntity *ex_entity : layer_region->perimeters()) { for (const ExtrusionEntity *perimeter : static_cast(ex_entity)->entities) { check_extrusion_entity_stability(perimeter, layer_lines, layer->slice_z, layer_region, external_lines, issues, params); } // perimeter } // ex_entity - for (const ExtrusionEntity *ex_entity : layer_region->fills.entities) { + for (const ExtrusionEntity *ex_entity : layer_region->fills()) { for (const ExtrusionEntity *fill : static_cast(ex_entity)->entities) { if (fill->role() == ExtrusionRole::erGapFill || fill->role() == ExtrusionRole::erBridgeInfill) { diff --git a/src/libslic3r/Surface.hpp b/src/libslic3r/Surface.hpp index ef1de30e9..4afcdf6f5 100644 --- a/src/libslic3r/Surface.hpp +++ b/src/libslic3r/Surface.hpp @@ -104,7 +104,7 @@ public: }; typedef std::vector Surfaces; -typedef std::vector SurfacesPtr; +typedef std::vector SurfacesPtr; inline Polygons to_polygons(const Surface &surface) { @@ -221,6 +221,7 @@ inline void polygons_append(Polygons &dst, const SurfacesPtr &src) } } +/* inline void polygons_append(Polygons &dst, SurfacesPtr &&src) { dst.reserve(dst.size() + number_polygons(src)); @@ -230,6 +231,7 @@ inline void polygons_append(Polygons &dst, SurfacesPtr &&src) (*it)->expolygon.holes.clear(); } } +*/ // Append a vector of Surfaces at the end of another vector of polygons. inline void surfaces_append(Surfaces &dst, const ExPolygons &src, SurfaceType surfaceType) diff --git a/src/libslic3r/SurfaceCollection.cpp b/src/libslic3r/SurfaceCollection.cpp index 2ec071f7d..10a12b683 100644 --- a/src/libslic3r/SurfaceCollection.cpp +++ b/src/libslic3r/SurfaceCollection.cpp @@ -22,46 +22,45 @@ void SurfaceCollection::simplify(double tolerance) } /* group surfaces by common properties */ -void SurfaceCollection::group(std::vector *retval) +void SurfaceCollection::group(std::vector *retval) const { - for (Surfaces::iterator it = this->surfaces.begin(); it != this->surfaces.end(); ++it) { + for (const Surface &surface : this->surfaces) { // find a group with the same properties - SurfacesPtr* group = NULL; + SurfacesPtr *group = nullptr; for (std::vector::iterator git = retval->begin(); git != retval->end(); ++git) - if (! git->empty() && surfaces_could_merge(*git->front(), *it)) { + if (! git->empty() && surfaces_could_merge(*git->front(), surface)) { group = &*git; break; } // if no group with these properties exists, add one - if (group == NULL) { + if (group == nullptr) { retval->resize(retval->size() + 1); group = &retval->back(); } // append surface to group - group->push_back(&*it); + group->push_back(&surface); } } -SurfacesPtr SurfaceCollection::filter_by_type(const SurfaceType type) +SurfacesPtr 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); - } + for (const Surface &surface : this->surfaces) + if (surface.surface_type == type) + ss.push_back(&surface); return ss; } -SurfacesPtr SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) +SurfacesPtr SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) const { SurfacesPtr ss; - for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) { + 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; } } - } return ss; } diff --git a/src/libslic3r/SurfaceCollection.hpp b/src/libslic3r/SurfaceCollection.hpp index 8c27a507b..b81808b32 100644 --- a/src/libslic3r/SurfaceCollection.hpp +++ b/src/libslic3r/SurfaceCollection.hpp @@ -17,7 +17,7 @@ public: SurfaceCollection(Surfaces &&surfaces) : surfaces(std::move(surfaces)) {}; void simplify(double tolerance); - void group(std::vector *retval); + void group(std::vector *retval) const; template bool any_internal_contains(const T &item) const { for (const Surface &surface : this->surfaces) if (surface.is_internal() && surface.expolygon.contains(item)) return true; return false; @@ -26,8 +26,8 @@ public: for (const Surface &surface : this->surfaces) if (surface.is_bottom() && surface.expolygon.contains(item)) return true; return false; } - SurfacesPtr filter_by_type(const SurfaceType type); - SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes); + SurfacesPtr filter_by_type(const SurfaceType type) const; + SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes) const; void keep_type(const SurfaceType type); void keep_types(const SurfaceType *types, int ntypes); void remove_type(const SurfaceType type); @@ -48,6 +48,13 @@ public: return false; } + Surfaces::const_iterator cbegin() const { return this->surfaces.cbegin(); } + Surfaces::const_iterator cend() const { return this->surfaces.cend(); } + Surfaces::const_iterator begin() const { return this->surfaces.cbegin(); } + Surfaces::const_iterator end() const { return this->surfaces.cend(); } + Surfaces::iterator begin() { return this->surfaces.begin(); } + Surfaces::iterator end() { return this->surfaces.end(); } + void set(const SurfaceCollection &coll) { surfaces = coll.surfaces; } void set(SurfaceCollection &&coll) { surfaces = std::move(coll.surfaces); } void set(const ExPolygons &src, SurfaceType surfaceType) { clear(); this->append(src, surfaceType); } diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index df820fac9..97175ea89 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -284,7 +284,7 @@ void TriangleMesh::rotate(float angle, const Axis &axis) case Z: its_rotate_z(this->its, angle); break; default: assert(false); return; } - update_bounding_box(this->its, this->m_stats); + update_bounding_box(this->its, m_stats); } } @@ -295,7 +295,7 @@ void TriangleMesh::rotate(float angle, const Vec3d& axis) Transform3d m = Transform3d::Identity(); m.rotate(Eigen::AngleAxisd(angle, axis_norm)); its_transform(its, m); - update_bounding_box(this->its, this->m_stats); + update_bounding_box(this->its, m_stats); } } @@ -334,7 +334,7 @@ void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed) det = -det; } m_stats.volume *= det; - update_bounding_box(this->its, this->m_stats); + update_bounding_box(this->its, m_stats); } void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed) @@ -346,7 +346,7 @@ void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed) det = -det; } m_stats.volume *= det; - update_bounding_box(this->its, this->m_stats); + update_bounding_box(this->its, m_stats); } void TriangleMesh::flip_triangles() @@ -512,7 +512,7 @@ std::vector TriangleMesh::slice(const std::vector &z) const size_t TriangleMesh::memsize() const { - size_t memsize = 8 + this->its.memsize() + sizeof(this->m_stats); + size_t memsize = 8 + this->its.memsize() + sizeof(m_stats); return memsize; } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index f30776307..6be4c4173 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -92,7 +92,7 @@ public: TriangleMesh(std::vector &&vertices, const std::vector &&faces); explicit TriangleMesh(const indexed_triangle_set &M); explicit TriangleMesh(indexed_triangle_set &&M, const RepairedMeshErrors& repaired_errors = RepairedMeshErrors()); - void clear() { this->its.clear(); this->m_stats.clear(); } + void clear() { this->its.clear(); m_stats.clear(); } bool ReadSTLFile(const char* input_file, bool repair = true); bool write_ascii(const char* output_file); bool write_binary(const char* output_file); diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 820c26acc..90f77d738 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -371,7 +371,7 @@ std::pair, std::vector> TriangleSelector::precompute_a { std::vector neighbors(m_triangles.size(), Vec3i(-1, -1, -1)); std::vector neighbors_propagated(m_triangles.size(), Vec3i(-1, -1, -1)); - for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) { + for (int facet_idx = 0; facet_idx < m_orig_size_indices; ++facet_idx) { neighbors[facet_idx] = m_neighbors[facet_idx]; neighbors_propagated[facet_idx] = neighbors[facet_idx]; assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx])); @@ -1480,7 +1480,7 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const std::vector TriangleSelector::get_seed_fill_contour() const { std::vector edges_out; - for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) { + for (int facet_idx = 0; facet_idx < m_orig_size_indices; ++facet_idx) { const Vec3i neighbors = m_neighbors[facet_idx]; assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors)); this->get_seed_fill_contour_recursive(facet_idx, neighbors, neighbors, edges_out); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f77eed369..c1e740672 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -7165,7 +7165,7 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c if (is_selected_separate_extruder) { bool at_least_one_has_correct_extruder = false; for (const LayerRegion* layerm : layer->regions()) { - if (layerm->slices.surfaces.empty()) + if (layerm->slices().empty()) continue; const PrintRegionConfig& cfg = layerm->region().config(); if (cfg.perimeter_extruder.value == m_selected_extruder || @@ -7208,14 +7208,14 @@ void GLCanvas3D::_load_print_object_toolpaths(const PrintObject& print_object, c } if (ctxt.has_perimeters) #if ENABLE_LEGACY_OPENGL_REMOVAL - _3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, + _3DScene::extrusionentity_to_verts(layerm->perimeters(), float(layer->print_z), copy, select_geometry(idx_layer, layerm->region().config().perimeter_extruder.value, 0)); #else _3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy, volume(idx_layer, layerm->region().config().perimeter_extruder.value, 0)); #endif // ENABLE_LEGACY_OPENGL_REMOVAL if (ctxt.has_infill) { - for (const ExtrusionEntity *ee : layerm->fills.entities) { + for (const ExtrusionEntity *ee : layerm->fills()) { // fill represents infill extrusions of a single island. const auto *fill = dynamic_cast(ee); if (! fill->entities.empty()) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index b03010b17..c5f4d9672 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3244,7 +3244,7 @@ void GUI_App::app_updater(bool from_user) app_data.target_path =dwnld_dlg.get_download_path(); // start download - this->plater_->get_notification_manager()->push_download_progress_notification(_utf8("Download"), std::bind(&AppUpdater::cancel_callback, this->m_app_updater.get())); + this->plater_->get_notification_manager()->push_download_progress_notification(_utf8("Download"), std::bind(&AppUpdater::cancel_callback, m_app_updater.get())); app_data.start_after = dwnld_dlg.run_after_download(); m_app_updater->set_app_data(std::move(app_data)); m_app_updater->sync_download(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 62611ac25..966c36b27 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -1158,18 +1158,18 @@ void TriangleSelectorGUI::update_render_data() #if !ENABLE_LEGACY_OPENGL_REMOVAL void GLPaintContour::render() const { - assert(this->m_contour_VBO_id != 0); - assert(this->m_contour_EBO_id != 0); + assert(m_contour_VBO_id != 0); + assert(m_contour_EBO_id != 0); glsafe(::glLineWidth(4.0f)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_contour_VBO_id)); glsafe(::glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), nullptr)); glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); if (this->contour_indices_size > 0) { - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_contour_EBO_id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_contour_EBO_id)); glsafe(::glDrawElements(GL_LINES, GLsizei(this->contour_indices_size), GL_UNSIGNED_INT, nullptr)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } @@ -1181,20 +1181,20 @@ void GLPaintContour::render() const void GLPaintContour::finalize_geometry() { - assert(this->m_contour_VBO_id == 0); - assert(this->m_contour_EBO_id == 0); + assert(m_contour_VBO_id == 0); + assert(m_contour_EBO_id == 0); if (!this->contour_vertices.empty()) { - glsafe(::glGenBuffers(1, &this->m_contour_VBO_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_contour_VBO_id)); + glsafe(::glGenBuffers(1, &m_contour_VBO_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_contour_VBO_id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, this->contour_vertices.size() * sizeof(float), this->contour_vertices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); this->contour_vertices.clear(); } if (!this->contour_indices.empty()) { - glsafe(::glGenBuffers(1, &this->m_contour_EBO_id)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->m_contour_EBO_id)); + glsafe(::glGenBuffers(1, &m_contour_EBO_id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_contour_EBO_id)); glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->contour_indices.size() * sizeof(unsigned int), this->contour_indices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); this->contour_indices.clear(); @@ -1203,13 +1203,13 @@ void GLPaintContour::finalize_geometry() void GLPaintContour::release_geometry() { - if (this->m_contour_VBO_id) { - glsafe(::glDeleteBuffers(1, &this->m_contour_VBO_id)); - this->m_contour_VBO_id = 0; + if (m_contour_VBO_id) { + glsafe(::glDeleteBuffers(1, &m_contour_VBO_id)); + m_contour_VBO_id = 0; } - if (this->m_contour_EBO_id) { - glsafe(::glDeleteBuffers(1, &this->m_contour_EBO_id)); - this->m_contour_EBO_id = 0; + if (m_contour_EBO_id) { + glsafe(::glDeleteBuffers(1, &m_contour_EBO_id)); + m_contour_EBO_id = 0; } this->clear(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 04f24b20d..94aca4fdb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -41,7 +41,7 @@ public: void render() const; - inline bool has_VBO() const { return this->m_contour_EBO_id != 0; } + inline bool has_VBO() const { return m_contour_EBO_id != 0; } // Release the geometry data, release OpenGL VBOs. void release_geometry(); diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 1855b6a4e..cfa2ef15a 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -101,7 +101,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co this->back_to_initial_value(opt_id); }; field->m_back_to_sys_value = [this](std::string opt_id) { - if (!this->m_disabled) + if (!m_disabled) this->back_to_sys_value(opt_id); }; diff --git a/src/slic3r/Utils/AppUpdater.cpp b/src/slic3r/Utils/AppUpdater.cpp index 27f2e34bc..a17adea8a 100644 --- a/src/slic3r/Utils/AppUpdater.cpp +++ b/src/slic3r/Utils/AppUpdater.cpp @@ -168,7 +168,7 @@ bool AppUpdater::priv::http_get_file(const std::string& url, size_t size_limit, .size_limit(size_limit) .on_progress([&, progress_fn](Http::Progress progress, bool& cancel) { // progress function returns true as success (to continue) - cancel = (this->m_cancel ? true : !progress_fn(std::move(progress))); + cancel = (m_cancel ? true : !progress_fn(std::move(progress))); if (cancel) { error_message = GUI::format("Error getting: `%1%`: Download was canceled.", //lm:typo //dk: am i blind? :) url); @@ -259,7 +259,7 @@ boost::filesystem::path AppUpdater::priv::download_file(const DownloadAppData& d ); if (!res) { - if (this->m_cancel) + if (m_cancel) { BOOST_LOG_TRIVIAL(info) << error_message; //lm:Is this an error? // dk: changed to info wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_APP_DOWNLOAD_FAILED); // FAILED with empty msg only closes progress notification diff --git a/tests/fff_print/test_perimeters.cpp b/tests/fff_print/test_perimeters.cpp index 71ab3e675..54cf37067 100644 --- a/tests/fff_print/test_perimeters.cpp +++ b/tests/fff_print/test_perimeters.cpp @@ -459,8 +459,8 @@ SCENARIO("Some weird coverage test", "[Perimeters]") object->slice(); Layer *layer = object->get_layer(1); LayerRegion *layerm = layer->get_region(0); - layerm->slices.clear(); - layerm->slices.append({ expolygon }, stInternal); + layerm->m_slices.clear(); + layerm->m_slices.append({ expolygon }, stInternal); // make perimeters layer->make_perimeters(); @@ -472,22 +472,22 @@ SCENARIO("Some weird coverage test", "[Perimeters]") Polygons covered_by_infill; { Polygons acc; - for (const ExtrusionEntity *ee : layerm->perimeters.entities) + for (const ExtrusionEntity *ee : layerm->perimeters()) for (const ExtrusionEntity *ee : dynamic_cast(ee)->entities) append(acc, offset(dynamic_cast(ee)->polygon().split_at_first_point(), float(pflow.scaled_width() / 2.f + SCALED_EPSILON))); covered_by_perimeters = union_(acc); } { Polygons acc; - for (const Surface &surface : layerm->fill_surfaces.surfaces) - append(acc, to_polygons(surface.expolygon)); - for (const ExtrusionEntity *ee : layerm->thin_fills.entities) + for (const ExPolygon &expolygon : layerm->fill_expolygons()) + append(acc, to_polygons(expolygon)); + for (const ExtrusionEntity *ee : layerm->thin_fills().entities) append(acc, offset(dynamic_cast(ee)->polyline, float(iflow.scaled_width() / 2.f + SCALED_EPSILON))); covered_by_infill = union_(acc); } // compute the non covered area - ExPolygons non_covered = diff_ex(to_polygons(layerm->slices.surfaces), union_(covered_by_perimeters, covered_by_infill)); + ExPolygons non_covered = diff_ex(to_polygons(layerm->slices().surfaces), union_(covered_by_perimeters, covered_by_infill)); /* if (0) { @@ -506,7 +506,8 @@ SCENARIO("Some weird coverage test", "[Perimeters]") } */ THEN("no gap between perimeters and infill") { - size_t num_non_convered = std::count_if(non_covered.begin(), non_covered.end(), [&iflow](const ExPolygon &ex){ return ex.area() > sqr(double(iflow.scaled_width())); }); + size_t num_non_convered = std::count_if(non_covered.begin(), non_covered.end(), + [&iflow](const ExPolygon &ex){ return ex.area() > sqr(double(iflow.scaled_width())); }); REQUIRE(num_non_convered == 0); } } diff --git a/tests/fff_print/test_print.cpp b/tests/fff_print/test_print.cpp index d8ab5a3fa..204f3f8e0 100644 --- a/tests/fff_print/test_print.cpp +++ b/tests/fff_print/test_print.cpp @@ -20,11 +20,11 @@ SCENARIO("PrintObject: Perimeter generation", "[PrintObject]") { } THEN("Every layer in region 0 has 1 island of perimeters") { for (const Layer *layer : object.layers()) - REQUIRE(layer->regions().front()->perimeters.entities.size() == 1); + REQUIRE(layer->regions().front()->perimeters().size() == 1); } THEN("Every layer in region 0 has 3 paths in its perimeters list.") { for (const Layer *layer : object.layers()) - REQUIRE(layer->regions().front()->perimeters.items_count() == 3); + REQUIRE(layer->regions().front()->perimeters().items_count() == 3); } } } @@ -66,7 +66,7 @@ SCENARIO("Print: Changing number of solid surfaces does not cause all surfaces t // iterate over all of the regions in the layer for (const LayerRegion *region : layer.regions()) { // for each region, iterate over the fill surfaces - for (const Surface &surface : region->fill_surfaces.surfaces) + for (const Surface &surface : region->fill_surfaces()) CHECK(surface.is_solid()); } }; diff --git a/xs/xsp/Layer.xsp b/xs/xsp/Layer.xsp index e42486985..da2962c1e 100644 --- a/xs/xsp/Layer.xsp +++ b/xs/xsp/Layer.xsp @@ -13,15 +13,15 @@ %code%{ RETVAL = &THIS->region(); %}; Ref slices() - %code%{ RETVAL = &THIS->slices; %}; + %code%{ RETVAL = const_cast(&THIS->slices()); %}; Ref thin_fills() - %code%{ RETVAL = &THIS->thin_fills; %}; + %code%{ RETVAL = const_cast(&THIS->thin_fills()); %}; Ref fill_surfaces() - %code%{ RETVAL = &THIS->fill_surfaces; %}; + %code%{ RETVAL = const_cast(&THIS->fill_surfaces()); %}; Ref perimeters() - %code%{ RETVAL = &THIS->perimeters; %}; + %code%{ RETVAL = const_cast(&THIS->perimeters()); %}; Ref fills() - %code%{ RETVAL = &THIS->fills; %}; + %code%{ RETVAL = const_cast(&THIS->fills()); %}; void prepare_fill_surfaces(); void make_perimeters(SurfaceCollection* slices, SurfaceCollection* fill_surfaces)