FDM synchronization of front end with back end:

Fixed unnecessary invalidation of already calculated perimeters
if the infill density changes.
Fixed a race condition in invalidation of FDM regions.
This commit is contained in:
Vojtech Bubnik 2021-02-11 12:03:21 +01:00
parent cf260f6e44
commit 7f95b280f0
3 changed files with 24 additions and 14 deletions

View file

@ -59,7 +59,7 @@ PrintRegion* Print::add_region(const PrintRegionConfig &config)
// Called by Print::apply().
// This method only accepts PrintConfig option keys.
bool Print::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* new_config */, const std::vector<t_config_option_key> &opt_keys)
{
if (opt_keys.empty())
return false;
@ -621,7 +621,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
// The following call may stop the background processing.
if (! print_diff.empty())
update_apply_status(this->invalidate_state_by_config_options(print_diff));
update_apply_status(this->invalidate_state_by_config_options(new_full_config, print_diff));
// Apply variables to placeholder parser. The placeholder parser is used by G-code export,
// which should be stopped if print_diff is not empty.
@ -902,7 +902,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
for (auto it = range.first; it != range.second; ++ it) {
t_config_option_keys diff = it->print_object->config().diff(new_config);
if (! diff.empty()) {
update_apply_status(it->print_object->invalidate_state_by_config_options(diff));
update_apply_status(it->print_object->invalidate_state_by_config_options(it->print_object->config(), new_config, diff));
it->print_object->config_apply_only(new_config, diff, true);
}
}
@ -1091,10 +1091,11 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
if (this_region_config_set) {
t_config_option_keys diff = region.config().diff(this_region_config);
if (! diff.empty()) {
region.config_apply_only(this_region_config, diff, false);
// Stop the background process before assigning new configuration to the regions.
for (PrintObject *print_object : m_objects)
if (region_id < print_object->region_volumes.size() && ! print_object->region_volumes[region_id].empty())
update_apply_status(print_object->invalidate_state_by_config_options(diff));
update_apply_status(print_object->invalidate_state_by_config_options(region.config(), this_region_config, diff));
region.config_apply_only(this_region_config, diff, false);
}
}
}

View file

@ -248,7 +248,9 @@ private:
// Invalidates all PrintObject and Print steps.
bool invalidate_all_steps();
// Invalidate steps based on a set of parameters changed.
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
// It may be called for both the PrintObjectConfig and PrintRegionConfig.
bool invalidate_state_by_config_options(
const ConfigOptionResolver &old_config, const ConfigOptionResolver &new_config, const std::vector<t_config_option_key> &opt_keys);
// If ! m_slicing_params.valid, recalculate.
void update_slicing_parameters();
@ -509,7 +511,7 @@ private:
t_config_option_keys &full_config_diff,
DynamicPrintConfig &filament_overrides) const;
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
bool invalidate_state_by_config_options(const ConfigOptionResolver &new_config, const std::vector<t_config_option_key> &opt_keys);
void _make_skirt();
void _make_wipe_tower();

View file

@ -509,7 +509,8 @@ SupportLayerPtrs::iterator PrintObject::insert_support_layer(SupportLayerPtrs::i
// Called by Print::apply().
// This method only accepts PrintObjectConfig and PrintRegionConfig option keys.
bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys)
bool PrintObject::invalidate_state_by_config_options(
const ConfigOptionResolver &old_config, const ConfigOptionResolver &new_config, const std::vector<t_config_option_key> &opt_keys)
{
if (opt_keys.empty())
return false;
@ -574,7 +575,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bottom_solid_layers") {
steps.emplace_back(posPrepareInfill);
if(m_print->config().spiral_vase) {
if (m_print->config().spiral_vase) {
// Changing the number of bottom layers when a spiral vase is enabled requires re-slicing the object again.
// Otherwise, holes in the bottom layers could be filled, as is reported in GH #5528.
steps.emplace_back(posSlice);
@ -605,13 +606,19 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "top_infill_extrusion_width"
|| opt_key == "first_layer_extrusion_width") {
steps.emplace_back(posInfill);
} else if (
//FIXME
} else if (opt_key == "fill_density") {
// One likely wants to reslice only when switching between zero infill to simulate boolean difference (subtracting volumes),
// normal infill and 100% (solid) infill.
opt_key == "fill_density"
// for perimeter - infill overlap
|| opt_key == "solid_infill_extrusion_width") {
const auto *old_density = old_config.option<ConfigOptionPercent>(opt_key);
const auto *new_density = new_config.option<ConfigOptionPercent>(opt_key);
assert(old_density && new_density);
//FIXME Vojtech is not quite sure about the 100% here, maybe it is not needed.
if (is_approx(old_density->value, 0.) || is_approx(old_density->value, 100.) ||
is_approx(new_density->value, 0.) || is_approx(new_density->value, 100.))
steps.emplace_back(posPerimeters);
steps.emplace_back(posPrepareInfill);
} else if (opt_key == "solid_infill_extrusion_width") {
// This value is used for calculating perimeter - infill overlap, thus perimeters need to be recalculated.
steps.emplace_back(posPerimeters);
steps.emplace_back(posPrepareInfill);
} else if (