diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index b502a65b43..9716ecc208 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -643,6 +643,94 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: #endif } +Polylines Layer::generate_sparse_infill_polylines_for_anchoring() const +{ + std::vector surface_fills = group_fills(*this); + const Slic3r::BoundingBox bbox = this->object()->bounding_box(); + const auto resolution = this->object()->print()->config().gcode_resolution.value; + + Polylines sparse_infill_polylines{}; + + for (SurfaceFill &surface_fill : surface_fills) { + // skip patterns for which additional input is nullptr + switch (surface_fill.params.pattern) { + case ipLightning: continue; break; + case ipAdaptiveCubic: continue; break; + case ipSupportCubic: continue; break; + case ipCount: continue; break; + case ipSupportBase: continue; break; + case ipEnsuring: continue; break; + case ipRectilinear: + case ipMonotonic: + case ipMonotonicLines: + case ipAlignedRectilinear: + case ipGrid: + case ipTriangles: + case ipStars: + case ipCubic: + case ipLine: + case ipConcentric: + case ipHoneycomb: + case ip3DHoneycomb: + case ipGyroid: + case ipHilbertCurve: + case ipArchimedeanChords: + case ipOctagramSpiral: break; + } + + // Create the filler object. + std::unique_ptr f = std::unique_ptr(Fill::new_from_type(surface_fill.params.pattern)); + f->set_bounding_box(bbox); + f->layer_id = this->id(); + f->z = this->print_z; + f->angle = surface_fill.params.angle; + // f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree; + f->print_config = &this->object()->print()->config(); + f->print_object_config = &this->object()->config(); + + // calculate flow spacing for infill pattern generation + double link_max_length = 0.; + if (!surface_fill.params.bridge) { +#if 0 + link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing()); +// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length); +#else + if (surface_fill.params.density > 80.) // 80% + link_max_length = 3. * f->spacing; +#endif + } + + // Maximum length of the perimeter segment linking two infill lines. + f->link_max_length = (coord_t) scale_(link_max_length); + // Used by the concentric infill pattern to clip the loops to create extrusion paths. + f->loop_clipping = coord_t(scale_(surface_fill.params.flow.nozzle_diameter()) * LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER); + + LayerRegion &layerm = *m_regions[surface_fill.region_id]; + + // apply half spacing using this flow's own spacing and generate infill + FillParams params; + params.density = float(0.01 * surface_fill.params.density); + params.dont_adjust = false; // surface_fill.params.dont_adjust; + params.anchor_length = surface_fill.params.anchor_length; + params.anchor_length_max = surface_fill.params.anchor_length_max; + params.resolution = resolution; + params.use_arachne = false; + params.layer_height = layerm.layer()->height; + + for (ExPolygon &expoly : surface_fill.expolygons) { + // Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon. + f->spacing = surface_fill.params.spacing; + surface_fill.surface.expolygon = std::move(expoly); + try { + Polylines polylines = f->fill_surface(&surface_fill.surface, params); + sparse_infill_polylines.insert(sparse_infill_polylines.end(), polylines.begin(), polylines.end()); + } catch (InfillFailedException &) {} + } + } + + return sparse_infill_polylines; +} + // Create ironing extrusions over top surfaces. void Layer::make_ironing() { diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index d2bdc1088c..a59c029b8f 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -369,6 +369,7 @@ public: // Phony version of make_fills() without parameters for Perl integration only. void make_fills() { this->make_fills(nullptr, nullptr, nullptr); } void make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator); + Polylines generate_sparse_infill_polylines_for_anchoring() const; void make_ironing(); void export_region_slices_to_svg(const char *path) const; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 1dbffa5335..ca9516d202 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -397,6 +397,7 @@ void PrintObject::infill() this->prepare_infill(); if (this->set_started(posInfill)) { + m_print->set_status(45, L("making infill")); auto [adaptive_fill_octree, support_fill_octree] = this->prepare_adaptive_infill_data(); auto lightning_generator = this->prepare_lightning_infill_data(); @@ -1658,18 +1659,8 @@ void PrintObject::bridge_over_infill() continue; } - // Now, temporarily fill the previous layer and extract the extrusions. - // TODO - the make_fills function does a lot of work, some of it is not needed (e.g. sorting the paths) - // It would be nice to have a function that only creates the fill polylines, ideally without modifying the global state - po->get_layer(lidx)->lower_layer->make_fills(nullptr, nullptr, nullptr); - Polylines lower_layer_polylines; - for (const LayerRegion *region : layer->lower_layer->m_regions) { - for (const ExtrusionEntity *ee : region->fills().entities) { - assert(ee->is_collection()); - auto region_polylines = dynamic_cast(ee)->as_polylines(); - lower_layer_polylines.insert(lower_layer_polylines.end(), region_polylines.begin(), region_polylines.end()); - } - } + // generate sparse infill polylines from lower layers to get anchorable polylines + Polylines lower_layer_polylines = po->get_layer(lidx)->lower_layer->generate_sparse_infill_polylines_for_anchoring(); for (std::pair candidates : bridging_surface_candidates) { if (candidates.second.empty()) { @@ -1786,7 +1777,7 @@ void PrintObject::bridge_over_infill() assert(candidate->surface_type == stInternalSolid); Polygons bridged_area = expand(to_polygons(candidate->expolygon), flow.scaled_spacing()); Polygons infill_region = to_polygons(surface_to_region[candidate]->fill_expolygons()); - bool touches_perimeter = !diff(bridged_area, infill_region).empty(); + bool touches_perimeter = !diff(bridged_area, infill_region).empty(); bool touches_solid_region_under = !intersection(bridged_area, not_sparse_infill).empty(); bridged_area =