Add monotonous infill thanks to @bubnikv and @wavexx

also the rectilinear2.cpp rework that go along
use of monotonous in ironing
use of monotonous instead of rectilinear of "filled" in top & bottom
reduce gap fill area from rectilinearWGapFill to the area with no overlap
fix flatten(): don't put everything in a no_sort collection but correctly recreate the hierarchy of no_sort, sort, no_sort of collections.
This commit is contained in:
supermerill 2020-09-05 20:00:22 +02:00
parent 01ce6c877e
commit f48ed5091c
12 changed files with 2031 additions and 763 deletions

View File

@ -151,14 +151,13 @@ ExtrusionEntityCollection ExtrusionEntityCollection::flatten(bool preserve_order
}
void
FlatenEntities::use(const ExtrusionEntityCollection &coll) {
if (coll.no_sort && preserve_ordering) {
if ((coll.no_sort || this->to_fill.no_sort) && preserve_ordering) {
FlatenEntities unsortable(coll, preserve_ordering);
for (const ExtrusionEntity* entity : coll.entities) {
entity->visit(unsortable);
}
to_fill.append(std::move(unsortable.to_fill));
}
else {
} else {
for (const ExtrusionEntity* entity : coll.entities) {
entity->visit(*this);
}

View File

@ -32,6 +32,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipGyroid: return new FillGyroid();
case ipRectilinear: return new FillRectilinear2();
// case ipRectilinear: return new FillRectilinear();
case ipMonotonous: return new FillMonotonous();
case ipRectilinearWGapFill: return new FillRectilinear2WGapFill();
case ipScatteredRectilinear:return new FillScatteredRectilinear();
case ipLine: return new FillLine();
@ -146,7 +147,11 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const {
//add overlap & call fill_surface
Polylines polylines = this->fill_surface(surface, params);
Polylines polylines;
try {
polylines = this->fill_surface(surface, params);
} catch (InfillFailedException&) {
}
if (polylines.empty())
return;
// ensure it doesn't over or under-extrude
@ -590,10 +595,11 @@ Fill::do_gap_fill(const ExPolygons &gapfill_areas, const FillParams &params, Ext
// offset2_ex(gapfill_areas, double(-max / 2), double(+max / 2)),
// true);
ExPolygons gapfill_areas_collapsed = offset2_ex(gapfill_areas, double(-min / 2), double(+min / 2));
const double minarea = scale_(params.config->gap_fill_min_area.get_abs_value(params.flow->width) ) * params.flow->scaled_width();
for (const ExPolygon &ex : gapfill_areas_collapsed) {
//remove too small gaps that are too hard to fill.
//ie one that are smaller than an extrusion with width of min and a length of max.
if (ex.area() > scale_(params.flow->nozzle_diameter)*scale_(params.flow->nozzle_diameter) * 2) {
if (ex.area() > minarea) {
MedialAxis{ ex, params.flow->scaled_width() * 2, params.flow->scaled_width() / 5, coord_t(params.flow->height) }.build(polylines_gapfill);
}
}

View File

@ -22,49 +22,46 @@ namespace Slic3r {
class ExPolygon;
class Surface;
class InfillFailedException : public std::runtime_error {
public:
InfillFailedException() : std::runtime_error("Infill failed") {}
};
struct FillParams
{
FillParams() {
memset(this, 0, sizeof(FillParams));
// Adjustment does not work.
dont_adjust = true;
flow_mult = 1.f;
fill_exactly = false;
role = erNone;
flow = NULL;
config = NULL;
}
bool full_infill() const { return density > 0.9999f && density < 1.0001f; }
// Fill density, fraction in <0, 1>
float density;
float density { 0.f };
// Fill extruding flow multiplier, fraction in <0, 1>. Used by "over bridge compensation"
float flow_mult;
float flow_mult { 1.0f };
// Don't connect the fill lines around the inner perimeter.
bool dont_connect;
bool dont_connect{ false };
// Don't adjust spacing to fill the space evenly.
bool dont_adjust;
bool dont_adjust { true };
// Monotonous infill - strictly left to right for better surface quality of top infills.
bool monotonous { false };
// Try to extrude the exact amount of plastic to fill the volume requested
bool fill_exactly;
bool fill_exactly{ false };
// For Honeycomb.
// we were requested to complete each loop;
// in this case we don't try to make more continuous paths
bool complete;
bool complete { false };
// if role == erNone or ERCustom, this method have to choose the best role itself, else it must use the argument's role.
ExtrusionRole role;
ExtrusionRole role { erNone };
//flow to use
Flow const *flow;
Flow const* flow { nullptr };
//full configuration for the region, to avoid copying every bit that is needed. Use this for process-specific parameters.
PrintRegionConfig const *config;
PrintRegionConfig const *config{ nullptr };
};
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@ class FillRectilinear2 : public Fill
{
public:
virtual Fill* clone() const override { return new FillRectilinear2(*this); };
virtual ~FillRectilinear2() {}
virtual ~FillRectilinear2() = default;
virtual void init_spacing(coordf_t spacing, const FillParams &params) override;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
@ -25,11 +25,20 @@ protected:
bool fill_surface_by_lines(const Surface *surface, const FillParams &params, float angleBase, float pattern_shift, Polylines &polylines_out) const;
};
class FillMonotonous : public FillRectilinear2
{
public:
virtual Fill* clone() const { return new FillMonotonous(*this); };
virtual ~FillMonotonous() = default;
virtual Polylines fill_surface(const Surface * surface, const FillParams & params) const override;
virtual bool no_sort() const { return true; }
};
class FillGrid2 : public FillRectilinear2
{
public:
virtual Fill* clone() const override { return new FillGrid2(*this); };
virtual ~FillGrid2() {}
virtual ~FillGrid2() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
protected:
@ -41,7 +50,7 @@ class FillTriangles : public FillRectilinear2
{
public:
virtual Fill* clone() const override { return new FillTriangles(*this); };
virtual ~FillTriangles() {}
virtual ~FillTriangles() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
protected:
@ -53,7 +62,7 @@ class FillStars : public FillRectilinear2
{
public:
virtual Fill* clone() const override { return new FillStars(*this); };
virtual ~FillStars() {}
virtual ~FillStars() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
protected:
@ -65,7 +74,7 @@ class FillCubic : public FillRectilinear2
{
public:
virtual Fill* clone() const override { return new FillCubic(*this); };
virtual ~FillCubic() {}
virtual ~FillCubic() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
protected:
@ -78,7 +87,7 @@ class FillRectilinear2Peri : public FillRectilinear2
public:
virtual Fill* clone() const override { return new FillRectilinear2Peri(*this); };
virtual ~FillRectilinear2Peri() {}
virtual ~FillRectilinear2Peri() = default;
//virtual Polylines fill_surface(const Surface *surface, const FillParams &params);
virtual void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const override;
@ -89,7 +98,7 @@ class FillScatteredRectilinear : public FillRectilinear2
{
public:
virtual Fill* clone() const override{ return new FillScatteredRectilinear(*this); };
virtual ~FillScatteredRectilinear() {}
virtual ~FillScatteredRectilinear() = default;
virtual Polylines fill_surface(const Surface *surface, const FillParams &params) const override;
protected:
@ -102,7 +111,7 @@ class FillRectilinearSawtooth : public FillRectilinear2 {
public:
virtual Fill* clone() const override { return new FillRectilinearSawtooth(*this); };
virtual ~FillRectilinearSawtooth() {}
virtual ~FillRectilinearSawtooth() = default;
virtual void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const override;
};
@ -112,7 +121,7 @@ class FillRectilinear2WGapFill : public FillRectilinear2
public:
virtual Fill* clone() const { return new FillRectilinear2WGapFill(*this); };
virtual ~FillRectilinear2WGapFill() {}
virtual ~FillRectilinear2WGapFill() = default;
virtual void fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const override;
static void split_polygon_gap_fill(const Surface &surface, const FillParams &params, ExPolygons &rectilinear, ExPolygons &gapfill);
};

View File

@ -24,7 +24,7 @@ namespace Slic3r {
// Save into layer smoothing path.
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
eec->no_sort = false;
eec->no_sort = params.monotonous;
FillParams params_modifided = params;
if (params.config != NULL && idx > 0) params_modifided.density /= (float)params.config->fill_smooth_width.get_abs_value(1);
else if (params.config != NULL && idx == 0) params_modifided.density *= 1;
@ -133,14 +133,18 @@ namespace Slic3r {
// first infill
perform_single_fill(0, *eecroot, *surface, params, volumeToOccupy);
//use monotonous for ironing pass
FillParams monotonous_params = params;
monotonous_params.monotonous = true;
//second infill
if (nbPass > 1){
perform_single_fill(1, *eecroot, *surface, params, volumeToOccupy);
perform_single_fill(1, *eecroot, *surface, monotonous_params, volumeToOccupy);
}
// third infill
if (nbPass > 2){
perform_single_fill(2, *eecroot, *surface, params, volumeToOccupy);
perform_single_fill(2, *eecroot, *surface, monotonous_params, volumeToOccupy);
}
if (!eecroot->entities.empty())

View File

@ -4501,6 +4501,7 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
// First we append the entities, there are eec->entities.size() of them:
//don't do fill->entities because it will discard no_sort, we must use flatten(preserve_ordering = true)
// this method will encapsulate every no_sort into an other collection, so we can get the entities directly.
ExtrusionEntitiesPtr entities = eec->flatten(true).entities;
size_t old_size = perimeters_or_infills->size();
size_t new_size = old_size + entities.size();

View File

@ -597,6 +597,7 @@ void PrintConfigDef::init_fff_params()
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("rectilineargapfill");
def->enum_values.push_back("monotonous");
def->enum_values.push_back("concentric");
def->enum_values.push_back("concentricgapfill");
def->enum_values.push_back("hilbertcurve");
@ -607,7 +608,8 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("smoothtriple");
def->enum_values.push_back("smoothhilbert");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Rectilinear (filled)"));
def->enum_labels.push_back(L("Monotonous (filled)"));
def->enum_labels.push_back(L("Monotonous"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Concentric (filled)"));
def->enum_labels.push_back(L("Hilbert Curve"));
@ -615,7 +617,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Octagram Spiral"));
def->enum_labels.push_back(L("Sawtooth"));
def->enum_labels.push_back(L("Ironing"));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonous));
def = this->add("bottom_fill_pattern", coEnum);
def->label = L("Bottom");
@ -627,6 +629,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("rectilineargapfill");
def->enum_values.push_back("monotonous");
def->enum_values.push_back("concentric");
def->enum_values.push_back("concentricgapfill");
def->enum_values.push_back("hilbertcurve");
@ -634,7 +637,8 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("octagramspiral");
def->enum_values.push_back("smooth");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Rectilinear (filled)"));
def->enum_labels.push_back(L("Monotonous (filled)"));
def->enum_labels.push_back(L("Monotonous"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Concentric (filled)"));
def->enum_labels.push_back(L("Hilbert Curve"));
@ -642,7 +646,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Octagram Spiral"));
def->enum_labels.push_back(L("Ironing"));
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipMonotonous));
def = this->add("solid_fill_pattern", coEnum);
def->label = L("Solid pattern");
@ -653,6 +657,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("smooth");
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("rectilineargapfill");
def->enum_values.push_back("monotonous");
def->enum_values.push_back("concentric");
def->enum_values.push_back("concentricgapfill");
def->enum_values.push_back("hilbertcurve");
@ -661,6 +666,7 @@ void PrintConfigDef::init_fff_params()
def->enum_labels.push_back(L("Ironing"));
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Rectilinear (filled)"));
def->enum_labels.push_back(L("Monotonous"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Concentric (filled)"));
def->enum_labels.push_back(L("Hilbert Curve"));
@ -1410,6 +1416,7 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Fill pattern for general low-density infill.");
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("monotonous");
def->enum_values.push_back("grid");
def->enum_values.push_back("triangles");
def->enum_values.push_back("stars");
@ -1424,6 +1431,7 @@ void PrintConfigDef::init_fff_params()
def->enum_values.push_back("octagramspiral");
def->enum_values.push_back("scatteredrectilinear");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Monotonous"));
def->enum_labels.push_back(L("Grid"));
def->enum_labels.push_back(L("Triangles"));
def->enum_labels.push_back(L("Stars"));
@ -3136,12 +3144,14 @@ void PrintConfigDef::init_fff_params()
def->tooltip = L("Pattern for interface layer.");
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
def->enum_values.push_back("rectilinear");
def->enum_values.push_back("monotonous");
def->enum_values.push_back("concentric");
def->enum_values.push_back("concentricgapfill");
def->enum_values.push_back("hilbertcurve");
def->enum_values.push_back("sawtooth");
def->enum_values.push_back("smooth");
def->enum_labels.push_back(L("Rectilinear"));
def->enum_labels.push_back(L("Monotonous"));
def->enum_labels.push_back(L("Concentric"));
def->enum_labels.push_back(L("Concentric (filled)"));
def->enum_labels.push_back(L("Hilbert Curve"));

View File

@ -59,7 +59,9 @@ enum PrintHostType {
enum InfillPattern {
ipRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSmooth, ipSmoothHilbert, ipSmoothTriple,
ipRectiWithPerimeter, ipConcentricGapFill, ipScatteredRectilinear, ipSawtooth, ipRectilinearWGapFill, ipCount
ipRectiWithPerimeter, ipConcentricGapFill, ipScatteredRectilinear, ipSawtooth, ipRectilinearWGapFill,
ipMonotonous,
ipCount
};
enum SupportMaterialPattern {
@ -165,6 +167,7 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g
static t_config_enum_values keys_map;
if (keys_map.empty()) {
keys_map["rectilinear"] = ipRectilinear;
keys_map["monotonous"] = ipMonotonous;
keys_map["grid"] = ipGrid;
keys_map["triangles"] = ipTriangles;
keys_map["stars"] = ipStars;
@ -182,8 +185,8 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g
keys_map["smoothtriple"] = ipSmoothTriple;
keys_map["smoothhilbert"] = ipSmoothHilbert;
keys_map["rectiwithperimeter"] = ipRectiWithPerimeter;
keys_map["scatteredrectilinear"] = ipScatteredRectilinear;
keys_map["rectilineargapfill"] = ipRectilinearWGapFill;
keys_map["scatteredrectilinear"]= ipScatteredRectilinear;
keys_map["rectilineargapfill"] = ipRectilinearWGapFill;
keys_map["sawtooth"] = ipSawtooth;
}
return keys_map;

View File

@ -3351,6 +3351,7 @@ void PrintObject::combine_infill()
// Because fill areas for rectilinear and honeycomb are grown
// later to overlap perimeters, we need to counteract that too.
((region->config().fill_pattern == ipRectilinear ||
region->config().fill_pattern == ipMonotonous ||
region->config().fill_pattern == ipGrid ||
region->config().fill_pattern == ipLine ||
region->config().fill_pattern == ipHoneycomb) ? 1.5f : 0.5f) *

View File

@ -58,6 +58,7 @@ std::vector<std::pair<size_t, bool>> chain_segments_closest_point(std::vector<En
EndPointType &end_point = end_points[next_idx];
//set the new entry point as taken
end_point.chain_id = 1;
assert((next_idx & 1) == 0 || could_reverse_func(next_idx >> 1));
out.emplace_back(next_idx / 2, (next_idx & 1) != 0);
//now switch to the other end of the segment
this_idx = next_idx ^ 1;

View File

@ -987,11 +987,9 @@ void Choice::set_value(const boost::any& value, bool change_event)
int val = boost::any_cast<int>(value);
if (m_opt_id == "top_fill_pattern" || m_opt_id == "bottom_fill_pattern" || m_opt_id == "solid_fill_pattern"
|| m_opt_id == "fill_pattern" || m_opt_id == "support_material_interface_pattern" || m_opt_id == "brim_ears_pattern")
{
val = idx_from_enum_value<InfillPattern>(val);
} else if (m_opt_id.compare("perimeter_loop_seam") == 0) {
else if (m_opt_id.compare("perimeter_loop_seam") == 0)
val = idx_from_enum_value<SeamPosition>(val);
}
else if (m_opt_id.compare("complete_objects_sort") == 0)
val = idx_from_enum_value<CompleteObjectSort>(val);
else if (m_opt_id.compare("gcode_flavor") == 0)