Skip to content

Commit

Permalink
#239 add z_step (inverse of slic3r z_steps_per_mm)
Browse files Browse the repository at this point in the history
seems to work without breaking.
todo: change all slicing stuff from double to scaled int.
  • Loading branch information
supermerill committed Jun 10, 2020
1 parent b78a91b commit 98c6217
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 11 deletions.
1 change: 1 addition & 0 deletions resources/ui_layout/printer_fff.ui
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ group:Size and coordinates
bed_shape
setting:max_print_height
setting:z_offset
setting:z_step
group:extruders_count_event:milling_count_event:Capabilities
extruders_count
setting:single_extruder_multi_material
Expand Down
13 changes: 13 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3480,6 +3480,15 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));

def = this->add("z_step", coFloat);
def->label = L("Z full step");
def->tooltip = L("Set this to the number of *full* steps (not microsteps) needed for moving the Z axis by 1mm; you can calculate this by dividing the number of microsteps configured in your firmware by the microstepping amount (8, 16, 32). Slic3r will round your configured layer height to the nearest multiple of that value in order to ensure the best accuracy. This is most useful for machines with imperial leadscrews or belt-driven Z or for unusual layer heights with metric leadscrews. If you still experience wobbling, try using 4 * full_step to achieve the same motor phase pattern for every layer (important for belt driven z-axis). Set to zero to disable this experimental feature.");
def->cli = "z-step=f";
def->sidetext = L("mm");
def->min = 0.0001;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0.005));

// Declare retract values for filament profile, overriding the printer's extruder profile.
for (const char *opt_key : {
// floats
Expand Down Expand Up @@ -4349,6 +4358,10 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
float v = boost::lexical_cast<float>(value);
if (v > 0)
value = boost::lexical_cast<std::string>(-v);
} else if (opt_key == "z_steps_per_mm") {
opt_key = "z_step";
float v = boost::lexical_cast<float>(value);
value = boost::lexical_cast<std::string>(1/v);
}

// Ignore the following obsolete configuration keys:
Expand Down
4 changes: 3 additions & 1 deletion src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,8 @@ class GCodeConfig : public StaticPrintConfig
ConfigOptionFloat wipe_advanced_nozzle_melted_volume;
ConfigOptionFloat wipe_advanced_multiplier;
ConfigOptionFloats wipe_extra_perimeter;
ConfigOptionEnum<WipeAlgo> wipe_advanced_algo;
ConfigOptionEnum<WipeAlgo> wipe_advanced_algo;
ConfigOptionFloat z_step;

std::string get_extrusion_axis() const
{
Expand Down Expand Up @@ -1010,6 +1011,7 @@ class GCodeConfig : public StaticPrintConfig
OPT_PTR(wipe_advanced_multiplier);
OPT_PTR(wipe_advanced_algo);
OPT_PTR(wipe_extra_perimeter);
OPT_PTR(z_step);
}
};

Expand Down
86 changes: 77 additions & 9 deletions src/libslic3r/Slicing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,23 @@ namespace Slic3r
static const coordf_t MIN_LAYER_HEIGHT = 0.01;
static const coordf_t MIN_LAYER_HEIGHT_DEFAULT = 0.07;

inline coordf_t check_z_step(coordf_t val, coordf_t z_step) {
uint64_t valint = uint64_t(val * 100000. + 0.1);
uint64_t stepint = uint64_t(z_step * 100000.);
return (((valint + (stepint/2)) / stepint) * stepint) / 100000.;
//return int((val + z_step * 0.5) / z_step) * z_step;
}
inline bool test_z_step(coordf_t val, coordf_t z_step) {
uint64_t valint = uint64_t(val * 100000 + 0.1);
uint64_t stepint = uint64_t(z_step * 100000);
return valint % stepint == 0;
}

// Minimum layer height for the variable layer height algorithm.
inline coordf_t min_layer_height_from_nozzle(const PrintConfig &print_config, int idx_nozzle)
{
coordf_t min_layer_height = print_config.min_layer_height.get_at(idx_nozzle - 1);
return (min_layer_height == 0.) ? MIN_LAYER_HEIGHT_DEFAULT : std::max(MIN_LAYER_HEIGHT, min_layer_height);
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,
Expand All @@ -38,14 +50,14 @@ inline coordf_t max_layer_height_from_nozzle(const PrintConfig &print_config, in
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);
return std::max(min_layer_height, (max_layer_height == 0.) ? (0.75 * nozzle_dmr) : max_layer_height);
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)
{
coordf_t min_layer_height = print_config.opt_float("min_layer_height", idx_nozzle - 1);
return (min_layer_height == 0.) ? MIN_LAYER_HEIGHT_DEFAULT : std::max(MIN_LAYER_HEIGHT, min_layer_height);
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,
Expand All @@ -55,7 +67,7 @@ coordf_t Slicing::max_layer_height_from_nozzle(const DynamicPrintConfig &print_c
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);
return std::max(min_layer_height, (max_layer_height == 0.) ? (0.75 * nozzle_dmr) : max_layer_height);
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"));
}

SlicingParameters SlicingParameters::create_from_config(
Expand All @@ -65,10 +77,11 @@ SlicingParameters SlicingParameters::create_from_config(
const std::vector<uint16_t> &object_extruders)
{
//first layer height is got from the first_layer_height setting unless the value was garbage.
// if the first_layer_height setting depends of the nozzle width, use the first one.
// if the first_layer_height setting depends of the nozzle width, use the first one. Apply the z_step
coordf_t first_layer_height = (object_config.first_layer_height.get_abs_value(print_config.nozzle_diameter.empty() ? 0. : print_config.nozzle_diameter.get_at(0)) <= 0) ?
object_config.layer_height.value :
object_config.first_layer_height.get_abs_value(print_config.nozzle_diameter.get_at(0));
first_layer_height = check_z_step(first_layer_height, print_config.z_step);
// If object_config.support_material_extruder == 0 resp. object_config.support_material_interface_extruder == 0,
// print_config.nozzle_diameter.get_at(size_t(-1)) returns the 0th nozzle diameter,
// which is consistent with the requirement that if support_material_extruder == 0 resp. support_material_interface_extruder == 0,
Expand All @@ -86,6 +99,12 @@ SlicingParameters SlicingParameters::create_from_config(
params.object_print_z_max = object_height;
params.base_raft_layers = object_config.raft_layers.value;
params.soluble_interface = soluble_interface;
params.z_step = print_config.z_step;

//apply z_step to layer_height
params.layer_height = check_z_step(params.layer_height , params.z_step);
params.object_print_z_max = check_z_step(params.object_print_z_max, params.z_step);
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;
Expand All @@ -112,10 +131,16 @@ SlicingParameters SlicingParameters::create_from_config(
}
params.min_layer_height = std::min(params.min_layer_height, params.layer_height);
params.max_layer_height = std::max(params.max_layer_height, params.layer_height);
//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);
params.max_suport_layer_height = check_z_step(params.max_suport_layer_height, params.z_step);

if (! soluble_interface) {
params.gap_raft_object = object_config.support_material_contact_distance_top.get_abs_value(support_material_interface_extruder_dmr);
params.gap_raft_object = check_z_step(params.gap_raft_object, params.z_step);
params.gap_object_support = object_config.support_material_contact_distance_bottom.get_abs_value(support_material_interface_extruder_dmr);
params.gap_object_support = check_z_step(params.gap_object_support, params.z_step);
params.gap_support_object = params.gap_raft_object;
}

Expand All @@ -124,11 +149,14 @@ SlicingParameters SlicingParameters::create_from_config(
params.base_raft_layers -= params.interface_raft_layers;
// Use as large as possible layer height for the intermediate raft layers.
params.base_raft_layer_height = std::max(params.layer_height, 0.75 * support_material_extruder_dmr);
params.base_raft_layer_height = check_z_step(params.base_raft_layer_height, params.z_step);
params.interface_raft_layer_height = std::max(params.layer_height, 0.75 * support_material_interface_extruder_dmr);
params.interface_raft_layer_height = check_z_step(params.interface_raft_layer_height, params.z_step);
params.contact_raft_layer_height_bridging = false;
params.first_object_layer_bridging = false;
#if 1
params.contact_raft_layer_height = std::max(params.layer_height, 0.75 * support_material_interface_extruder_dmr);
params.contact_raft_layer_height = check_z_step(params.contact_raft_layer_height, params.z_step);
if (! soluble_interface) {
// Compute the average of all nozzles used for printing the object over a raft.
//FIXME It is expected, that the 1st layer of the object is printed with a bridging flow over a full raft. Shall it not be vice versa?
Expand All @@ -143,6 +171,7 @@ SlicingParameters SlicingParameters::create_from_config(
}
#else
params.contact_raft_layer_height = soluble_interface ? support_material_interface_extruder_dmr : 0.75 * support_material_interface_extruder_dmr;
params.contact_raft_layer_height = check_z_step(params.contact_raft_layer_height, params.z_step);
params.contact_raft_layer_height_bridging = ! soluble_interface;
...
#endif
Expand All @@ -169,6 +198,24 @@ SlicingParameters SlicingParameters::create_from_config(
params.object_print_z_max += print_z;
}

assert(test_z_step(params.interface_raft_layer_height , params.z_step));
assert(test_z_step(params.base_raft_layer_height, params.z_step));
assert(test_z_step(params.contact_raft_layer_height, params.z_step));
assert(test_z_step(params.layer_height, params.z_step));
assert(test_z_step(params.min_layer_height, params.z_step));
assert(test_z_step(params.max_layer_height, params.z_step));
assert(test_z_step(params.max_suport_layer_height, params.z_step));
assert(test_z_step(params.first_print_layer_height, params.z_step));
assert(test_z_step(params.first_object_layer_height, params.z_step));
assert(test_z_step(params.gap_raft_object, params.z_step));
assert(test_z_step(params.gap_object_support, params.z_step));
assert(test_z_step(params.gap_support_object, params.z_step));
assert(test_z_step(params.raft_base_top_z, params.z_step));
assert(test_z_step(params.raft_interface_top_z, params.z_step));
assert(test_z_step(params.raft_contact_top_z, params.z_step));
assert(test_z_step(params.object_print_z_min, params.z_step));
assert(test_z_step(params.object_print_z_max, params.z_step));

params.valid = true;
return params;
}
Expand All @@ -177,8 +224,12 @@ std::vector<std::pair<t_layer_height_range, coordf_t>> layer_height_ranges(const
{
std::vector<std::pair<t_layer_height_range, coordf_t>> out;
out.reserve(config_ranges.size());
for (const auto &kvp : config_ranges)
out.emplace_back(kvp.first, kvp.second.option("layer_height")->getFloat());
for (const auto& kvp : config_ranges) {
coordf_t z_step = kvp.second.opt_float("z_step");
coordf_t layer_height = kvp.second.opt_float("layer_height");
out.emplace_back(kvp.first, check_z_step(layer_height, z_step));

}
return out;
}

Expand All @@ -203,6 +254,9 @@ std::vector<coordf_t> layer_height_profile_from_ranges(
if (! ranges_non_overlapping.empty())
// Trim current low with the last high.
lo = std::max(lo, ranges_non_overlapping.back().first.second);
lo = check_z_step(lo, slicing_params.z_step);
hi = check_z_step(hi, slicing_params.z_step);
height = check_z_step(height, slicing_params.z_step);
if (lo + EPSILON < hi)
// Ignore too narrow ranges.
ranges_non_overlapping.push_back(std::pair<t_layer_height_range,coordf_t>(t_layer_height_range(lo, hi), height));
Expand Down Expand Up @@ -294,6 +348,7 @@ std::vector<double> layer_height_profile_adaptive(const SlicingParameters& slici
}
}
#endif
cusp_height = check_z_step(cusp_height, slicing_params.z_step);
height = std::min((coordf_t)cusp_height, height);

// apply z-gradation
Expand Down Expand Up @@ -373,6 +428,7 @@ std::vector<double> smooth_height_profile(const std::vector<double>& profile, co
for (size_t i = 0; i < skip_count; ++i)
{
ret.push_back(profile[i]);
ret[i] = check_z_step(ret[i], slicing_params.z_step);
}

// smooth the rest of the profile by biasing a gaussian blur
Expand All @@ -384,6 +440,7 @@ std::vector<double> smooth_height_profile(const std::vector<double>& profile, co
for (size_t i = skip_count; i < size; i += 2)
{
double zi = profile[i];
zi = check_z_step(zi, slicing_params.z_step);
double hi = profile[i + 1];
ret.push_back(zi);
ret.push_back(0.0);
Expand All @@ -407,6 +464,7 @@ std::vector<double> smooth_height_profile(const std::vector<double>& profile, co
height = clamp(slicing_params.min_layer_height, slicing_params.max_layer_height, (weight_total != 0.0) ? height /= weight_total : hi);
if (smoothing_params.keep_min)
height = std::min(height, hi);
height = check_z_step(height, slicing_params.z_step);
}

return ret;
Expand Down Expand Up @@ -482,7 +540,7 @@ void adjust_layer_height_profile(
coordf_t lo = std::max(z_span_variable.first, z - 0.5 * band_width);
// Do not limit the upper side of the band, so that the modifications to the top point of the profile will be allowed.
coordf_t hi = z + 0.5 * band_width;
coordf_t z_step = 0.1;
coordf_t z_step_adjust = 0.1;
size_t idx = 0;
while (idx < layer_height_profile.size() && layer_height_profile[idx] < lo)
idx += 2;
Expand Down Expand Up @@ -548,7 +606,7 @@ void adjust_layer_height_profile(
profile_new.push_back(height);
}
// Limit zz to the object height, so the next iteration the last profile point will be set.
zz = std::min(zz + z_step, z_span_variable.second);
zz = std::min(zz + z_step_adjust, z_span_variable.second);
idx = next;
while (idx < layer_height_profile.size() && layer_height_profile[idx] < zz)
idx += 2;
Expand Down Expand Up @@ -590,6 +648,10 @@ void adjust_layer_height_profile(
}
}

//i'm not sure it's needed. just in case.
for (size_t i = 0; i < layer_height_profile.size(); i ++)
layer_height_profile[i] = check_z_step(layer_height_profile[i], slicing_params.z_step);

assert(layer_height_profile.size() > 2);
assert(layer_height_profile.size() % 2 == 0);
assert(layer_height_profile[0] == 0.);
Expand Down Expand Up @@ -638,10 +700,12 @@ std::vector<coordf_t> generate_object_layers(
coordf_t z1 = layer_height_profile[idx_layer_height_profile];
coordf_t h1 = layer_height_profile[idx_layer_height_profile + 1];
height = h1;
height = check_z_step(height, slicing_params.z_step);
if (next < layer_height_profile.size()) {
coordf_t z2 = layer_height_profile[next];
coordf_t h2 = layer_height_profile[next + 1];
height = lerp(h1, h2, (slice_z - z1) / (z2 - z1));
height = check_z_step(height, slicing_params.z_step);
assert(height >= slicing_params.min_layer_height - EPSILON && height <= slicing_params.max_layer_height + EPSILON);
}
}
Expand Down Expand Up @@ -684,6 +748,10 @@ std::vector<coordf_t> generate_object_layers(
}
}

#ifdef _DEBUG
for (size_t i = 0; i < out.size(); i++)
assert(test_z_step(out[i], slicing_params.z_step/2));
#endif
return out;
}

Expand Down
4 changes: 4 additions & 0 deletions src/libslic3r/Slicing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class PrintConfig;
class PrintObjectConfig;
class ModelObject;

coordf_t check_z_step(coordf_t val, coordf_t z_step);

// Parameters to guide object slicing and support generation.
// The slicing parameters account for a raft and whether the 1st object layer is printed with a normal or a bridging flow
// (using a normal flow over a soluble support, using a bridging flow over a non-soluble support).
Expand Down Expand Up @@ -65,6 +67,8 @@ struct SlicingParameters
coordf_t max_layer_height;
coordf_t max_suport_layer_height;
bool exact_last_layer_height;
// min common divisor for all layer height
coordf_t z_step;

// First layer height of the print, this may be used for the first layer of the raft
// or for the first layer of the print.
Expand Down
3 changes: 2 additions & 1 deletion src/slic3r/GUI/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,8 @@ const std::vector<std::string>& Preset::printer_options()
"machine_max_jerk_x", "machine_max_jerk_y", "machine_max_jerk_z", "machine_max_jerk_e",
"time_estimation_compensation",
"print_machine_envelope",
"fan_speedup_time"
"fan_speedup_time",
"z_step"
};
s_opts.insert(s_opts.end(), Preset::nozzle_options().begin(), Preset::nozzle_options().end());
s_opts.insert(s_opts.end(), Preset::milling_options().begin(), Preset::milling_options().end());
Expand Down
27 changes: 27 additions & 0 deletions src/slic3r/GUI/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2576,6 +2576,33 @@ void TabPrinter::update_fff()
field->toggle(have_advanced_wipe_volume);
}
}

//z step checks
{
double z_step = m_config->opt_float("z_step");
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] / z_step != 0) {
if(!has_changed )
new_conf = *m_config;
new_conf.option<ConfigOptionFloats>("min_layer_height")->values[i] = std::max(z_step, check_z_step(new_conf.option<ConfigOptionFloats>("min_layer_height")->values[i], z_step));
has_changed = true;
}
const std::vector<double>& max_layer_height = m_config->option<ConfigOptionFloats>("max_layer_height")->values;
for (int i = 0; i < max_layer_height.size(); i++)
if (max_layer_height[i] / z_step != 0) {
if (!has_changed)
new_conf = *m_config;
new_conf.option<ConfigOptionFloats>("max_layer_height")->values[i] = std::max(z_step, check_z_step(new_conf.option<ConfigOptionFloats>("max_layer_height")->values[i], z_step));
has_changed = true;
}
if (has_changed) {
load_config(new_conf);
}
}

// Thaw();
}

Expand Down

0 comments on commit 98c6217

Please sign in to comment.