Merge branch 'lm_skirtbrim'

This commit is contained in:
Lukas Matena 2021-07-14 16:02:15 +02:00
commit 1031af09c1
10 changed files with 78 additions and 44 deletions

View File

@ -402,9 +402,13 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance
const BrimType &bt = object->config().brim_type; const BrimType &bt = object->config().brim_type;
return (bt == btOuterOnly || bt == btOuterAndInner) && print.config().skirt_distance.value < object->config().brim_width; return (bt == btOuterOnly || bt == btOuterAndInner) && print.config().skirt_distance.value < object->config().brim_width;
}); });
const bool draft_shield = print.config().draft_shield != dsDisabled;
// If there is a possibility that brim intersects skirt, go through loops and split those extrusions // If there is a possibility that brim intersects skirt, go through loops and split those extrusions
// The result is either the original Polygon or a list of Polylines // The result is either the original Polygon or a list of Polylines
if (! print.skirt().empty() && could_brim_intersects_skirt) if (draft_shield && ! print.skirt().empty() && could_brim_intersects_skirt)
{ {
// Find the bounding polygons of the skirt // Find the bounding polygons of the skirt
const Polygons skirt_inners = offset(dynamic_cast<ExtrusionLoop*>(print.skirt().entities.back())->polygon(), const Polygons skirt_inners = offset(dynamic_cast<ExtrusionLoop*>(print.skirt().entities.back())->polygon(),

View File

@ -157,7 +157,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower_x" || opt_key == "wipe_tower_x"
|| opt_key == "wipe_tower_y" || opt_key == "wipe_tower_y"
|| opt_key == "wipe_tower_rotation_angle") { || opt_key == "wipe_tower_rotation_angle") {
steps.emplace_back(psSkirt); steps.emplace_back(psSkirtBrim);
} else if ( } else if (
opt_key == "nozzle_diameter" opt_key == "nozzle_diameter"
|| opt_key == "resolution" || opt_key == "resolution"
@ -201,7 +201,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "first_layer_speed" || opt_key == "first_layer_speed"
|| opt_key == "z_offset") { || opt_key == "z_offset") {
steps.emplace_back(psWipeTower); steps.emplace_back(psWipeTower);
steps.emplace_back(psSkirt); steps.emplace_back(psSkirtBrim);
} else if (opt_key == "filament_soluble") { } else if (opt_key == "filament_soluble") {
steps.emplace_back(psWipeTower); steps.emplace_back(psWipeTower);
// Soluble support interface / non-soluble base interface produces non-soluble interface layers below soluble interface layers. // Soluble support interface / non-soluble base interface produces non-soluble interface layers below soluble interface layers.
@ -215,8 +215,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
osteps.emplace_back(posPerimeters); osteps.emplace_back(posPerimeters);
osteps.emplace_back(posInfill); osteps.emplace_back(posInfill);
osteps.emplace_back(posSupportMaterial); osteps.emplace_back(posSupportMaterial);
steps.emplace_back(psSkirt); steps.emplace_back(psSkirtBrim);
steps.emplace_back(psBrim);
} else { } else {
// for legacy, if we can't handle this option let's invalidate all steps // for legacy, if we can't handle this option let's invalidate all steps
//FIXME invalidate all steps of all objects as well? //FIXME invalidate all steps of all objects as well?
@ -239,8 +238,6 @@ bool Print::invalidate_step(PrintStep step)
{ {
bool invalidated = Inherited::invalidate_step(step); bool invalidated = Inherited::invalidate_step(step);
// Propagate to dependent steps. // Propagate to dependent steps.
if (step == psSkirt)
invalidated |= Inherited::invalidate_step(psBrim);
if (step != psGCodeExport) if (step != psGCodeExport)
invalidated |= Inherited::invalidate_step(psGCodeExport); invalidated |= Inherited::invalidate_step(psGCodeExport);
return invalidated; return invalidated;
@ -342,12 +339,12 @@ std::vector<ObjectID> Print::print_object_ids() const
bool Print::has_infinite_skirt() const bool Print::has_infinite_skirt() const
{ {
return (m_config.draft_shield && m_config.skirts > 0) || (m_config.ooze_prevention && this->extruders().size() > 1); return (m_config.draft_shield == dsEnabled && m_config.skirts > 0) || (m_config.ooze_prevention && this->extruders().size() > 1);
} }
bool Print::has_skirt() const bool Print::has_skirt() const
{ {
return (m_config.skirt_height > 0 && m_config.skirts > 0) || this->has_infinite_skirt(); return (m_config.skirt_height > 0 && m_config.skirts > 0) || m_config.draft_shield != dsDisabled;
} }
bool Print::has_brim() const bool Print::has_brim() const
@ -861,30 +858,39 @@ void Print::process()
} }
this->set_done(psWipeTower); this->set_done(psWipeTower);
} }
if (this->set_started(psSkirt)) { if (this->set_started(psSkirtBrim)) {
this->set_status(88, L("Generating skirt and brim"));
m_skirt.clear(); m_skirt.clear();
m_skirt_convex_hull.clear(); m_skirt_convex_hull.clear();
m_first_layer_convex_hull.points.clear(); m_first_layer_convex_hull.points.clear();
if (this->has_skirt()) { const bool draft_shield = config().draft_shield != dsDisabled;
this->set_status(88, L("Generating skirt"));
this->_make_skirt(); if (this->has_skirt() && draft_shield) {
// In case that draft shield is active, generate skirt first so brim
// can be trimmed to make room for it.
_make_skirt();
} }
this->set_done(psSkirt);
}
if (this->set_started(psBrim)) {
m_brim.clear(); m_brim.clear();
m_first_layer_convex_hull.points.clear(); m_first_layer_convex_hull.points.clear();
if (this->has_brim()) { if (this->has_brim()) {
this->set_status(88, L("Generating brim"));
Polygons islands_area; Polygons islands_area;
m_brim = make_brim(*this, this->make_try_cancel(), islands_area); m_brim = make_brim(*this, this->make_try_cancel(), islands_area);
for (Polygon &poly : union_(this->first_layer_islands(), islands_area)) for (Polygon &poly : union_(this->first_layer_islands(), islands_area))
append(m_first_layer_convex_hull.points, std::move(poly.points)); append(m_first_layer_convex_hull.points, std::move(poly.points));
} }
// Brim depends on skirt (brim lines are trimmed by the skirt lines), therefore if
// the skirt gets invalidated, brim gets invalidated as well and the following line is called.
if (has_skirt() && ! draft_shield) {
// In case that draft shield is NOT active, generate skirt now.
// It will be placed around the brim, so brim has to be ready.
assert(m_skirt.empty());
_make_skirt();
}
this->finalize_first_layer_convex_hull(); this->finalize_first_layer_convex_hull();
this->set_done(psBrim); this->set_done(psSkirtBrim);
} }
BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info(); BOOST_LOG_TRIVIAL(info) << "Slicing process finished." << log_memory_info();
} }
@ -964,6 +970,10 @@ void Print::_make_skirt()
// Include the wipe tower. // Include the wipe tower.
append(points, this->first_layer_wipe_tower_corners()); append(points, this->first_layer_wipe_tower_corners());
// Unless draft shield is enabled, include all brims as well.
if (config().draft_shield == dsDisabled)
append(points, m_first_layer_convex_hull.points);
if (points.size() < 3) if (points.size() < 3)
// At least three points required for a convex hull. // At least three points required for a convex hull.
return; return;

View File

@ -45,11 +45,10 @@ enum PrintStep {
// psToolOrdering is a synonym to psWipeTower, as the Wipe Tower calculates and modifies the ToolOrdering, // psToolOrdering is a synonym to psWipeTower, as the Wipe Tower calculates and modifies the ToolOrdering,
// while if printing without the Wipe Tower, the ToolOrdering is calculated as well. // while if printing without the Wipe Tower, the ToolOrdering is calculated as well.
psToolOrdering = psWipeTower, psToolOrdering = psWipeTower,
psSkirt, psSkirtBrim,
psBrim,
// Last step before G-code export, after this step is finished, the initial extrusion path preview // Last step before G-code export, after this step is finished, the initial extrusion path preview
// should be refreshed. // should be refreshed.
psSlicingFinished = psBrim, psSlicingFinished = psSkirtBrim,
psGCodeExport, psGCodeExport,
psCount, psCount,
}; };

View File

@ -1240,7 +1240,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
deleted_objects = true; deleted_objects = true;
} }
if (new_objects || deleted_objects) if (new_objects || deleted_objects)
update_apply_status(this->invalidate_steps({ psSkirt, psBrim, psWipeTower, psGCodeExport })); update_apply_status(this->invalidate_steps({ psSkirtBrim, psWipeTower, psGCodeExport }));
if (new_objects) if (new_objects)
update_apply_status(false); update_apply_status(false);
print_regions_reshuffled = true; print_regions_reshuffled = true;

View File

@ -173,6 +173,13 @@ static const t_config_enum_values s_keys_map_BrimType = {
}; };
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BrimType) CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(BrimType)
static const t_config_enum_values s_keys_map_DraftShield = {
{ "disabled", dsDisabled },
{ "limited", dsLimited },
{ "enabled", dsEnabled }
};
CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(DraftShield)
static const t_config_enum_values s_keys_map_ForwardCompatibilitySubstitutionRule = { static const t_config_enum_values s_keys_map_ForwardCompatibilitySubstitutionRule = {
{ "disable", ForwardCompatibilitySubstitutionRule::Disable }, { "disable", ForwardCompatibilitySubstitutionRule::Disable },
{ "enable", ForwardCompatibilitySubstitutionRule::Enable }, { "enable", ForwardCompatibilitySubstitutionRule::Enable },
@ -2147,27 +2154,34 @@ void PrintConfigDef::init_fff_params()
#endif #endif
def = this->add("skirt_distance", coFloat); def = this->add("skirt_distance", coFloat);
def->label = L("Distance from object"); def->label = L("Distance from brim/object");
def->tooltip = L("Distance between skirt and object(s). Set this to zero to attach the skirt " def->tooltip = L("Distance between skirt and brim (when draft shield is not used) or objects.");
"to the object(s) and get a brim for better adhesion.");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->min = 0; def->min = 0;
def->set_default_value(new ConfigOptionFloat(6)); def->set_default_value(new ConfigOptionFloat(6));
def = this->add("skirt_height", coInt); def = this->add("skirt_height", coInt);
def->label = L("Skirt height"); def->label = L("Skirt height");
def->tooltip = L("Height of skirt expressed in layers. Set this to a tall value to use skirt " def->tooltip = L("Height of skirt expressed in layers.");
"as a shield against drafts.");
def->sidetext = L("layers"); def->sidetext = L("layers");
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionInt(1)); def->set_default_value(new ConfigOptionInt(1));
def = this->add("draft_shield", coBool); def = this->add("draft_shield", coEnum);
def->label = L("Draft shield"); def->label = L("Draft shield");
def->tooltip = L("If enabled, the skirt will be as tall as a highest printed object. " def->tooltip = L("With draft shield active, the skirt will be printed skirt_distance from the object, possibly intersecting brim.\n"
"Enabled = skirt is as tall as the highest printed object.\n"
"Limited = skirt is as tall as specified by skirt_height.\n"
"This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft."); "This is useful to protect an ABS or ASA print from warping and detaching from print bed due to wind draft.");
def->enum_keys_map = &ConfigOptionEnum<DraftShield>::get_enum_values();
def->enum_values.push_back("disabled");
def->enum_values.push_back("limited");
def->enum_values.push_back("enabled");
def->enum_labels.push_back(L("Disabled"));
def->enum_labels.push_back(L("Limited"));
def->enum_labels.push_back(L("Enabled"));
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false)); def->set_default_value(new ConfigOptionEnum<DraftShield>(dsDisabled));
def = this->add("skirts", coInt); def = this->add("skirts", coInt);
def->label = L("Loops (minimum)"); def->label = L("Loops (minimum)");
@ -3652,9 +3666,12 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
value = "rectilinear"; value = "rectilinear";
} else if (opt_key == "skirt_height" && value == "-1") { } else if (opt_key == "skirt_height" && value == "-1") {
// PrusaSlicer no more accepts skirt_height == -1 to print a draft shield to the top of the highest object. // PrusaSlicer no more accepts skirt_height == -1 to print a draft shield to the top of the highest object.
// A new "draft_shield" boolean config value is used instead. // A new "draft_shield" enum config value is used instead.
opt_key = "draft_shield"; opt_key = "draft_shield";
value = "1"; value = "enabled";
} else if (opt_key == "draft_shield" && (value == "1" || value == "0")) {
// draft_shield used to be a bool, it was turned into an enum in PrusaSlicer 2.4.0.
value = value == "1" ? "enabled" : "disabled";
} else if (opt_key == "octoprint_host") { } else if (opt_key == "octoprint_host") {
opt_key = "print_host"; opt_key = "print_host";
} else if (opt_key == "octoprint_cafile") { } else if (opt_key == "octoprint_cafile") {

View File

@ -121,6 +121,10 @@ enum BrimType {
btOuterAndInner, btOuterAndInner,
}; };
enum DraftShield {
dsDisabled, dsLimited, dsEnabled
};
#define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \ #define CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NAME) \
template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \ template<> const t_config_enum_names& ConfigOptionEnum<NAME>::get_enum_names(); \
template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values(); template<> const t_config_enum_values& ConfigOptionEnum<NAME>::get_enum_values();
@ -141,6 +145,7 @@ CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SeamPosition)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLADisplayOrientation) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLADisplayOrientation)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLAPillarConnectionMode) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(SLAPillarConnectionMode)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(BrimType)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(DraftShield)
CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(ForwardCompatibilitySubstitutionRule)
#undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS #undef CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS
@ -689,6 +694,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionBools, cooling)) ((ConfigOptionBools, cooling))
((ConfigOptionFloat, default_acceleration)) ((ConfigOptionFloat, default_acceleration))
((ConfigOptionInts, disable_fan_first_layers)) ((ConfigOptionInts, disable_fan_first_layers))
((ConfigOptionEnum<DraftShield>, draft_shield))
((ConfigOptionFloat, duplicate_distance)) ((ConfigOptionFloat, duplicate_distance))
((ConfigOptionFloat, extruder_clearance_height)) ((ConfigOptionFloat, extruder_clearance_height))
((ConfigOptionFloat, extruder_clearance_radius)) ((ConfigOptionFloat, extruder_clearance_radius))
@ -728,7 +734,6 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionBools, retract_layer_change)) ((ConfigOptionBools, retract_layer_change))
((ConfigOptionFloat, skirt_distance)) ((ConfigOptionFloat, skirt_distance))
((ConfigOptionInt, skirt_height)) ((ConfigOptionInt, skirt_height))
((ConfigOptionBool, draft_shield))
((ConfigOptionInt, skirts)) ((ConfigOptionInt, skirts))
((ConfigOptionInts, slowdown_below_layer_time)) ((ConfigOptionInts, slowdown_below_layer_time))
((ConfigOptionBool, spiral_vase)) ((ConfigOptionBool, spiral_vase))

View File

@ -91,7 +91,7 @@ PrintBase::ApplyStatus PrintObject::set_instances(PrintInstances &&instances)
[](const PrintInstance& lhs, const PrintInstance& rhs) { return lhs.model_instance == rhs.model_instance && lhs.shift == rhs.shift; }); [](const PrintInstance& lhs, const PrintInstance& rhs) { return lhs.model_instance == rhs.model_instance && lhs.shift == rhs.shift; });
if (! equal) { if (! equal) {
status = PrintBase::APPLY_STATUS_CHANGED; status = PrintBase::APPLY_STATUS_CHANGED;
if (m_print->invalidate_steps({ psSkirt, psBrim, psGCodeExport }) || if (m_print->invalidate_steps({ psSkirtBrim, psGCodeExport }) ||
(! equal_length && m_print->invalidate_step(psWipeTower))) (! equal_length && m_print->invalidate_step(psWipeTower)))
status = PrintBase::APPLY_STATUS_INVALIDATED; status = PrintBase::APPLY_STATUS_INVALIDATED;
m_instances = std::move(instances); m_instances = std::move(instances);
@ -674,18 +674,18 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
// propagate to dependent steps // propagate to dependent steps
if (step == posPerimeters) { if (step == posPerimeters) {
invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning }); invalidated |= this->invalidate_steps({ posPrepareInfill, posInfill, posIroning });
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posPrepareInfill) { } else if (step == posPrepareInfill) {
invalidated |= this->invalidate_steps({ posInfill, posIroning }); invalidated |= this->invalidate_steps({ posInfill, posIroning });
} else if (step == posInfill) { } else if (step == posInfill) {
invalidated |= this->invalidate_steps({ posIroning }); invalidated |= this->invalidate_steps({ posIroning });
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
} else if (step == posSlice) { } else if (step == posSlice) {
invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial }); invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial });
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false; m_slicing_params.valid = false;
} else if (step == posSupportMaterial) { } else if (step == posSupportMaterial) {
invalidated |= m_print->invalidate_steps({ psSkirt, psBrim }); invalidated |= m_print->invalidate_steps({ psSkirtBrim });
m_slicing_params.valid = false; m_slicing_params.valid = false;
} }

View File

@ -276,7 +276,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
toggle_field(el, have_default_acceleration); toggle_field(el, have_default_acceleration);
bool have_skirt = config->opt_int("skirts") > 0; bool have_skirt = config->opt_int("skirts") > 0;
toggle_field("skirt_height", have_skirt && !config->opt_bool("draft_shield")); toggle_field("skirt_height", have_skirt && config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
for (auto el : { "skirt_distance", "draft_shield", "min_skirt_length" }) for (auto el : { "skirt_distance", "draft_shield", "min_skirt_length" })
toggle_field(el, have_skirt); toggle_field(el, have_skirt);

View File

@ -5704,7 +5704,7 @@ void GLCanvas3D::_load_print_toolpaths()
if (print == nullptr) if (print == nullptr)
return; return;
if (!print->is_step_done(psSkirt) || !print->is_step_done(psBrim)) if (! print->is_step_done(psSkirtBrim))
return; return;
if (!print->has_skirt() && !print->has_brim()) if (!print->has_skirt() && !print->has_brim())

View File

@ -17,8 +17,7 @@ _constant()
STEP_PREPARE_INFILL = posPrepareInfill STEP_PREPARE_INFILL = posPrepareInfill
STEP_INFILL = posInfill STEP_INFILL = posInfill
STEP_SUPPORTMATERIAL = posSupportMaterial STEP_SUPPORTMATERIAL = posSupportMaterial
STEP_SKIRT = psSkirt STEP_SKIRTBRIM = psSkirtBrim
STEP_BRIM = psBrim
STEP_WIPE_TOWER = psWipeTower STEP_WIPE_TOWER = psWipeTower
PROTOTYPE: PROTOTYPE:
CODE: CODE: