optimize the brdige over infill by extractng only the sparse infill lines from previous layer

This commit is contained in:
PavelMikus 2023-02-24 16:47:07 +01:00
parent feb9310fe3
commit e4910381b4
3 changed files with 93 additions and 13 deletions

View file

@ -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<SurfaceFill> 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<Fill> f = std::unique_ptr<Fill>(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()
{

View file

@ -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;

View file

@ -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<const ExtrusionEntityCollection *>(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<const LayerSlice *, SurfacesPtr> 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 =