WIP: Ironing over top surfaces.
This commit is contained in:
parent
b578b7ec87
commit
10110ed307
19 changed files with 321 additions and 38 deletions
|
@ -312,6 +312,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role)
|
|||
case erOverhangPerimeter : return L("Overhang perimeter");
|
||||
case erInternalInfill : return L("Internal infill");
|
||||
case erSolidInfill : return L("Solid infill");
|
||||
case erIroning : return L("Ironing");
|
||||
case erTopSolidInfill : return L("Top solid infill");
|
||||
case erBridgeInfill : return L("Bridge infill");
|
||||
case erGapFill : return L("Gap fill");
|
||||
|
|
|
@ -22,6 +22,7 @@ enum ExtrusionRole : uint8_t {
|
|||
erInternalInfill,
|
||||
erSolidInfill,
|
||||
erTopSolidInfill,
|
||||
erIroning,
|
||||
erBridgeInfill,
|
||||
erGapFill,
|
||||
erSkirt,
|
||||
|
@ -54,14 +55,16 @@ inline bool is_infill(ExtrusionRole role)
|
|||
return role == erBridgeInfill
|
||||
|| role == erInternalInfill
|
||||
|| role == erSolidInfill
|
||||
|| role == erTopSolidInfill;
|
||||
|| role == erTopSolidInfill
|
||||
|| role == erIroning;
|
||||
}
|
||||
|
||||
inline bool is_solid_infill(ExtrusionRole role)
|
||||
{
|
||||
return role == erBridgeInfill
|
||||
|| role == erSolidInfill
|
||||
|| role == erTopSolidInfill;
|
||||
|| role == erTopSolidInfill
|
||||
|| role == erIroning;
|
||||
}
|
||||
|
||||
inline bool is_bridge(ExtrusionRole role) {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../Surface.hpp"
|
||||
|
||||
#include "FillBase.hpp"
|
||||
#include "FillRectilinear2.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
@ -388,8 +389,8 @@ void Layer::make_fills()
|
|||
flow_width = new_flow.width;
|
||||
}
|
||||
// Save into layer.
|
||||
auto *eec = new ExtrusionEntityCollection();
|
||||
m_regions[surface_fill.region_id]->fills.entities.push_back(eec);
|
||||
ExtrusionEntityCollection* eec = nullptr;
|
||||
m_regions[surface_fill.region_id]->fills.entities.push_back(eec = new ExtrusionEntityCollection());
|
||||
// Only concentric fills are not sorted.
|
||||
eec->no_sort = f->no_sort();
|
||||
extrusion_entities_append_paths(
|
||||
|
@ -418,4 +419,163 @@ void Layer::make_fills()
|
|||
#endif
|
||||
}
|
||||
|
||||
// Create ironing extrusions over top surfaces.
|
||||
void Layer::make_ironing()
|
||||
{
|
||||
// LayerRegion::slices contains surfaces marked with SurfaceType.
|
||||
// Here we want to collect top surfaces extruded with the same extruder.
|
||||
// A surface will be ironed with the same extruder to not contaminate the print with another material leaking from the nozzle.
|
||||
|
||||
// First classify regions based on the extruder used.
|
||||
struct IroningParams {
|
||||
int extruder = -1;
|
||||
bool just_infill = false;
|
||||
// Spacing of the ironing lines, also to calculate the extrusion flow from.
|
||||
double line_spacing;
|
||||
// Height of the extrusion, to calculate the extrusion flow from.
|
||||
double height;
|
||||
double speed;
|
||||
double angle;
|
||||
|
||||
bool operator<(const IroningParams &rhs) const {
|
||||
if (this->extruder < rhs.extruder)
|
||||
return true;
|
||||
if (this->extruder > rhs.extruder)
|
||||
return false;
|
||||
if (int(this->just_infill) < int(rhs.just_infill))
|
||||
return true;
|
||||
if (int(this->just_infill) > int(rhs.just_infill))
|
||||
return false;
|
||||
if (this->line_spacing < rhs.line_spacing)
|
||||
return true;
|
||||
if (this->line_spacing > rhs.line_spacing)
|
||||
return false;
|
||||
if (this->height < rhs.height)
|
||||
return true;
|
||||
if (this->height > rhs.height)
|
||||
return false;
|
||||
if (this->speed < rhs.speed)
|
||||
return true;
|
||||
if (this->speed > rhs.speed)
|
||||
return false;
|
||||
if (this->angle < rhs.angle)
|
||||
return true;
|
||||
if (this->angle > rhs.angle)
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const IroningParams &rhs) const {
|
||||
return this->extruder == rhs.extruder && this->just_infill == rhs.just_infill &&
|
||||
this->line_spacing == rhs.line_spacing && this->height == rhs.height && this->speed == rhs.speed &&
|
||||
this->angle == rhs.angle;
|
||||
}
|
||||
|
||||
LayerRegion *layerm = nullptr;
|
||||
|
||||
// IdeaMaker: ironing
|
||||
// ironing flowrate (5% percent)
|
||||
// ironing speed (10 mm/sec)
|
||||
|
||||
// Kisslicer:
|
||||
// iron off, Sweep, Group
|
||||
// ironing speed: 15 mm/sec
|
||||
|
||||
// Cura:
|
||||
// Pattern (zig-zag / concentric)
|
||||
// line spacing (0.1mm)
|
||||
// flow: from normal layer height. 10%
|
||||
// speed: 20 mm/sec
|
||||
};
|
||||
|
||||
std::vector<IroningParams> by_extruder;
|
||||
bool extruder_dont_care = this->object()->config().wipe_into_objects;
|
||||
double default_layer_height = this->object()->config().layer_height;
|
||||
|
||||
for (LayerRegion *layerm : m_regions)
|
||||
if (! layerm->slices.empty()) {
|
||||
IroningParams ironing_params;
|
||||
const PrintRegionConfig &config = layerm->region()->config();
|
||||
if (config.ironing_type == IroningType::AllSolid ||
|
||||
(config.top_solid_layers > 0 &&
|
||||
(config.ironing_type == IroningType::TopSurfaces ||
|
||||
(config.ironing_type == IroningType::TopmostOnly && layerm->layer()->upper_layer == nullptr)))) {
|
||||
if (config.perimeter_extruder == config.solid_infill_extruder || config.perimeters == 0) {
|
||||
// Iron the whole face.
|
||||
ironing_params.extruder = config.solid_infill_extruder;
|
||||
} else {
|
||||
// Iron just the infill.
|
||||
ironing_params.extruder = config.solid_infill_extruder;
|
||||
}
|
||||
}
|
||||
if (ironing_params.extruder != -1) {
|
||||
ironing_params.just_infill = false;
|
||||
ironing_params.line_spacing = config.ironing_spacing;
|
||||
ironing_params.height = default_layer_height * 0.01 * config.ironing_flowrate;
|
||||
ironing_params.speed = config.ironing_speed;
|
||||
ironing_params.angle = config.fill_angle * M_PI / 180.;
|
||||
ironing_params.layerm = layerm;
|
||||
by_extruder.emplace_back(ironing_params);
|
||||
}
|
||||
}
|
||||
std::sort(by_extruder.begin(), by_extruder.end());
|
||||
|
||||
FillRectilinear2 fill;
|
||||
FillParams fill_params;
|
||||
fill.set_bounding_box(this->object()->bounding_box());
|
||||
fill.layer_id = this->id();
|
||||
fill.z = this->print_z;
|
||||
fill.overlap = 0;
|
||||
fill_params.density = 1.;
|
||||
fill_params.dont_connect = true;
|
||||
|
||||
for (size_t i = 0; i < by_extruder.size(); ++ i) {
|
||||
// Find span of regions equivalent to the ironing operation.
|
||||
IroningParams &ironing_params = by_extruder[i];
|
||||
size_t j = i;
|
||||
for (++ j; j < by_extruder.size() && ironing_params == by_extruder[j]; ++ j) ;
|
||||
|
||||
// Create the ironing extrusions for regions <i, j)
|
||||
ExPolygons ironing_areas;
|
||||
double nozzle_dmr = this->object()->print()->config().nozzle_diameter.values[ironing_params.extruder - 1];
|
||||
if (ironing_params.just_infill) {
|
||||
// Just infill.
|
||||
} else {
|
||||
// Infill and perimeter.
|
||||
// Merge top surfaces with the same ironing parameters.
|
||||
Polygons polys;
|
||||
for (size_t k = i; k < j; ++ k)
|
||||
for (const Surface &surface : by_extruder[k].layerm->slices.surfaces)
|
||||
if (surface.surface_type == stTop)
|
||||
polygons_append(polys, surface.expolygon);
|
||||
// Trim the top surfaces with half the nozzle diameter.
|
||||
ironing_areas = intersection_ex(polys, offset(this->lslices, - float(scale_(0.5 * nozzle_dmr))));
|
||||
}
|
||||
|
||||
// Create the filler object.
|
||||
fill.spacing = ironing_params.line_spacing;
|
||||
fill.angle = float(ironing_params.angle + 0.25 * M_PI);
|
||||
fill.link_max_length = (coord_t)scale_(3. * fill.spacing);
|
||||
double height = ironing_params.height * fill.spacing / nozzle_dmr;
|
||||
Flow flow = Flow::new_from_spacing(float(nozzle_dmr), 0., float(height), false);
|
||||
double flow_mm3_per_mm = flow.mm3_per_mm();
|
||||
Surface surface_fill(stTop, ExPolygon());
|
||||
for (ExPolygon &expoly : ironing_areas) {
|
||||
surface_fill.expolygon = std::move(expoly);
|
||||
Polylines polylines = fill.fill_surface(&surface_fill, fill_params);
|
||||
if (! polylines.empty()) {
|
||||
// Save into layer.
|
||||
ExtrusionEntityCollection *eec = nullptr;
|
||||
ironing_params.layerm->fills.entities.push_back(eec = new ExtrusionEntityCollection());
|
||||
//FIXME we may not want to sort a monotonous infill.
|
||||
eec->no_sort = false;
|
||||
extrusion_entities_append_paths(
|
||||
eec->entities, std::move(polylines),
|
||||
erIroning,
|
||||
flow_mm3_per_mm, float(flow.width), float(height));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -20,27 +20,21 @@ class Surface;
|
|||
|
||||
struct FillParams
|
||||
{
|
||||
FillParams() {
|
||||
memset(this, 0, sizeof(FillParams));
|
||||
// Adjustment does not work.
|
||||
dont_adjust = true;
|
||||
}
|
||||
|
||||
bool full_infill() const { return density > 0.9999f; }
|
||||
|
||||
// Fill density, fraction in <0, 1>
|
||||
float density;
|
||||
float density { 0.f };
|
||||
|
||||
// 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 };
|
||||
|
||||
// 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 };
|
||||
};
|
||||
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||
|
||||
|
|
|
@ -2246,12 +2246,14 @@ void GCode::process_layer(
|
|||
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast<unsigned int>(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region;
|
||||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
||||
if (print.config().infill_first) {
|
||||
gcode += this->extrude_infill(print, by_region_specific);
|
||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
||||
} else {
|
||||
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);
|
||||
gcode += this->extrude_infill(print,by_region_specific, false);
|
||||
}
|
||||
// ironing
|
||||
gcode += this->extrude_infill(print,by_region_specific, true);
|
||||
}
|
||||
if (this->config().gcode_label_objects)
|
||||
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||
|
@ -2873,22 +2875,30 @@ 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)
|
||||
std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing)
|
||||
{
|
||||
std::string gcode;
|
||||
std::string gcode;
|
||||
ExtrusionEntitiesPtr extrusions;
|
||||
const char* extrusion_name = ironing ? "ironing" : "infill";
|
||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||
if (! region.infills.empty()) {
|
||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||
ExtrusionEntitiesPtr extrusions { region.infills };
|
||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||
for (const ExtrusionEntity *fill : extrusions) {
|
||||
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
||||
if (eec) {
|
||||
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
||||
gcode += this->extrude_entity(*ee, "infill");
|
||||
} else
|
||||
gcode += this->extrude_entity(*fill, "infill");
|
||||
}
|
||||
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()[®ion - &by_region.front()]->config());
|
||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||
for (const ExtrusionEntity *fill : extrusions) {
|
||||
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
||||
if (eec) {
|
||||
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
||||
gcode += this->extrude_entity(*ee, extrusion_name);
|
||||
} else
|
||||
gcode += this->extrude_entity(*fill, extrusion_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
@ -3027,6 +3037,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
speed = m_config.get_abs_value("solid_infill_speed");
|
||||
} else if (path.role() == erTopSolidInfill) {
|
||||
speed = m_config.get_abs_value("top_solid_infill_speed");
|
||||
} else if (path.role() == erIroning) {
|
||||
speed = m_config.get_abs_value("ironing_speed");
|
||||
} else if (path.role() == erGapFill) {
|
||||
speed = m_config.get_abs_value("gap_fill_speed");
|
||||
} else {
|
||||
|
|
|
@ -295,7 +295,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);
|
||||
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, bool ironing);
|
||||
std::string extrude_support(const ExtrusionEntityCollection &support_fills);
|
||||
|
||||
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||
|
|
|
@ -117,6 +117,7 @@ const Color GCodePreviewData::Extrusion::Default_Extrusion_Role_Colors[erCount]
|
|||
Color(1.0f, 1.0f, 0.0f, 1.0f), // erInternalInfill
|
||||
Color(1.0f, 0.0f, 1.0f, 1.0f), // erSolidInfill
|
||||
Color(0.0f, 1.0f, 1.0f, 1.0f), // erTopSolidInfill
|
||||
Color(0.0f, 1.0f, 1.0f, 1.0f), // erIroning
|
||||
Color(0.5f, 0.5f, 0.5f, 1.0f), // erBridgeInfill
|
||||
Color(1.0f, 1.0f, 1.0f, 1.0f), // erGapFill
|
||||
Color(0.5f, 0.0f, 0.0f, 1.0f), // erSkirt
|
||||
|
|
|
@ -36,11 +36,6 @@ public:
|
|||
// collection of surfaces for infill generation
|
||||
SurfaceCollection fill_surfaces;
|
||||
|
||||
// Collection of perimeter surfaces. This is a cached result of diff(slices, fill_surfaces).
|
||||
// While not necessary, the memory consumption is meager and it speeds up calculation.
|
||||
// The perimeter_surfaces keep the IDs of the slices (top/bottom/)
|
||||
SurfaceCollection perimeter_surfaces;
|
||||
|
||||
// collection of expolygons representing the bridged areas (thus not
|
||||
// needing support material)
|
||||
Polygons bridged;
|
||||
|
@ -140,6 +135,7 @@ public:
|
|||
}
|
||||
void make_perimeters();
|
||||
void make_fills();
|
||||
void make_ironing();
|
||||
|
||||
void export_region_slices_to_svg(const char *path) const;
|
||||
void export_region_fill_surfaces_to_svg(const char *path) const;
|
||||
|
|
|
@ -1583,6 +1583,8 @@ void Print::process()
|
|||
this->set_status(70, L("Infilling layers"));
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->infill();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->ironing();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_material();
|
||||
if (this->set_started(psWipeTower)) {
|
||||
|
|
|
@ -41,7 +41,7 @@ enum PrintStep {
|
|||
|
||||
enum PrintObjectStep {
|
||||
posSlice, posPerimeters, posPrepareInfill,
|
||||
posInfill, posSupportMaterial, posCount,
|
||||
posInfill, posIroning, posSupportMaterial, posCount,
|
||||
};
|
||||
|
||||
// A PrintRegion object represents a group of volumes to print
|
||||
|
@ -218,6 +218,7 @@ private:
|
|||
void make_perimeters();
|
||||
void prepare_infill();
|
||||
void infill();
|
||||
void ironing();
|
||||
void generate_support_material();
|
||||
|
||||
void _slice(const std::vector<coordf_t> &layer_height_profile);
|
||||
|
|
|
@ -1076,6 +1076,53 @@ void PrintConfigDef::init_fff_params()
|
|||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("ironing", coBool);
|
||||
def->label = L("Enable ironing");
|
||||
def->tooltip = L("Enable ironing of the top layers with the hot print head for smooth surface");
|
||||
def->category = L("Ironing");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("ironing_type", coEnum);
|
||||
def->label = L("Ironingy Type");
|
||||
def->tooltip = L("Ironingy Type");
|
||||
def->enum_keys_map = &ConfigOptionEnum<IroningType>::get_enum_values();
|
||||
def->enum_values.push_back("top");
|
||||
def->enum_values.push_back("topmost");
|
||||
def->enum_values.push_back("solid");
|
||||
def->enum_labels.push_back("All top surfaces");
|
||||
def->enum_labels.push_back("Topmost surface only");
|
||||
def->enum_labels.push_back("All solid surfaces");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<IroningType>(IroningType::TopSurfaces));
|
||||
|
||||
def = this->add("ironing_flowrate", coPercent);
|
||||
def->label = L("Flow rate");
|
||||
def->category = L("Ironing");
|
||||
def->tooltip = L("Percent of a flow rate relative to object's normal layer height.");
|
||||
def->sidetext = L("%");
|
||||
def->ratio_over = "layer_height";
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercent(15));
|
||||
|
||||
def = this->add("ironing_spacing", coFloat);
|
||||
def->label = L("Spacing between ironing passes");
|
||||
def->tooltip = L("Distance between ironing lins");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||
|
||||
def = this->add("ironing_speed", coFloat);
|
||||
def->label = L("Ironing speed");
|
||||
def->category = L("Speed");
|
||||
def->tooltip = L("Ironing speed");
|
||||
def->sidetext = L("mm/s");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(60));
|
||||
|
||||
def = this->add("layer_gcode", coString);
|
||||
def->label = L("After layer change G-code");
|
||||
def->tooltip = L("This custom code is inserted at every layer change, right after the Z move "
|
||||
|
|
|
@ -38,6 +38,13 @@ enum InfillPattern {
|
|||
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipCount,
|
||||
};
|
||||
|
||||
enum class IroningType {
|
||||
TopSurfaces,
|
||||
TopmostOnly,
|
||||
AllSolid,
|
||||
Count,
|
||||
};
|
||||
|
||||
enum SupportMaterialPattern {
|
||||
smpRectilinear, smpRectilinearGrid, smpHoneycomb,
|
||||
};
|
||||
|
@ -122,6 +129,16 @@ template<> inline const t_config_enum_values& ConfigOptionEnum<InfillPattern>::g
|
|||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<IroningType>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
keys_map["top"] = int(IroningType::TopSurfaces);
|
||||
keys_map["topmost"] = int(IroningType::TopmostOnly);
|
||||
keys_map["solid"] = int(IroningType::AllSolid);
|
||||
}
|
||||
return keys_map;
|
||||
}
|
||||
|
||||
template<> inline const t_config_enum_values& ConfigOptionEnum<SupportMaterialPattern>::get_enum_values() {
|
||||
static t_config_enum_values keys_map;
|
||||
if (keys_map.empty()) {
|
||||
|
@ -485,6 +502,12 @@ public:
|
|||
ConfigOptionInt infill_every_layers;
|
||||
ConfigOptionFloatOrPercent infill_overlap;
|
||||
ConfigOptionFloat infill_speed;
|
||||
// Ironing options
|
||||
ConfigOptionBool ironing;
|
||||
ConfigOptionEnum<IroningType> ironing_type;
|
||||
ConfigOptionPercent ironing_flowrate;
|
||||
ConfigOptionFloat ironing_spacing;
|
||||
ConfigOptionFloat ironing_speed;
|
||||
// Detect bridging perimeters
|
||||
ConfigOptionBool overhangs;
|
||||
ConfigOptionInt perimeter_extruder;
|
||||
|
@ -530,6 +553,11 @@ protected:
|
|||
OPT_PTR(infill_every_layers);
|
||||
OPT_PTR(infill_overlap);
|
||||
OPT_PTR(infill_speed);
|
||||
OPT_PTR(ironing);
|
||||
OPT_PTR(ironing_type);
|
||||
OPT_PTR(ironing_flowrate);
|
||||
OPT_PTR(ironing_spacing);
|
||||
OPT_PTR(ironing_speed);
|
||||
OPT_PTR(overhangs);
|
||||
OPT_PTR(perimeter_extruder);
|
||||
OPT_PTR(perimeter_extrusion_width);
|
||||
|
|
|
@ -387,6 +387,25 @@ void PrintObject::infill()
|
|||
}
|
||||
}
|
||||
|
||||
void PrintObject::ironing()
|
||||
{
|
||||
if (this->set_started(posIroning)) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - start";
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>(1, m_layers.size()),
|
||||
[this](const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||
m_print->throw_if_canceled();
|
||||
m_layers[layer_idx]->make_ironing();
|
||||
}
|
||||
}
|
||||
);
|
||||
m_print->throw_if_canceled();
|
||||
BOOST_LOG_TRIVIAL(debug) << "Ironing in parallel - end";
|
||||
this->set_done(posIroning);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintObject::generate_support_material()
|
||||
{
|
||||
if (this->set_started(posSupportMaterial)) {
|
||||
|
|
|
@ -298,6 +298,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
|||
toggle_field("support_material_extruder", have_support_material || have_skirt);
|
||||
toggle_field("support_material_speed", have_support_material || have_brim || have_skirt);
|
||||
|
||||
bool has_ironing = config->opt_bool("ironing");
|
||||
for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" })
|
||||
toggle_field(el, has_ironing);
|
||||
|
||||
bool have_sequential_printing = config->opt_bool("complete_objects");
|
||||
for (auto el : { "extruder_clearance_radius", "extruder_clearance_height" })
|
||||
toggle_field(el, have_sequential_printing);
|
||||
|
|
|
@ -1027,6 +1027,8 @@ boost::any& Choice::get_value()
|
|||
}
|
||||
if (m_opt_id.compare("fill_pattern") == 0)
|
||||
m_value = static_cast<InfillPattern>(ret_enum);
|
||||
else if (m_opt_id.compare("ironing_type") == 0)
|
||||
m_value = static_cast<IroningType>(ret_enum);
|
||||
else if (m_opt_id.compare("gcode_flavor") == 0)
|
||||
m_value = static_cast<GCodeFlavor>(ret_enum);
|
||||
else if (m_opt_id.compare("support_material_pattern") == 0)
|
||||
|
|
|
@ -188,6 +188,8 @@ void change_opt_value(DynamicPrintConfig& config, const t_config_option_key& opt
|
|||
opt_key == "bottom_fill_pattern" ||
|
||||
opt_key == "fill_pattern")
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<InfillPattern>(boost::any_cast<InfillPattern>(value)));
|
||||
else if (opt_key.compare("ironing_type") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<IroningType>(boost::any_cast<IroningType>(value)));
|
||||
else if (opt_key.compare("gcode_flavor") == 0)
|
||||
config.set_key_value(opt_key, new ConfigOptionEnum<GCodeFlavor>(boost::any_cast<GCodeFlavor>(value)));
|
||||
else if (opt_key.compare("support_material_pattern") == 0)
|
||||
|
|
|
@ -680,6 +680,9 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
|||
opt_key == "fill_pattern" ) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<InfillPattern>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("ironing_type") == 0 ) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<IroningType>>(opt_key)->value);
|
||||
}
|
||||
else if (opt_key.compare("gcode_flavor") == 0 ) {
|
||||
ret = static_cast<int>(config.option<ConfigOptionEnum<GCodeFlavor>>(opt_key)->value);
|
||||
}
|
||||
|
|
|
@ -405,8 +405,9 @@ const std::vector<std::string>& Preset::print_options()
|
|||
"extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs",
|
||||
"seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern",
|
||||
"infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle",
|
||||
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "max_print_speed",
|
||||
"max_volumetric_speed",
|
||||
"solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first",
|
||||
"ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing",
|
||||
"max_print_speed", "max_volumetric_speed",
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
"max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative",
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
|
|
|
@ -1162,6 +1162,12 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("top_fill_pattern");
|
||||
optgroup->append_single_option_line("bottom_fill_pattern");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Ironing")));
|
||||
optgroup->append_single_option_line("ironing");
|
||||
optgroup->append_single_option_line("ironing_type");
|
||||
optgroup->append_single_option_line("ironing_flowrate");
|
||||
optgroup->append_single_option_line("ironing_spacing");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Reducing printing time")));
|
||||
optgroup->append_single_option_line("infill_every_layers");
|
||||
optgroup->append_single_option_line("infill_only_where_needed");
|
||||
|
@ -1222,6 +1228,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("support_material_interface_speed");
|
||||
optgroup->append_single_option_line("bridge_speed");
|
||||
optgroup->append_single_option_line("gap_fill_speed");
|
||||
optgroup->append_single_option_line("ironing_speed");
|
||||
|
||||
optgroup = page->new_optgroup(_(L("Speed for non-print moves")));
|
||||
optgroup->append_single_option_line("travel_speed");
|
||||
|
|
Loading…
Add table
Reference in a new issue