#718 fix ironing post-process double the fills.

This commit is contained in:
supermerill 2020-11-26 20:52:01 +01:00
parent db21177093
commit 9f7f558816
8 changed files with 81 additions and 79 deletions

View File

@ -549,6 +549,7 @@ void Layer::make_ironing()
// speed: 20 mm/sec // speed: 20 mm/sec
}; };
std::unordered_map<ExtrusionEntityCollection*, ExtrusionEntityCollection*> fill_2_ironing_coll;
std::vector<IroningParams> by_extruder; std::vector<IroningParams> by_extruder;
bool extruder_dont_care = this->object()->config().wipe_into_objects; bool extruder_dont_care = this->object()->config().wipe_into_objects;
double default_layer_height = this->object()->config().layer_height; double default_layer_height = this->object()->config().layer_height;
@ -631,9 +632,33 @@ void Layer::make_ironing()
} catch (InfillFailedException &) { } catch (InfillFailedException &) {
} }
if (! polylines.empty()) { if (! polylines.empty()) {
//always extrude ironing after infill
ExtrusionEntityCollection* eec_ironing;
if (fill_2_ironing_coll.find(&ironing_params.layerm->fills) == fill_2_ironing_coll.end()) {
if (ironing_params.layerm->fills.empty()) {
eec_ironing = &ironing_params.layerm->fills;
fill_2_ironing_coll[&ironing_params.layerm->fills] = eec_ironing;
} else {
//create the "normal fill" collection
ExtrusionEntityCollection* eec_before_layer_ironing = new ExtrusionEntityCollection(ironing_params.layerm->fills);
eec_before_layer_ironing->no_sort = ironing_params.layerm->fills.no_sort;
//create the "ironing fill" collection
eec_ironing = new ExtrusionEntityCollection();
eec_ironing->no_sort = false;
fill_2_ironing_coll[&ironing_params.layerm->fills] = eec_ironing;
//add them as fills in the right order (and we need an other ExtrusionEntityCollection, as the no_sort of fills isn't read anywhere)
ExtrusionEntityCollection* eec_root = new ExtrusionEntityCollection();
ironing_params.layerm->fills.clear();
ironing_params.layerm->fills.entities.push_back(eec_root);
eec_root->entities.push_back(eec_before_layer_ironing);
eec_root->entities.push_back(eec_ironing);
eec_root->no_sort = true;
}
} else
eec_ironing = fill_2_ironing_coll[&ironing_params.layerm->fills];
// Save into layer. // Save into layer.
ExtrusionEntityCollection *eec = nullptr; ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection()); eec_ironing->entities.push_back(eec);
// Don't sort the ironing infill lines as they are monotonicly ordered. // Don't sort the ironing infill lines as they are monotonicly ordered.
eec->no_sort = true; eec->no_sort = true;
extrusion_entities_append_paths( extrusion_entities_append_paths(

View File

@ -147,6 +147,26 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
return std::pair<float, Point>(out_angle, out_shift); return std::pair<float, Point>(out_angle, out_shift);
} }
double Fill::compute_unscaled_volume_to_fill(const Surface* surface, const FillParams& params) const {
double polyline_volume = 0;
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
polyline_volume += params.flow.height * unscaled(unscaled(poly->area()));
double perimeter_gap_usage = params.config->perimeter_overlap.get_abs_value(1);
// add external "perimeter gap"
double perimeter_round_gap = unscaled(poly->contour.length()) * params.flow.height * (1 - 0.25 * PI) * 0.5;
// add holes "perimeter gaps"
double holes_gaps = 0;
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
holes_gaps += unscaled(hole->length()) * params.flow.height * (1 - 0.25 * PI) * 0.5;
}
polyline_volume += (perimeter_round_gap + holes_gaps) * perimeter_gap_usage;
}
if (this->no_overlap_expolygons.empty()) {
polyline_volume = unscaled(unscaled(surface->area())) * params.flow.height;
}
return polyline_volume;
}
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const { void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &params, ExtrusionEntitiesPtr &out) const {
//add overlap & call fill_surface //add overlap & call fill_surface
Polylines polylines; Polylines polylines;
@ -158,33 +178,28 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
return; return;
// ensure it doesn't over or under-extrude // ensure it doesn't over or under-extrude
double multFlow = 1; double mult_flow = 1;
if (!params.dont_adjust && params.full_infill() && !params.flow.bridge && params.fill_exactly){ if (!params.dont_adjust && params.full_infill() && !params.flow.bridge && params.fill_exactly){
// compute the path of the nozzle -> extruded volume // compute the path of the nozzle -> extruded volume
double lengthTot = 0; double length_tot = 0;
int nbLines = 0;
for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){ for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){
Lines lines = pline->lines(); Lines lines = pline->lines();
for (auto line = lines.begin(); line != lines.end(); ++line){ for (auto line = lines.begin(); line != lines.end(); ++line){
lengthTot += unscaled(line->length()); length_tot += unscaled(line->length());
nbLines++;
} }
} }
double extrudedVolume = params.flow.mm3_per_mm() * lengthTot; double extruded_volume = params.flow.mm3_per_mm() * length_tot;
// compute real volume // compute real volume
double poylineVolume = 0; double polyline_volume = compute_unscaled_volume_to_fill(surface, params);
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
poylineVolume += params.flow.height*unscaled(unscaled(poly->area()));
}
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n", //printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
// extrudedVolume, // extrudedVolume,
// (poylineVolume), // (poylineVolume),
// (poylineVolume) / extrudedVolume, // (poylineVolume) / extrudedVolume,
// this->no_overlap_expolygons.size()); // this->no_overlap_expolygons.size());
if (extrudedVolume != 0 && poylineVolume != 0) multFlow = poylineVolume / extrudedVolume; if (extruded_volume != 0 && polyline_volume != 0) mult_flow = polyline_volume / extruded_volume;
//failsafe, it can happen //failsafe, it can happen
if (multFlow > 1.3) multFlow = 1.3; if (mult_flow > 1.3) mult_flow = 1.3;
if (multFlow < 0.8) multFlow = 0.8; if (mult_flow < 0.8) mult_flow = 0.8;
} }
// Save into layer. // Save into layer.
@ -199,8 +214,8 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams &para
extrusion_entities_append_paths( extrusion_entities_append_paths(
eec->entities, std::move(polylines), eec->entities, std::move(polylines),
good_role, good_role,
params.flow.mm3_per_mm() * params.flow_mult * multFlow, params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
(float)(params.flow.width * params.flow_mult * multFlow), (float)(params.flow.width * params.flow_mult * mult_flow),
(float)params.flow.height); (float)params.flow.height);
} }

View File

@ -156,7 +156,9 @@ protected:
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const; virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
void do_gap_fill(const ExPolygons &gapfill_areas, const FillParams &params, ExtrusionEntitiesPtr &coll_out) const; void do_gap_fill(const ExPolygons& gapfill_areas, const FillParams& params, ExtrusionEntitiesPtr& coll_out) const;
double compute_unscaled_volume_to_fill(const Surface* surface, const FillParams& params) const;
ExtrusionRole getRoleFromSurfaceType(const FillParams &params, const Surface *surface) const { ExtrusionRole getRoleFromSurfaceType(const FillParams &params, const Surface *surface) const {
if (params.role == erNone || params.role == erCustom) { if (params.role == erNone || params.role == erCustom) {

View File

@ -3287,19 +3287,7 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
} }
double extrudedVolume = params.flow.mm3_per_mm() * lengthTot; double extrudedVolume = params.flow.mm3_per_mm() * lengthTot;
// compute real volume // compute real volume
double poylineVolume = 0; double poylineVolume = compute_unscaled_volume_to_fill(surface, params);
ExPolygons rectilinear_no_overlap_areas = intersection_ex(rectilinear_areas, this->no_overlap_expolygons);
for (const ExPolygon &poly : rectilinear_no_overlap_areas) {
poylineVolume += params.flow.height*unscaled(unscaled(poly.area()));
// add external "perimeter gap"
double perimeterRoundGap = unscaled(poly.contour.length()) * params.flow.height * (1 - 0.25*PI) * 0.5;
// add holes "perimeter gaps"
double holesGaps = 0;
for (auto hole = poly.holes.begin(); hole != poly.holes.end(); ++hole) {
holesGaps += unscaled(hole->length()) * params.flow.height * (1 - 0.25*PI) * 0.5;
}
poylineVolume += perimeterRoundGap + holesGaps;
}
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n", //printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
// extrudedVolume, // extrudedVolume,
// (poylineVolume), // (poylineVolume),

View File

@ -106,24 +106,7 @@ namespace Slic3r {
coordf_t init_spacing = this->get_spacing(); coordf_t init_spacing = this->get_spacing();
// compute the volume to extrude // compute the volume to extrude
double volumeToOccupy = 0; double volume_to_occupy = compute_unscaled_volume_to_fill(surface, params);
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
// add external "perimeter gap"
double poylineVolume = params.flow.height*unscaled(unscaled(poly->area()));
double perimeterRoundGap = unscaled(poly->contour.length()) * params.flow.height * (1 - 0.25*PI) * 0.5;
// add holes "perimeter gaps"
double holesGaps = 0;
for (auto hole = poly->holes.begin(); hole != poly->holes.end(); ++hole) {
holesGaps += unscaled(hole->length()) * params.flow.height * (1 - 0.25*PI) * 0.5;
}
poylineVolume += perimeterRoundGap + holesGaps;
//extruded volume: see http://manual.slic3r.org/advanced/flow-math, and we need to remove a circle at an end (as the flow continue)
volumeToOccupy += poylineVolume;
}
if (this->no_overlap_expolygons.empty()) {
volumeToOccupy = unscaled(unscaled(surface->area())) * params.flow.height;
}
//create root node //create root node
ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection(); ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
@ -134,7 +117,7 @@ namespace Slic3r {
FillParams first_pass_params = params; FillParams first_pass_params = params;
if(first_pass_params.role != ExtrusionRole::erSupportMaterial && first_pass_params.role != ExtrusionRole::erSupportMaterialInterface) if(first_pass_params.role != ExtrusionRole::erSupportMaterial && first_pass_params.role != ExtrusionRole::erSupportMaterialInterface)
first_pass_params.role = ExtrusionRole::erSolidInfill; first_pass_params.role = ExtrusionRole::erSolidInfill;
perform_single_fill(0, *eecroot, *surface, first_pass_params, volumeToOccupy); perform_single_fill(0, *eecroot, *surface, first_pass_params, volume_to_occupy);
//use monotonic for ironing pass //use monotonic for ironing pass
FillParams monotonic_params = params; FillParams monotonic_params = params;
@ -142,12 +125,12 @@ namespace Slic3r {
//second infill //second infill
if (nbPass > 1){ if (nbPass > 1){
perform_single_fill(1, *eecroot, *surface, monotonic_params, volumeToOccupy); perform_single_fill(1, *eecroot, *surface, monotonic_params, volume_to_occupy);
} }
// third infill // third infill
if (nbPass > 2){ if (nbPass > 2){
perform_single_fill(2, *eecroot, *surface, monotonic_params, volumeToOccupy); perform_single_fill(2, *eecroot, *surface, monotonic_params, volume_to_occupy);
} }
if (!eecroot->entities.empty()) if (!eecroot->entities.empty())

View File

@ -2478,12 +2478,9 @@ void GCode::process_layer(
extruder_id, extruder_id,
print_wipe_extrusions != 0) : print_wipe_extrusions != 0) :
island.by_region; island.by_region;
gcode += this->extrude_infill(print, by_region_specific, true, false); gcode += this->extrude_infill(print, by_region_specific, true);
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]); gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
gcode += this->extrude_infill(print, by_region_specific, false, false); gcode += this->extrude_infill(print, by_region_specific, false);
// ironing
gcode += this->extrude_infill(print,by_region_specific, false, true);
} }
if (this->config().gcode_label_objects) if (this->config().gcode_label_objects)
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name
@ -3329,19 +3326,12 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
} }
// Chain the paths hierarchically by a greedy algorithm to minimize a travel distance. // Chain the paths hierarchically by a greedy algorithm to minimize a travel distance.
std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool is_infill_first, bool ironing) std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool is_infill_first)
{ {
std::string gcode; std::string gcode;
ExtrusionEntitiesPtr extrusions;
for (const ObjectByExtruder::Island::Region &region : by_region) { for (const ObjectByExtruder::Island::Region &region : by_region) {
if (!region.infills.empty() && if (!region.infills.empty() &&
( ironing || print.regions()[&region - &by_region.front()]->config().infill_first == is_infill_first) ) { ( print.regions()[&region - &by_region.front()]->config().infill_first == is_infill_first) ) {
extrusions.clear();
extrusions.reserve(region.infills.size());
for (ExtrusionEntity *ee : region.infills)
if ((ee->role() == erIroning) == ironing)
extrusions.emplace_back(ee);
if (! extrusions.empty()) {
m_config.apply(print.regions()[&region - &by_region.front()]->config()); m_config.apply(print.regions()[&region - &by_region.front()]->config());
m_writer.apply_print_region_config(print.regions()[&region - &by_region.front()]->config()); m_writer.apply_print_region_config(print.regions()[&region - &by_region.front()]->config());
if (m_config.print_temperature > 0) if (m_config.print_temperature > 0)
@ -3357,7 +3347,6 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
} }
} }
} }
}
return gcode; return gcode;
} }

View File

@ -328,7 +328,7 @@ private:
const size_t single_object_instance_idx); const size_t single_object_instance_idx);
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid); std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool is_infill_first, bool ironing); std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool is_infill_first);
std::string extrude_support(const ExtrusionEntityCollection &support_fills); std::string extrude_support(const ExtrusionEntityCollection &support_fills);
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment); std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);

View File

@ -2513,7 +2513,7 @@ end:
// Optimized version for a single region layer. // Optimized version for a single region layer.
if (layer->regions().size() == 1) { if (layer->regions().size() == 1) {
assert(!upscaled); assert(!upscaled);
assert(!clipped); //assert(!clipped); //can happen with z-range modifier
// Single region, growing or shrinking. // Single region, growing or shrinking.
LayerRegion *layerm = layer->regions().front(); LayerRegion *layerm = layer->regions().front();
ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces)); ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces));