mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 07:15:57 +08:00
#718 fix ironing post-process double the fills.
This commit is contained in:
parent
db21177093
commit
9f7f558816
@ -549,6 +549,7 @@ void Layer::make_ironing()
|
||||
// speed: 20 mm/sec
|
||||
};
|
||||
|
||||
std::unordered_map<ExtrusionEntityCollection*, ExtrusionEntityCollection*> fill_2_ironing_coll;
|
||||
std::vector<IroningParams> by_extruder;
|
||||
bool extruder_dont_care = this->object()->config().wipe_into_objects;
|
||||
double default_layer_height = this->object()->config().layer_height;
|
||||
@ -631,9 +632,33 @@ void Layer::make_ironing()
|
||||
} catch (InfillFailedException &) {
|
||||
}
|
||||
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.
|
||||
ExtrusionEntityCollection *eec = nullptr;
|
||||
ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection());
|
||||
ExtrusionEntityCollection *eec = new ExtrusionEntityCollection();
|
||||
eec_ironing->entities.push_back(eec);
|
||||
// Don't sort the ironing infill lines as they are monotonicly ordered.
|
||||
eec->no_sort = true;
|
||||
extrusion_entities_append_paths(
|
||||
|
@ -147,6 +147,26 @@ std::pair<float, Point> Fill::_infill_direction(const Surface *surface) const
|
||||
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 ¶ms, ExtrusionEntitiesPtr &out) const {
|
||||
//add overlap & call fill_surface
|
||||
Polylines polylines;
|
||||
@ -158,33 +178,28 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
||||
return;
|
||||
|
||||
// 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){
|
||||
// compute the path of the nozzle -> extruded volume
|
||||
double lengthTot = 0;
|
||||
int nbLines = 0;
|
||||
double length_tot = 0;
|
||||
for (auto pline = polylines.begin(); pline != polylines.end(); ++pline){
|
||||
Lines lines = pline->lines();
|
||||
for (auto line = lines.begin(); line != lines.end(); ++line){
|
||||
lengthTot += unscaled(line->length());
|
||||
nbLines++;
|
||||
length_tot += unscaled(line->length());
|
||||
}
|
||||
}
|
||||
double extrudedVolume = params.flow.mm3_per_mm() * lengthTot;
|
||||
double extruded_volume = params.flow.mm3_per_mm() * length_tot;
|
||||
// compute real volume
|
||||
double poylineVolume = 0;
|
||||
for (auto poly = this->no_overlap_expolygons.begin(); poly != this->no_overlap_expolygons.end(); ++poly) {
|
||||
poylineVolume += params.flow.height*unscaled(unscaled(poly->area()));
|
||||
}
|
||||
double polyline_volume = compute_unscaled_volume_to_fill(surface, params);
|
||||
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
|
||||
// extrudedVolume,
|
||||
// (poylineVolume),
|
||||
// (poylineVolume) / extrudedVolume,
|
||||
// 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
|
||||
if (multFlow > 1.3) multFlow = 1.3;
|
||||
if (multFlow < 0.8) multFlow = 0.8;
|
||||
if (mult_flow > 1.3) mult_flow = 1.3;
|
||||
if (mult_flow < 0.8) mult_flow = 0.8;
|
||||
}
|
||||
|
||||
// Save into layer.
|
||||
@ -199,8 +214,8 @@ void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities, std::move(polylines),
|
||||
good_role,
|
||||
params.flow.mm3_per_mm() * params.flow_mult * multFlow,
|
||||
(float)(params.flow.width * params.flow_mult * multFlow),
|
||||
params.flow.mm3_per_mm() * params.flow_mult * mult_flow,
|
||||
(float)(params.flow.width * params.flow_mult * mult_flow),
|
||||
(float)params.flow.height);
|
||||
|
||||
}
|
||||
|
@ -158,6 +158,8 @@ protected:
|
||||
|
||||
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 ¶ms, const Surface *surface) const {
|
||||
if (params.role == erNone || params.role == erCustom) {
|
||||
return params.flow.bridge ?
|
||||
|
@ -3287,19 +3287,7 @@ FillRectilinearWGapFill::fill_surface_extrusion(const Surface *surface, const Fi
|
||||
}
|
||||
double extrudedVolume = params.flow.mm3_per_mm() * lengthTot;
|
||||
// compute real volume
|
||||
double poylineVolume = 0;
|
||||
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;
|
||||
}
|
||||
double poylineVolume = compute_unscaled_volume_to_fill(surface, params);
|
||||
//printf("process want %f mm3 extruded for a volume of %f space : we mult by %f %i\n",
|
||||
// extrudedVolume,
|
||||
// (poylineVolume),
|
||||
|
@ -106,24 +106,7 @@ namespace Slic3r {
|
||||
coordf_t init_spacing = this->get_spacing();
|
||||
|
||||
// compute the volume to extrude
|
||||
double volumeToOccupy = 0;
|
||||
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;
|
||||
}
|
||||
double volume_to_occupy = compute_unscaled_volume_to_fill(surface, params);
|
||||
|
||||
//create root node
|
||||
ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection();
|
||||
@ -134,7 +117,7 @@ namespace Slic3r {
|
||||
FillParams first_pass_params = params;
|
||||
if(first_pass_params.role != ExtrusionRole::erSupportMaterial && first_pass_params.role != ExtrusionRole::erSupportMaterialInterface)
|
||||
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
|
||||
FillParams monotonic_params = params;
|
||||
@ -142,12 +125,12 @@ namespace Slic3r {
|
||||
|
||||
//second infill
|
||||
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
|
||||
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())
|
||||
|
@ -2478,12 +2478,9 @@ void GCode::process_layer(
|
||||
extruder_id,
|
||||
print_wipe_extrusions != 0) :
|
||||
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_infill(print, by_region_specific, false, false);
|
||||
|
||||
// ironing
|
||||
gcode += this->extrude_infill(print,by_region_specific, false, true);
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
}
|
||||
if (this->config().gcode_label_objects)
|
||||
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.
|
||||
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;
|
||||
ExtrusionEntitiesPtr extrusions;
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||
if (!region.infills.empty() &&
|
||||
( ironing || print.regions()[®ion - &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()) {
|
||||
( print.regions()[®ion - &by_region.front()]->config().infill_first == is_infill_first) ) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
m_writer.apply_print_region_config(print.regions()[®ion - &by_region.front()]->config());
|
||||
if (m_config.print_temperature > 0)
|
||||
@ -3357,7 +3347,6 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
@ -328,7 +328,7 @@ private:
|
||||
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_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 travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||
|
@ -2513,7 +2513,7 @@ end:
|
||||
// Optimized version for a single region layer.
|
||||
if (layer->regions().size() == 1) {
|
||||
assert(!upscaled);
|
||||
assert(!clipped);
|
||||
//assert(!clipped); //can happen with z-range modifier
|
||||
// Single region, growing or shrinking.
|
||||
LayerRegion *layerm = layer->regions().front();
|
||||
ExPolygons expolygons = to_expolygons(std::move(layerm->m_slices.surfaces));
|
||||
|
Loading…
x
Reference in New Issue
Block a user