max_layer_height & min_layer_height now can be percent.

Also some fixes on crash that may happens when using them.
This commit is contained in:
supermerill 2021-10-30 16:33:19 +02:00
parent 0a61223a53
commit 41c0fb19d7
14 changed files with 123 additions and 90 deletions

View File

@ -1108,9 +1108,12 @@ private:
struct FloatOrPercent
{
public:
double value;
bool percent;
double get_abs_value(double ratio) const { return percent ? value * ratio : value; }
private:
friend class cereal::access;
template<class Archive> void serialize(Archive & ar) {ar(this->value); ar(this->percent); }

View File

@ -518,8 +518,10 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
gap_over_supports = std::max(0., gap_over_supports);
// Not a soluble support,
double support_layer_height_min = 1000000.;
for (auto lh : object.print()->config().min_layer_height.values)
support_layer_height_min = std::min(support_layer_height_min, std::max(0.01, lh));
const ConfigOptionFloatsOrPercents& min_layer_height = object.print()->config().min_layer_height;
const ConfigOptionFloats& nozzle_diameter = object.print()->config().nozzle_diameter;
for(int extr_id = 0; extr_id < min_layer_height.values.size(); ++extr_id)
support_layer_height_min = std::min(support_layer_height_min, std::max(nozzle_diameter.values[extr_id]/40, min_layer_height.get_abs_value(extr_id, nozzle_diameter.values[extr_id])));
gap_over_supports += support_layer_height_min;
}
@ -2915,9 +2917,9 @@ std::string GCode::extrude_loop_vase(const ExtrusionLoop &original_loop, const s
}
//all in unscaled coordinates (hence why it's coordf_t and not coord_t)
const coordf_t min_height = EXTRUDER_CONFIG_WITH_DEFAULT(min_layer_height, this->m_layer->height);
const coordf_t min_height = m_config.min_layer_height.get_abs_value(m_writer.tool()->id(), m_config.nozzle_diameter.get_at(m_writer.tool()->id()));
const coordf_t bot_init_z = - this->m_layer->height;
//const coordf_t bot_last_z = bot_init_z + this->m_layer->height - EXTRUDER_CONFIG(min_layer_height);
//const coordf_t bot_last_z = bot_init_z + this->m_layer->height - m_config.min_layer_height.get_abs_value(m_writer.tool()->id(), m_config.nozzle_diameter.get_at(m_writer.tool()->id()));
const coordf_t init_z = bot_init_z + min_height;
//const coordf_t last_z = bot_init_z + this->m_layer->height;
@ -3157,7 +3159,7 @@ std::string GCode::extrude_loop(const ExtrusionLoop &original_loop, const std::s
//but not for the first layer
&& this->m_layer->id() > 0
//exclude if min_layer_height * 2 > layer_height (increase from 2 to 3 because it's working but uses in-between)
&& this->m_layer->height >= EXTRUDER_CONFIG_WITH_DEFAULT(min_layer_height, 0) * 2 - EPSILON
&& this->m_layer->height >= m_config.min_layer_height.get_abs_value(m_writer.tool()->id(), m_config.nozzle_diameter.get_at(m_writer.tool()->id())) * 2 - EPSILON
) {
return extrude_loop_vase(original_loop, description, speed, lower_layer_edge_grid);
}

View File

@ -349,7 +349,7 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
// Test for a raft, insert additional wipe tower layer to fill in the raft separation gap.
double max_layer_height = std::numeric_limits<double>::max();
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
double mlh = config.max_layer_height.values[i];
double mlh = config.max_layer_height.get_abs_value(i, config.nozzle_diameter.values[i]);
if (mlh == 0.)
mlh = 0.75 * config.nozzle_diameter.values[i];
max_layer_height = std::min(max_layer_height, mlh);

View File

@ -1595,9 +1595,9 @@ std::pair<PrintBase::PrintValidationError, std::string> Print::validate() const
PrintRegion::collect_object_printing_extruders(config(), object->config(), region->config(), object_extruders);
double layer_height = object->config().layer_height.value;
for (uint16_t extruder_id : object_extruders) {
double min_layer_height = config().min_layer_height.values[extruder_id];
double max_layer_height = config().max_layer_height.values[extruder_id];
double nozzle_diameter = config().nozzle_diameter.values[extruder_id];
double nozzle_diameter = config().nozzle_diameter.get_at(extruder_id);
double min_layer_height = config().min_layer_height.get_abs_value(extruder_id, nozzle_diameter);
double max_layer_height = config().max_layer_height.get_abs_value(extruder_id, nozzle_diameter);
if (max_layer_height < EPSILON) max_layer_height = nozzle_diameter * 0.75;
if (min_layer_height > max_layer_height) return { PrintBase::PrintValidationError::pveWrongSettings, L("Min layer height can't be greater than Max layer height") };
if (max_layer_height > nozzle_diameter) return { PrintBase::PrintValidationError::pveWrongSettings, L("Max layer height can't be greater than nozzle diameter") };

View File

@ -2732,19 +2732,21 @@ void PrintConfigDef::init_fff_params()
def->is_vector_extruder = true;
def->set_default_value(new ConfigOptionInts { 100 });
def = this->add("max_layer_height", coFloats);
def = this->add("max_layer_height", coFloatsOrPercents);
def->label = L("Max");
def->full_label = L("Max layer height");
def->category = OptionCategory::general;
def->tooltip = L("This is the highest printable layer height for this extruder, used to cap "
"the variable layer height and support layer height. Maximum recommended layer height "
"is 75% of the extrusion width to achieve reasonable inter-layer adhesion. "
"If set to 0, layer height is limited to 75% of the nozzle diameter.");
def->sidetext = L("mm");
"\nCan be a % of the nozzle diameter."
"\nIf set to 0, layer height is limited to 75% of the nozzle diameter.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->mode = comSimple;
def->is_vector_extruder = true;
def->set_default_value(new ConfigOptionFloats { 0. });
def->set_default_value(new ConfigOptionFloatsOrPercents{ FloatOrPercent{ 75, true} });
def = this->add("max_print_speed", coFloat);
def->label = L("Max print speed");
@ -2824,17 +2826,19 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(false));
def = this->add("min_layer_height", coFloats);
def = this->add("min_layer_height", coFloatsOrPercents);
def->label = L("Min");
def->full_label = L("Min layer height");
def->category = OptionCategory::extruders;
def->tooltip = L("This is the lowest printable layer height for this extruder and limits "
"the resolution for variable layer height. Typical values are between 0.05 mm and 0.1 mm.");
def->sidetext = L("mm");
"the resolution for variable layer height. Typical values are between 0.05 mm and 0.1 mm."
"\nCan be a % of the nozzle diameter.");
def->sidetext = L("mm or %");
def->ratio_over = "nozzle_diameter";
def->min = 0;
def->mode = comSimple;
def->is_vector_extruder = true;
def->set_default_value(new ConfigOptionFloats { 0.07 });
def->set_default_value(new ConfigOptionFloatsOrPercents{ FloatOrPercent{ 5, true} });
def = this->add("min_length", coFloat);
def->label = L("Minimum extrusion length");

View File

@ -1339,7 +1339,7 @@ public:
ConfigOptionInts full_fan_speed_layer;
ConfigOptionFloatOrPercent infill_acceleration;
ConfigOptionInts max_fan_speed;
ConfigOptionFloats max_layer_height;
ConfigOptionFloatsOrPercents max_layer_height;
ConfigOptionFloat max_print_height;
ConfigOptionPercents max_speed_reduction;
ConfigOptionFloats milling_diameter;
@ -1348,7 +1348,7 @@ public:
//ConfigOptionPoints milling_offset;
//ConfigOptionFloats milling_z_offset;
ConfigOptionInts min_fan_speed;
ConfigOptionFloats min_layer_height;
ConfigOptionFloatsOrPercents min_layer_height;
ConfigOptionFloats min_print_speed;
ConfigOptionFloat min_skirt_length;
ConfigOptionString notes;

View File

@ -39,36 +39,40 @@ inline bool test_z_step(const coordf_t val, const coordf_t z_step) {
}
// Minimum layer height for the variable layer height algorithm.
inline coordf_t min_layer_height_from_nozzle(const PrintConfig &print_config, int idx_nozzle)
// idx_nozzle began at 0
inline coordf_t min_layer_height_from_nozzle(const PrintConfig &print_config, uint16_t idx_nozzle)
{
coordf_t min_layer_height = print_config.min_layer_height.get_at(idx_nozzle - 1);
coordf_t min_layer_height = print_config.min_layer_height.get_abs_value(idx_nozzle, print_config.nozzle_diameter.get_at(idx_nozzle));
return check_z_step( (min_layer_height == 0.) ? (MIN_LAYER_HEIGHT_DEFAULT) : std::max(MIN_LAYER_HEIGHT, min_layer_height), print_config.z_step);
}
// Maximum layer height for the variable layer height algorithm, 3/4 of a nozzle dimaeter by default,
// it should not be smaller than the minimum layer height.
inline coordf_t max_layer_height_from_nozzle(const PrintConfig &print_config, int idx_nozzle)
// idx_nozzle began at 0
inline coordf_t max_layer_height_from_nozzle(const PrintConfig &print_config, uint16_t idx_nozzle)
{
coordf_t min_layer_height = min_layer_height_from_nozzle(print_config, idx_nozzle);
coordf_t max_layer_height = print_config.max_layer_height.get_at(idx_nozzle - 1);
coordf_t nozzle_dmr = print_config.nozzle_diameter.get_at(idx_nozzle - 1);
coordf_t nozzle_dmr = print_config.nozzle_diameter.get_at(idx_nozzle);
coordf_t max_layer_height = print_config.max_layer_height.get_abs_value(idx_nozzle, nozzle_dmr);
return check_z_step(std::max(min_layer_height, (max_layer_height == 0.) ? (0.75 * nozzle_dmr) : max_layer_height), print_config.z_step);
}
// Minimum layer height for the variable layer height algorithm.
coordf_t Slicing::min_layer_height_from_nozzle(const DynamicPrintConfig &print_config, int idx_nozzle)
// idx_nozzle began at 0
coordf_t Slicing::min_layer_height_from_nozzle(const DynamicPrintConfig &print_config, uint16_t idx_nozzle)
{
coordf_t min_layer_height = print_config.opt_float("min_layer_height", idx_nozzle - 1);
coordf_t min_layer_height = print_config.get_computed_value("min_layer_height", idx_nozzle);
return check_z_step((min_layer_height == 0.) ? (MIN_LAYER_HEIGHT_DEFAULT) : std::max(MIN_LAYER_HEIGHT, min_layer_height), print_config.opt_float("z_step"));
}
// Maximum layer height for the variable layer height algorithm, 3/4 of a nozzle dimaeter by default,
// it should not be smaller than the minimum layer height.
coordf_t Slicing::max_layer_height_from_nozzle(const DynamicPrintConfig &print_config, int idx_nozzle)
// idx_nozzle began at 0
coordf_t Slicing::max_layer_height_from_nozzle(const DynamicPrintConfig &print_config, uint16_t idx_nozzle)
{
coordf_t min_layer_height = min_layer_height_from_nozzle(print_config, idx_nozzle);
coordf_t max_layer_height = print_config.opt_float("max_layer_height", idx_nozzle - 1);
coordf_t nozzle_dmr = print_config.opt_float("nozzle_diameter", idx_nozzle - 1);
coordf_t max_layer_height = print_config.get_computed_value("max_layer_height", idx_nozzle);
coordf_t nozzle_dmr = print_config.opt_float("nozzle_diameter", idx_nozzle);
return check_z_step(std::max(min_layer_height, (max_layer_height == 0.) ? (0.75 * nozzle_dmr) : max_layer_height), print_config.opt_float("z_step"));
}
@ -124,18 +128,26 @@ SlicingParameters SlicingParameters::create_from_config(
if (params.object_print_z_max < object_height) params.object_print_z_max += params.z_step;
// Miniumum/maximum of the minimum layer height over all extruders.
params.min_layer_height = MIN_LAYER_HEIGHT;
params.min_layer_height = 0;
params.max_layer_height = std::numeric_limits<double>::max();
params.max_suport_layer_height = 0;
params.exact_last_layer_height = object_config.exact_last_layer_height.value;
if (object_config.support_material.value || params.base_raft_layers > 0) {
// Has some form of support. Add the support layers to the minimum / maximum layer height limits.
params.min_layer_height = std::max(
min_layer_height_from_nozzle(print_config, object_config.support_material_extruder),
min_layer_height_from_nozzle(print_config, object_config.support_material_interface_extruder));
params.max_layer_height = std::min(
max_layer_height_from_nozzle(print_config, object_config.support_material_extruder),
max_layer_height_from_nozzle(print_config, object_config.support_material_interface_extruder));
params.max_suport_layer_height = params.max_layer_height;
if (object_config.support_material_extruder > 0)
params.min_layer_height = std::max(params.min_layer_height,
min_layer_height_from_nozzle(print_config, object_config.support_material_extruder - 1));
if (object_config.support_material_interface_extruder > 0)
params.min_layer_height = std::max(params.min_layer_height,
min_layer_height_from_nozzle(print_config, object_config.support_material_interface_extruder - 1));
if (object_config.support_material_extruder > 0)
params.max_layer_height = std::min(params.max_layer_height,
max_layer_height_from_nozzle(print_config, object_config.support_material_extruder - 1));
if (object_config.support_material_interface_extruder > 0)
params.max_layer_height = std::min(params.max_layer_height,
max_layer_height_from_nozzle(print_config, object_config.support_material_interface_extruder - 1));
if (params.max_layer_height < std::numeric_limits<double>::max())
params.max_suport_layer_height = params.max_layer_height;
}
if (object_extruders.empty()) {
params.min_layer_height = std::max(params.min_layer_height, min_layer_height_from_nozzle(print_config, 0));
@ -151,6 +163,7 @@ SlicingParameters SlicingParameters::create_from_config(
//apply z_step to min/max
params.min_layer_height = check_z_step(params.min_layer_height, params.z_step);
params.max_layer_height = check_z_step(params.max_layer_height, params.z_step);
if (params.max_suport_layer_height == 0) params.max_suport_layer_height = params.max_layer_height;
params.max_suport_layer_height = check_z_step(params.max_suport_layer_height, params.z_step);
if (! soluble_interface) {

View File

@ -188,13 +188,13 @@ extern int generate_layer_height_texture(
void *data, int rows, int cols, bool level_of_detail_2nd_level);
namespace Slicing {
// Minimum layer height for the variable layer height algorithm. Nozzle index is 1 based.
coordf_t min_layer_height_from_nozzle(const DynamicPrintConfig &print_config, int idx_nozzle);
// Minimum layer height for the variable layer height algorithm. Nozzle index is 0 based.
coordf_t min_layer_height_from_nozzle(const DynamicPrintConfig &print_config, uint16_t idx_nozzle);
// Maximum layer height for the variable layer height algorithm, 3/4 of a nozzle dimaeter by default,
// it should not be smaller than the minimum layer height.
// Nozzle index is 1 based.
coordf_t max_layer_height_from_nozzle(const DynamicPrintConfig &print_config, int idx_nozzle);
// Nozzle index is 0 based.
coordf_t max_layer_height_from_nozzle(const DynamicPrintConfig &print_config, uint16_t idx_nozzle);
} // namespace Slicing
} // namespace Slic3r

View File

@ -152,8 +152,10 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
{
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
m_support_layer_height_min = 1000000.;
for (auto lh : m_print_config->min_layer_height.values)
m_support_layer_height_min = std::min(m_support_layer_height_min, std::max(0.01, lh));
const ConfigOptionFloatsOrPercents& min_layer_height = m_print_config->min_layer_height;
const ConfigOptionFloats& nozzle_diameter = m_print_config->nozzle_diameter;
for (int extr_id = 0; extr_id < min_layer_height.values.size(); ++extr_id)
m_support_layer_height_min = std::min(m_support_layer_height_min, std::max(0.01, min_layer_height.get_abs_value(extr_id, nozzle_diameter.get_at(extr_id))));
if (m_object_config->support_material_interface_layers.value == 0) {
// No interface layers allowed, print everything with the base support pattern.

View File

@ -150,7 +150,7 @@ void CalibrationBridgeDialog::create_geometry(std::string setting_to_test, bool
double z_step = printer_config->option<ConfigOptionFloat>("z_step")->value;
if (z_step == 0)
z_step = 0.1;
double max_height = printer_config->option<ConfigOptionFloats>("max_layer_height")->values[0];
double max_height = printer_config->get_computed_value("max_layer_height",0);
if (max_height > first_layer_height + z_step)
for (size_t i = 0; i < nb_items; i++)
model.objects[objs_idx[i]]->config.set_key_value("first_layer_height", new ConfigOptionFloatOrPercent(first_layer_height + z_step, false));

View File

@ -461,36 +461,36 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
// The layer editing shader was already active.
current_shader = nullptr;
const_cast<LayersEditing*>(this)->generate_layer_height_texture();
const_cast<LayersEditing*>(this)->generate_layer_height_texture();
// Uniforms were resolved, go ahead using the layer editing shader.
// Uniforms were resolved, go ahead using the layer editing shader.
shader->set_uniform("z_to_texture_row", float(m_layers_texture.cells - 1) / (float(m_layers_texture.width) * float(m_object_max_z)));
shader->set_uniform("z_texture_row_to_normalized", 1.0f / float(m_layers_texture.height));
shader->set_uniform("z_cursor", float(m_object_max_z) * float(this->get_cursor_z_relative(canvas)));
shader->set_uniform("z_cursor_band_width", float(this->band_width));
// Initialize the layer height texture mapping.
GLsizei w = (GLsizei)m_layers_texture.width;
GLsizei h = (GLsizei)m_layers_texture.height;
GLsizei half_w = w / 2;
GLsizei half_h = h / 2;
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data()));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4));
for (const GLVolume* glvolume : volumes.volumes) {
// Render the object using the layer editing shader and texture.
if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
continue;
// Initialize the layer height texture mapping.
GLsizei w = (GLsizei)m_layers_texture.width;
GLsizei h = (GLsizei)m_layers_texture.height;
GLsizei half_w = w / 2;
GLsizei half_h = h / 2;
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
glsafe(::glBindTexture(GL_TEXTURE_2D, m_z_texture_id));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
glsafe(::glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, half_w, half_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data()));
glsafe(::glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, half_w, half_h, GL_RGBA, GL_UNSIGNED_BYTE, m_layers_texture.data.data() + m_layers_texture.width * m_layers_texture.height * 4));
for (const GLVolume* glvolume : volumes.volumes) {
// Render the object using the layer editing shader and texture.
if (! glvolume->is_active || glvolume->composite_id.object_id != this->last_object_id || glvolume->is_modifier)
continue;
shader->set_uniform("volume_world_matrix", glvolume->world_matrix());
shader->set_uniform("object_max_z", GLfloat(0));
glvolume->render();
}
// Revert back to the previous shader.
glBindTexture(GL_TEXTURE_2D, 0);
shader->set_uniform("volume_world_matrix", glvolume->world_matrix());
shader->set_uniform("object_max_z", GLfloat(0));
glvolume->render();
}
// Revert back to the previous shader.
glBindTexture(GL_TEXTURE_2D, 0);
if (current_shader != nullptr)
current_shader->start_using();
}
@ -1527,10 +1527,12 @@ bool GLCanvas3D::is_layers_editing_allowed() const
void GLCanvas3D::reset_layer_height_profile()
{
wxGetApp().plater()->take_snapshot(_L("Variable layer height - Reset"));
m_layers_editing.reset_layer_height_profile(*this);
m_layers_editing.state = LayersEditing::Completed;
m_dirty = true;
if (is_layers_editing_enabled()) {
wxGetApp().plater()->take_snapshot(_L("Variable layer height - Reset"));
m_layers_editing.reset_layer_height_profile(*this);
m_layers_editing.state = LayersEditing::Completed;
m_dirty = true;
}
}
void GLCanvas3D::adaptive_layer_height_profile(float quality_factor)

View File

@ -3401,14 +3401,14 @@ void ObjectList::del_layer_range(const t_layer_height_range& range)
static double get_min_layer_height(const int extruder_idx)
{
const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
return config.opt_float("min_layer_height", std::max(0, extruder_idx - 1));
return config.get_computed_value("min_layer_height", std::max(0, extruder_idx - 1));
}
static double get_max_layer_height(const int extruder_idx)
{
const DynamicPrintConfig& config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
int extruder_idx_zero_based = std::max(0, extruder_idx - 1);
double max_layer_height = config.opt_float("max_layer_height", extruder_idx_zero_based);
double max_layer_height = config.get_computed_value("max_layer_height", extruder_idx_zero_based);
// In case max_layer_height is set to zero, it should default to 75 % of nozzle diameter:
if (max_layer_height < EPSILON)

View File

@ -496,7 +496,7 @@ std::string PresetHints::top_bottom_shell_thickness_explanation(const PresetBund
double layer_height = print_config.opt_float("layer_height");
bool variable_layer_height = printer_config.opt_bool("variable_layer_height");
//FIXME the following line takes into account the 1st extruder only.
double min_layer_height = variable_layer_height ? Slicing::min_layer_height_from_nozzle(printer_config, 1) : layer_height;
double min_layer_height = variable_layer_height ? Slicing::min_layer_height_from_nozzle(printer_config, 0) : layer_height;
if (layer_height <= 0.f) {
out += _utf8(L("Top / bottom shell thickness hint: Not available due to invalid layer height."));

View File

@ -1191,6 +1191,11 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
wxGetApp().mainframe->plater()->canvas3D()->set_arrange_settings(m_presets->get_edited_preset().config, m_presets->get_edited_preset().printer_technology());
}
// reset variable layer height if min/max has changed, as it's probably now invalid.
if (opt_key.find("min_layer_height") == 0 || opt_key.find("max_layer_height") == 0) {
wxPostEvent((wxEvtHandler*)wxGetApp().mainframe->plater()->canvas3D()->get_wxglcanvas(), SimpleEvent(EVT_GLCANVAS_RESET_LAYER_HEIGHT_PROFILE));
}
//wxGetApp().preset_bundle->value_changed(opt_key);
// update phony fields
@ -3036,24 +3041,26 @@ void TabPrinter::toggle_options()
int64_t z_step_Mlong = (int64_t)(z_step * 1000000.);
DynamicPrintConfig new_conf;
bool has_changed = false;
const std::vector<double>& min_layer_height = m_config->option<ConfigOptionFloats>("min_layer_height")->values;
for (int i = 0; i < min_layer_height.size(); i++) {
if (min_layer_height[i] != 0 && (int64_t)(min_layer_height[i] * 1000000.) % z_step_Mlong != 0) {
if (!has_changed)
new_conf = *m_config;
new_conf.option<ConfigOptionFloats>("min_layer_height")->values[i] = std::max(z_step, Slic3r::check_z_step(new_conf.option<ConfigOptionFloats>("min_layer_height")->values[i], z_step));
has_changed = true;
}
}
const std::vector<double>& nozzle_diameters = m_config->option<ConfigOptionFloats>("nozzle_diameter")->values;
std::vector<double> max_layer_height = m_config->option<ConfigOptionFloats>("max_layer_height")->values;
const std::vector<FloatOrPercent>& min_layer_height = m_config->option<ConfigOptionFloatsOrPercents>("min_layer_height")->values;
for (int i = 0; i < min_layer_height.size(); i++) {
if(!min_layer_height[i].percent)
if (min_layer_height[i].get_abs_value(nozzle_diameters[i]) != 0 && (int64_t)(min_layer_height[i].get_abs_value(nozzle_diameters[i]) * 1000000.) % z_step_Mlong != 0) {
if (!has_changed)
new_conf = *m_config;
new_conf.option<ConfigOptionFloatsOrPercents>("min_layer_height")->values[i] = FloatOrPercent{ std::max(z_step, Slic3r::check_z_step(min_layer_height[i].get_abs_value(nozzle_diameters[i]), z_step)), false };
has_changed = true;
}
}
std::vector<FloatOrPercent> max_layer_height = m_config->option<ConfigOptionFloatsOrPercents>("max_layer_height")->values;
for (int i = 0; i < max_layer_height.size(); i++) {
if ((int64_t)(max_layer_height[i] * 1000000.) % z_step_Mlong != 0) {
if (!has_changed)
new_conf = *m_config;
new_conf.option<ConfigOptionFloats>("max_layer_height")->values[i] = std::max(z_step, Slic3r::check_z_step(new_conf.option<ConfigOptionFloats>("max_layer_height")->values[i], z_step));
has_changed = true;
}
if (!max_layer_height[i].percent)
if ((int64_t)(max_layer_height[i].get_abs_value(nozzle_diameters[i]) * 1000000.) % z_step_Mlong != 0) {
if (!has_changed)
new_conf = *m_config;
new_conf.option<ConfigOptionFloatsOrPercents>("max_layer_height")->values[i] = FloatOrPercent{ std::max(z_step, Slic3r::check_z_step(new_conf.option<ConfigOptionFloats>("max_layer_height")->values[i], z_step)), false };
has_changed = true;
}
}
if (has_changed) {
load_config(new_conf);