Skip to content

Commit

Permalink
Port "Extend sparse infill" from Prusa (#2134)
Browse files Browse the repository at this point in the history
* Remove BambuLab's implementation of solid infill bridging enhancement
, will use Prusa's instead

* Port "Extend sparse infill" from Prusa

* Improve anchoring by shifting the lines half-spacing

* Add missing fill patterns

* Improve anchoring by keeping fine details

* Make sure the opposite directions do not cancel each other

---------

Co-authored-by: Pavel Mikus <[email protected]>
  • Loading branch information
Noisyfox and Godrak authored Sep 29, 2023
1 parent 0e785c0 commit ee0e6a7
Show file tree
Hide file tree
Showing 16 changed files with 1,011 additions and 500 deletions.
2 changes: 0 additions & 2 deletions src/libslic3r/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,6 @@ set(lisbslic3r_sources
Geometry/VoronoiUtilsCgal.hpp
Geometry/VoronoiVisualUtils.hpp
Int128.hpp
InternalBridgeDetector.cpp
InternalBridgeDetector.hpp
KDTreeIndirect.hpp
Layer.cpp
Layer.hpp
Expand Down
111 changes: 104 additions & 7 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
///|/ Copyright (c) Prusa Research 2016 - 2023 Lukáš Matěna @lukasmatena, Vojtěch Bubník @bubnikv, Pavel Mikuš @Godrak, Lukáš Hejl @hejllukas
///|/ Copyright (c) SuperSlicer 2023 Remi Durand @supermerill
///|/ Copyright (c) 2016 Sakari Kapanen @Flannelhead
///|/ Copyright (c) Slic3r 2011 - 2015 Alessandro Ranellucci @alranel
///|/ Copyright (c) 2013 Mark Hindess
///|/ Copyright (c) 2011 Michael Moon
///|/
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/
#include <assert.h>
#include <stdio.h>
#include <memory>
Expand Down Expand Up @@ -46,8 +55,6 @@ struct SurfaceFillParams
// 1000mm is roughly the maximum length line that fits into a 32bit coord_t.
float anchor_length = 1000.f;
float anchor_length_max = 1000.f;
//BBS
bool with_loop = false;

// width, height of extrusion, nozzle diameter, is bridge
// For the output, for fill generator.
Expand Down Expand Up @@ -79,7 +86,6 @@ struct SurfaceFillParams
// RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust);
RETURN_COMPARE_NON_EQUAL(anchor_length);
RETURN_COMPARE_NON_EQUAL(anchor_length_max);
RETURN_COMPARE_NON_EQUAL(with_loop);
RETURN_COMPARE_NON_EQUAL(flow.width());
RETURN_COMPARE_NON_EQUAL(flow.height());
RETURN_COMPARE_NON_EQUAL(flow.nozzle_diameter());
Expand All @@ -100,7 +106,6 @@ struct SurfaceFillParams
// this->dont_adjust == rhs.dont_adjust &&
this->anchor_length == rhs.anchor_length &&
this->anchor_length_max == rhs.anchor_length_max &&
this->with_loop == rhs.with_loop &&
this->flow == rhs.flow &&
this->extrusion_role == rhs.extrusion_role;
}
Expand Down Expand Up @@ -151,8 +156,6 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
params.extruder = layerm.region().extruder(extrusion_role);
params.pattern = region_config.sparse_infill_pattern.value;
params.density = float(region_config.sparse_infill_density);
//BBS
params.with_loop = surface.surface_type == stInternalWithLoop;

if (surface.is_solid()) {
params.density = 100.f;
Expand Down Expand Up @@ -501,7 +504,6 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.extrusion_role = surface_fill.params.extrusion_role;
params.using_internal_flow = using_internal_flow;
params.no_extrusion_overlap = surface_fill.params.overlap;
params.with_loop = surface_fill.params.with_loop;
params.config = &layerm->region().config();
if (surface_fill.params.pattern == ipGrid)
params.can_reverse = false;
Expand Down Expand Up @@ -540,6 +542,101 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
#endif
}

Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) const
{
std::vector<SurfaceFill> surface_fills = group_fills(*this);
const Slic3r::BoundingBox bbox = this->object()->bounding_box();
const auto resolution = this->object()->print()->config().resolution.value;

Polylines sparse_infill_polylines{};

for (SurfaceFill &surface_fill : surface_fills) {
if (surface_fill.surface.surface_type != stInternal) {
continue;
}

switch (surface_fill.params.pattern) {
case ipCount: continue; break;
case ipSupportBase: continue; break;
//TODO: case ipEnsuring: continue; break;
case ipLightning:
case ipAdaptiveCubic:
case ipSupportCubic:
case ipRectilinear:
case ipMonotonic:
case ipMonotonicLine:
case ipAlignedRectilinear:
case ipGrid:
case ipTriangles:
case ipStars:
case ipCubic:
case ipLine:
case ipConcentric:
case ipConcentricInternal:
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() - this->object()->get_layer(0)->id(); // We need to subtract raft layers.
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;
// TODO: f->print_config = &this->object()->print()->config();
// TODO: f->print_object_config = &this->object()->config();

if (surface_fill.params.pattern == ipLightning)
dynamic_cast<FillLightning::Filler *>(f.get())->generator = lightning_generator;

// 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
}

LayerRegion &layerm = *m_regions[surface_fill.region_id];

// 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_(layerm.region().config().seam_gap.get_abs_value(surface_fill.params.flow.nozzle_diameter())));

// 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()
{
Expand Down
56 changes: 6 additions & 50 deletions src/libslic3r/Fill/FillBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,57 +120,13 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
{
Polylines polylines;
ThickPolylines thick_polylines;
if (!params.with_loop) {
try {
if (params.use_arachne)
thick_polylines = this->fill_surface_arachne(surface, params);
else
polylines = this->fill_surface(surface, params);
}
catch (InfillFailedException&) {}
}
//BBS: add handling for infill pattern with loop
else {
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(this->overlap - 0.5 * this->spacing)));
Polylines loop_polylines = to_polylines(expp);
{
//BBS: clip the loop
size_t j = 0;
for (size_t i = 0; i < loop_polylines.size(); ++i) {
loop_polylines[i].clip_end(this->loop_clipping);
if (loop_polylines[i].is_valid()) {
if (j < i)
loop_polylines[j] = std::move(loop_polylines[i]);
++j;
}
}
if (j < loop_polylines.size())
loop_polylines.erase(loop_polylines.begin() + int(j), loop_polylines.end());
}

if (!loop_polylines.empty()) {
if (params.use_arachne)
append(thick_polylines, to_thick_polylines(std::move(loop_polylines), scaled<coord_t>(this->spacing)));
else
append(polylines, std::move(loop_polylines));
expp = offset_ex(expp, float(scale_(0 - 0.5 * this->spacing)));
} else {
//BBS: the area is too narrow to place a loop, return to original expolygon
expp = { surface->expolygon };
}

Surface temp_surface = *surface;
for (ExPolygon& ex : expp) {
temp_surface.expolygon = ex;
try {
if (params.use_arachne)
append(thick_polylines, std::move(this->fill_surface_arachne(&temp_surface, params)));
else
append(polylines, std::move(this->fill_surface(&temp_surface, params)));
}
catch (InfillFailedException&) {}
}
try {
if (params.use_arachne)
thick_polylines = this->fill_surface_arachne(surface, params);
else
polylines = this->fill_surface(surface, params);
}
catch (InfillFailedException&) {}

if (!polylines.empty() || !thick_polylines.empty()) {
// calculate actual flow from spacing (which might have been adjusted by the infill
Expand Down
2 changes: 0 additions & 2 deletions src/libslic3r/Fill/FillBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ struct FillParams
bool use_arachne{ false };
// Layer height for Concentric infill with Arachne.
coordf_t layer_height { 0.f };
//BBS
bool with_loop { false };

// BBS
Flow flow;
Expand Down
144 changes: 0 additions & 144 deletions src/libslic3r/InternalBridgeDetector.cpp

This file was deleted.

Loading

0 comments on commit ee0e6a7

Please sign in to comment.