Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Enabled gap fill algorithm for all solid fill types #3412

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f2e8431
ENH: Enabled gap fill algorithm for all solid fill types
igiannakas Dec 31, 2023
95ade4b
Merge branch 'main' into pr-gap-fill-enablement-for-all-infill-types
igiannakas Jan 1, 2024
2aaabaf
Merge remote-tracking branch 'upstream/main' into pr-gap-fill-enablem…
igiannakas Jan 1, 2024
8c98787
Made gap fill an option & refactored code into its own method
igiannakas Jan 1, 2024
bfafa54
Code comment updates
igiannakas Jan 1, 2024
e61366e
Merge remote-tracking branch 'upstream/main' into pr-gap-fill-enablem…
igiannakas Jan 1, 2024
bedb2b3
Merge branch 'main' into pr-gap-fill-enablement-for-all-infill-types
igiannakas Jan 2, 2024
113664f
Merge branch 'main' into pr-gap-fill-enablement-for-all-infill-types
igiannakas Jan 2, 2024
1dfe6ec
Merge branch 'main' into pr-gap-fill-enablement-for-all-infill-types
igiannakas Jan 6, 2024
fc2c0fa
Merge branch 'SoftFever:main' into pr-gap-fill-enablement-for-all-inf…
igiannakas Jan 9, 2024
5652c75
Merge branch 'SoftFever:main' into pr-gap-fill-enablement-for-all-inf…
igiannakas Jan 13, 2024
5c8814a
Merge branch 'SoftFever:main' into pr-gap-fill-enablement-for-all-inf…
igiannakas Jan 14, 2024
780f413
Merge branch 'main' into pr-gap-fill-enablement-for-all-infill-types
igiannakas Jan 14, 2024
889b4eb
Merge branch 'SoftFever:main' into pr-gap-fill-enablement-for-all-inf…
igiannakas Jan 17, 2024
4f9bc64
Merge branch 'SoftFever:main' into pr-gap-fill-enablement-for-all-inf…
igiannakas Jan 18, 2024
ca70ff9
Converted gap fill to enum and control filter out gap fill in the UI
igiannakas Jan 18, 2024
7e243a8
Update label for consistency
igiannakas Jan 18, 2024
95134e8
Spelling mistake
igiannakas Jan 18, 2024
4957c5e
Merge remote-tracking branch 'upstream/main' into pr-gap-fill-enablem…
igiannakas Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 62 additions & 1 deletion src/libslic3r/Fill/FillBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Fill* Fill::new_from_type(const InfillPattern type)
// BBS: for internal solid infill only
case ipConcentricInternal: return new FillConcentricInternal();
// BBS: for bottom and top surface only
case ipMonotonicLine: return new FillMonotonicLineWGapFill();
// Orca: Replace BBS implementation with Prusa implementation
case ipMonotonicLine: return new FillMonotonicLines();
default: throw Slic3r::InvalidArgument("unknown type");
}
}
Expand Down Expand Up @@ -173,6 +174,66 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
for (size_t i = idx; i < eec->entities.size(); i++)
eec->entities[i]->set_reverse();
}

// Orca: run gap fill
this->_create_gap_fill(surface, params, eec);
}
}

// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
// and append them to the out ExtrusionEntityCollection.
void Fill::_create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out){

//Orca: just to be safe, check against null pointer for the print object config and if NULL return.
if (this->print_object_config == nullptr) return;

// Orca: Enable gap fill as per the user preference. Return early if gap fill is to not be applied.
if ((this->print_object_config->gap_fill_target.value == gftNowhere) ||
(surface->surface_type == stInternalSolid && this->print_object_config->gap_fill_target.value != gftEverywhere))
return;

Flow new_flow = params.flow;
ExPolygons unextruded_areas;
unextruded_areas = diff_ex(this->no_overlap_expolygons, union_ex(out->polygons_covered_by_spacing(10)));
ExPolygons gapfill_areas = union_ex(unextruded_areas);
if (!this->no_overlap_expolygons.empty())
gapfill_areas = intersection_ex(gapfill_areas, this->no_overlap_expolygons);

if (gapfill_areas.size() > 0 && params.density >= 1) {
double min = 0.2 * new_flow.scaled_spacing() * (1 - INSET_OVERLAP_TOLERANCE);
double max = 2. * new_flow.scaled_spacing();
ExPolygons gaps_ex = diff_ex(
opening_ex(gapfill_areas, float(min / 2.)),
offset2_ex(gapfill_areas, -float(max / 2.), float(max / 2. + ClipperSafetyOffset)));
//BBS: sort the gap_ex to avoid mess travel
Points ordering_points;
ordering_points.reserve(gaps_ex.size());
ExPolygons gaps_ex_sorted;
gaps_ex_sorted.reserve(gaps_ex.size());
for (const ExPolygon &ex : gaps_ex)
ordering_points.push_back(ex.contour.first_point());
std::vector<Points::size_type> order2 = chain_points(ordering_points);
for (size_t i : order2)
gaps_ex_sorted.emplace_back(std::move(gaps_ex[i]));

ThickPolylines polylines;
for (ExPolygon& ex : gaps_ex_sorted) {
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
ex.medial_axis(min, max, &polylines);
}

if (!polylines.empty() && !is_bridge(params.extrusion_role)) {
polylines.erase(std::remove_if(polylines.begin(), polylines.end(),
[&](const ThickPolyline& p) {
return p.length() < scale_(params.config->filter_out_gap_fill.value);
}), polylines.end());

ExtrusionEntityCollection gap_fill;
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
auto gap = std::move(gap_fill.entities);
out->append(gap);
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/libslic3r/Fill/FillBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../Flow.hpp"
#include "../ExtrusionEntity.hpp"
#include "../ExtrusionEntityCollection.hpp"
#include "../ShortestPath.hpp"

namespace Slic3r {

Expand Down Expand Up @@ -106,6 +107,7 @@ class Fill
FillAdaptive::Octree* adapt_fill_octree = nullptr;

// PrintConfig and PrintObjectConfig are used by infills that use Arachne (Concentric and FillEnsuring).
// Orca: also used by gap fill function.
const PrintConfig *print_config = nullptr;
const PrintObjectConfig *print_object_config = nullptr;

Expand Down Expand Up @@ -134,7 +136,7 @@ class Fill
// Perform the fill.
virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);

// BBS: this method is used to fill the ExtrusionEntityCollection.
// It call fill_surface by default
virtual void fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out);
Expand Down Expand Up @@ -172,6 +174,10 @@ class Fill
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }

virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;

// Orca: Dedicated function to calculate gap fill lines for the provided surface, according to the print object parameters
// and append them to the out ExtrusionEntityCollection.
void _create_gap_fill(const Surface* surface, const FillParams& params, ExtrusionEntityCollection* out);

public:
static void connect_infill(Polylines &&infill_ordered, const ExPolygon &boundary, Polylines &polylines_out, const double spacing, const FillParams &params);
Expand Down
19 changes: 17 additions & 2 deletions src/libslic3r/Fill/FillRectilinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3099,7 +3099,22 @@ Points sample_grid_pattern(const Polygons& polygons, coord_t spacing, const Boun
return sample_grid_pattern(union_ex(polygons), spacing, global_bounding_box);
}

void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
// Orca: Introduced FillMonotonicLines from Prusa slicer, inhereting from FillRectilinear
// This replaces the FillMonotonicLineWGapFill from BBS
Polylines FillMonotonicLines::fill_surface(const Surface *surface, const FillParams &params)
{
FillParams params2 = params;
params2.monotonic = true;
params2.anchor_length_max = 0.0f;
Polylines polylines_out;
if (! fill_surface_by_lines(surface, params2, 0.f, 0.f, polylines_out))
BOOST_LOG_TRIVIAL(error) << "FillMonotonicLines::fill_surface() failed to fill a region.";
return polylines_out;
}

// Orca: Replaced with FillMonotonicLines from Prusa slicer. Moved gap fill algorithm to
// FillBase to perform gap fill for all fill types.
/*void FillMonotonicLineWGapFill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
{
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
coll_nosort->no_sort = this->no_sort();
Expand Down Expand Up @@ -3274,7 +3289,7 @@ void FillMonotonicLineWGapFill::fill_surface_by_lines(const Surface* surface, co
//assert(! it->has_duplicate_points());
it->remove_duplicate_points();
}
}
}*/


} // namespace Slic3r
16 changes: 14 additions & 2 deletions src/libslic3r/Fill/FillRectilinear.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,19 @@ class FillSupportBase : public FillRectilinear
float _layer_angle(size_t idx) const override { return 0.f; }
};

class FillMonotonicLineWGapFill : public Fill
// Orca: Introduced FillMonotonicLines from Prusa slicer, inhereting from FillRectilinear
// This replaces the FillMonotonicLineWGapFill from BBS
class FillMonotonicLines : public FillRectilinear
{
public:
Fill* clone() const override { return new FillMonotonicLines(*this); }
~FillMonotonicLines() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override;
bool no_sort() const override { return true; }
};

//Orca: Replaced with FillMonotonicLines, inheriting from FillRectilinear
/*class FillMonotonicLineWGapFill : public Fill
{
public:
~FillMonotonicLineWGapFill() override = default;
Expand All @@ -131,7 +143,7 @@ class FillMonotonicLineWGapFill : public Fill

private:
void fill_surface_by_lines(const Surface* surface, const FillParams& params, Polylines& polylines_out);
};
};*/

Points sample_grid_pattern(const ExPolygon& expolygon, coord_t spacing, const BoundingBox& global_bounding_box);
Points sample_grid_pattern(const ExPolygons& expolygons, coord_t spacing, const BoundingBox& global_bounding_box);
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,7 +771,7 @@ static std::vector<std::string> s_Preset_print_options {
"extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness","reduce_wall_solid_infill", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall", "overhang_reverse", "overhang_reverse_threshold","overhang_reverse_internal_only",
"seam_position", "staggered_inner_seams", "wall_sequence", "is_infill_first", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
"infill_direction",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern",
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle",
"max_travel_detour_distance",
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer",
Expand Down
29 changes: 29 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,22 @@ static t_config_enum_values s_keys_map_SeamPosition {
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamPosition)

// Orca
static t_config_enum_values s_keys_map_InternalBridgeFilter {
{ "disabled", ibfDisabled },
{ "limited", ibfLimited },
{ "nofilter", ibfNofilter },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(InternalBridgeFilter)

// Orca
static t_config_enum_values s_keys_map_GapFillTarget {
{ "everywhere", gftEverywhere },
{ "topbottom", gftTopBottom },
{ "nowhere", gftNowhere },
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GapFillTarget)

static const t_config_enum_values s_keys_map_SLADisplayOrientation = {
{ "landscape", sladoLandscape},
{ "portrait", sladoPortrait}
Expand Down Expand Up @@ -752,6 +761,26 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("mm");
def->min = 0;
def->set_default_value(new ConfigOptionFloat(0.));

def = this->add("gap_fill_target", coEnum);
def->label = L("Apply gap fill");
def->category = L("Strength");
def->tooltip = L("Enables gap fill for the selected surfaces. The minimum gap length that will be filled can be controlled "
"from the filter out tiny gaps option below.\n\n"
"Options:\n"
"1. Everywhere: Applies gap fill to top, bottom and internal solid surfaces\n"
"2. Top and Bottom surfaces: Applies gap fill to top and bottom surfaces only\n"
"3. Nowhere: Disables gap fill\n");
def->enum_keys_map = &ConfigOptionEnum<GapFillTarget>::get_enum_values();
def->enum_values.push_back("everywhere");
def->enum_values.push_back("topbottom");
def->enum_values.push_back("nowhere");
def->enum_labels.push_back(L("Everywhere"));
def->enum_labels.push_back(L("Top and bottom surfaces"));
def->enum_labels.push_back(L("Nowhere"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<GapFillTarget>(gftEverywhere));


def = this->add("enable_overhang_bridge_fan", coBools);
def->label = L("Force cooling for overhang and bridge");
Expand Down
8 changes: 8 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,17 @@ enum SeamPosition {
spNearest, spAligned, spRear, spRandom
};

//Orca
enum InternalBridgeFilter {
ibfDisabled, ibfLimited, ibfNofilter
};

//Orca
enum GapFillTarget {
gftEverywhere, gftTopBottom, gftNowhere
};


enum LiftType {
NormalLift,
SpiralLift,
Expand Down Expand Up @@ -789,6 +796,7 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionPercent, tree_support_top_rate))
((ConfigOptionFloat, tree_support_branch_diameter_organic))
((ConfigOptionFloat, tree_support_branch_angle_organic))
((ConfigOptionEnum<GapFillTarget>,gap_fill_target))
((ConfigOptionFloat, min_length_factor))

// Move all acceleration and jerk settings to object
Expand Down
4 changes: 4 additions & 0 deletions src/slic3r/GUI/ConfigManipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
apply(config, &new_conf);
}

// Orca: Hide the filter out tiny gaps field when gap fill target is nowhere as no gap fill will be applied.
bool have_gap_fill = config->opt_enum<GapFillTarget>("gap_fill_target") != gftNowhere;
toggle_line("filter_out_gap_fill", have_gap_fill);

bool have_ensure_vertical_thickness = config->opt_bool("ensure_vertical_shell_thickness");
if(have_ensure_vertical_thickness) {
DynamicPrintConfig new_conf = *config;
Expand Down
1 change: 1 addition & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2009,6 +2009,7 @@ void TabPrint::build()
optgroup->append_single_option_line("infill_anchor");
optgroup->append_single_option_line("infill_anchor_max");
optgroup->append_single_option_line("internal_solid_infill_pattern");
optgroup->append_single_option_line("gap_fill_target");
optgroup->append_single_option_line("filter_out_gap_fill");

optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
Expand Down