mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 10:45:55 +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
|
// 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(
|
||||||
|
@ -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 ¶ms, ExtrusionEntitiesPtr &out) const {
|
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, 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 ¶
|
|||||||
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 ¶
|
|||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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 ¶ms, 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 ¶ms, const Surface *surface) const {
|
ExtrusionRole getRoleFromSurfaceType(const FillParams ¶ms, const Surface *surface) const {
|
||||||
if (params.role == erNone || params.role == erCustom) {
|
if (params.role == erNone || params.role == erCustom) {
|
||||||
|
@ -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),
|
||||||
|
@ -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())
|
||||||
|
@ -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,32 +3326,24 @@ 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 ®ion : by_region) {
|
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||||
if (!region.infills.empty() &&
|
if (!region.infills.empty() &&
|
||||||
( ironing || print.regions()[®ion - &by_region.front()]->config().infill_first == is_infill_first) ) {
|
( print.regions()[®ion - &by_region.front()]->config().infill_first == is_infill_first) ) {
|
||||||
extrusions.clear();
|
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||||
extrusions.reserve(region.infills.size());
|
m_writer.apply_print_region_config(print.regions()[®ion - &by_region.front()]->config());
|
||||||
for (ExtrusionEntity *ee : region.infills)
|
if (m_config.print_temperature > 0)
|
||||||
if ((ee->role() == erIroning) == ironing)
|
gcode += m_writer.set_temperature(m_config.print_temperature.value, false, m_writer.tool()->id());
|
||||||
extrusions.emplace_back(ee);
|
|
||||||
if (! extrusions.empty()) {
|
|
||||||
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)
|
|
||||||
gcode += m_writer.set_temperature(m_config.print_temperature.value, false, m_writer.tool()->id());
|
|
||||||
else if(m_layer!=nullptr && m_layer->bottom_z() < EPSILON)
|
else if(m_layer!=nullptr && m_layer->bottom_z() < EPSILON)
|
||||||
gcode += m_writer.set_temperature(m_config.first_layer_temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
|
gcode += m_writer.set_temperature(m_config.first_layer_temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
|
||||||
else
|
else
|
||||||
gcode += m_writer.set_temperature(m_config.temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
|
gcode += m_writer.set_temperature(m_config.temperature.get_at(m_writer.tool()->id()), false, m_writer.tool()->id());
|
||||||
ExtrusionEntitiesPtr extrusions { region.infills };
|
ExtrusionEntitiesPtr extrusions { region.infills };
|
||||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||||
for (const ExtrusionEntity* fill : extrusions) {
|
for (const ExtrusionEntity* fill : extrusions) {
|
||||||
gcode += extrude_entity(*fill, "");
|
gcode += extrude_entity(*fill, "");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user