Fix sequential printing distance detection

* fix bug with skirt width
* always takes brim into account
This commit is contained in:
remi durand 2021-06-08 19:03:59 +02:00
parent b4fb97e527
commit 4ed4ec0151
6 changed files with 144 additions and 89 deletions

View File

@ -46,7 +46,7 @@ struct ArrangePolygon {
ExPolygon poly; /// The 2D silhouette to be arranged
Vec2crd translation{0, 0}; /// The translation of the poly
double rotation{0.0}; /// The rotation of the poly in radians
coord_t inflation = 0; /// Arrange with inflated polygon
//coord_t inflation = 0; /// Arrange with inflated polygon
int bed_idx{UNARRANGED}; /// To which logical bed does poly belong...
int priority{0};

View File

@ -64,50 +64,112 @@ static inline void throw_on_missing_variable(const std::string &opt_key, const c
// Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser.
double Flow::extrusion_width(const std::string& opt_key, const ConfigOptionFloatOrPercent* opt, const ConfigOptionResolver& config, const unsigned int first_printing_extruder)
{
assert(opt != nullptr);
assert(opt != nullptr);
bool first_layer = boost::starts_with(opt_key, "first_layer_");
bool first_layer = boost::starts_with(opt_key, "first_layer_") || boost::starts_with(opt_key, "brim_");
if (!first_layer && boost::starts_with(opt_key, "skirt_")) {
const ConfigOptionInt* optInt = config.option<ConfigOptionInt>("skirt_height");
const ConfigOptionBool* optBool = config.option<ConfigOptionBool>("draft_shield");
first_layer = (optBool && optInt && optInt->value == 1 && !optBool->value);
}
#if 0
// This is the logic used for skit / brim, but not for the rest of the 1st layer.
if (opt->value == 0. && first_layer) {
// The "first_layer_extrusion_width" was set to zero, try a substitute.
opt = config.option<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "perimeter_extrusion_width");
if (opt->value == 0.) {
// The role specific extrusion width value was set to zero, get a not-0 one (if possible)
opt = extrusion_option(opt_key, config);
}
if (opt->percent) {
auto opt_key_layer_height = first_layer ? "first_layer_height" : "layer_height";
auto opt_layer_height = config.option(opt_key_layer_height);
if (opt_layer_height == nullptr)
throw_on_missing_variable(opt_key, opt_key_layer_height);
// first_layer_height depends on first_printing_extruder
auto opt_nozzle_diameters = config.option<ConfigOptionFloats>("nozzle_diameter");
if (opt_nozzle_diameters == nullptr)
throw_on_missing_variable(opt_key, "nozzle_diameter");
return opt->get_abs_value(float(opt_nozzle_diameters->get_at(first_printing_extruder)));
}
if (opt->value == 0.) {
// If user left option to 0, calculate a sane default width.
auto opt_nozzle_diameters = config.option<ConfigOptionFloats>("nozzle_diameter");
if (opt_nozzle_diameters == nullptr)
throw_on_missing_variable(opt_key, "nozzle_diameter");
return auto_extrusion_width(opt_key_to_flow_role(opt_key), float(opt_nozzle_diameters->get_at(first_printing_extruder)));
}
return opt->value;
}
//used to get brim & skirt extrusion config
const ConfigOptionFloatOrPercent* Flow::extrusion_option(const std::string& opt_key, const ConfigOptionResolver& config)
{
const ConfigOptionFloatOrPercent* opt = config.option<ConfigOptionFloatOrPercent>(opt_key);
//brim is first_layer_extrusion_width then perimeter_extrusion_width
if (!opt && boost::starts_with(opt_key, "brim_")) {
const ConfigOptionFloatOrPercent* optTest = config.option<ConfigOptionFloatOrPercent>("first_layer_extrusion_width");
opt = optTest;
if (opt == nullptr)
throw_on_missing_variable(opt_key, "first_layer_extrusion_width");
if (opt->value == 0) {
opt = config.option<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "perimeter_extrusion_width");
}
}
if (opt == nullptr)
throw_on_missing_variable(opt_key, opt_key.c_str());
// This is the logic used for skit / brim, but not for the rest of the 1st layer.
if (opt->value == 0. && boost::starts_with(opt_key, "skirt")) {
// The "skirt_extrusion_width" was set to zero, try a substitute.
const ConfigOptionFloatOrPercent* optTest = config.option<ConfigOptionFloatOrPercent>("first_layer_extrusion_width");
const ConfigOptionInt* optInt = config.option<ConfigOptionInt>("skirt_height");
const ConfigOptionBool* optBool = config.option<ConfigOptionBool>("draft_shield");
if (optTest == nullptr)
throw_on_missing_variable(opt_key, "first_layer_extrusion_width");
if (optBool == nullptr)
throw_on_missing_variable(opt_key, "draft_shield");
if (optInt == nullptr)
throw_on_missing_variable(opt_key, "skirt_height");
// The "first_layer_extrusion_width" was set to zero, try a substitute.
if (optTest && optBool && optInt && optTest->value > 0 && optInt->value == 1 && !optBool->value)
opt = optTest;
if (opt->value == 0) {
opt = config.option<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "perimeter_extrusion_width");
}
}
#endif
// external_perimeter_extrusion_width default is perimeter_extrusion_width
if (opt->value == 0. && boost::starts_with(opt_key, "external_perimeter_extrusion_width")) {
// The role specific extrusion width value was set to zero, try the role non-specific extrusion width.
opt = config.option<ConfigOptionFloatOrPercent>("perimeter_extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "perimeter_extrusion_width");
}
// top_infill_extrusion_width default is solid_infill_extrusion_width
if (opt->value == 0. && boost::starts_with(opt_key, "top_infill_extrusion_width")) {
// The role specific extrusion width value was set to zero, try the role non-specific extrusion width.
opt = config.option<ConfigOptionFloatOrPercent>("solid_infill_extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "perimeter_extrusion_width");
}
if (opt->value == 0.) {
// The role specific extrusion width value was set to zero, try the role non-specific extrusion width.
opt = config.option<ConfigOptionFloatOrPercent>("extrusion_width");
if (opt == nullptr)
throw_on_missing_variable(opt_key, "extrusion_width");
// Use the "layer_height" instead of "first_layer_height".
first_layer = false;
}
if (opt->percent) {
auto opt_key_layer_height = first_layer ? "first_layer_height" : "layer_height";
auto opt_layer_height = config.option(opt_key_layer_height);
if (opt_layer_height == nullptr)
throw_on_missing_variable(opt_key, opt_key_layer_height);
// first_layer_height depends on first_printing_extruder
auto opt_nozzle_diameters = config.option<ConfigOptionFloats>("nozzle_diameter");
if (opt_nozzle_diameters == nullptr)
throw_on_missing_variable(opt_key, "nozzle_diameter");
return opt->get_abs_value(float(opt_nozzle_diameters->get_at(first_printing_extruder)));
}
if (opt->value == 0.) {
// If user left option to 0, calculate a sane default width.
auto opt_nozzle_diameters = config.option<ConfigOptionFloats>("nozzle_diameter");
if (opt_nozzle_diameters == nullptr)
throw_on_missing_variable(opt_key, "nozzle_diameter");
return auto_extrusion_width(opt_key_to_flow_role(opt_key), float(opt_nozzle_diameters->get_at(first_printing_extruder)));
}
return opt->value;
return opt;
}
// Used to provide hints to the user on default extrusion width values, and to provide reasonable values to the PlaceholderParser.

View File

@ -106,6 +106,8 @@ public:
// on active extruder etc. Therefore the value calculated by this function shall be used as a hint only.
static double extrusion_width(const std::string &opt_key, const ConfigOptionFloatOrPercent *opt, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0);
static double extrusion_width(const std::string &opt_key, const ConfigOptionResolver &config, const unsigned int first_printing_extruder = 0);
static const ConfigOptionFloatOrPercent* extrusion_option(const std::string& opt_key, const ConfigOptionResolver& config);
};
extern Flow support_material_flow(const PrintObject *object, float layer_height = 0.f);

View File

@ -1658,20 +1658,12 @@ double Print::skirt_first_layer_height() const
Flow Print::brim_flow(size_t extruder_id, const PrintObjectConfig& brim_config) const
{
ConfigOptionFloatOrPercent width = brim_config.first_layer_extrusion_width;
if (width.value <= 0)
width = m_default_region_config.perimeter_extrusion_width;
if (width.value <= 0)
width = brim_config.extrusion_width;
/* We currently use a random region's perimeter extruder.
While this works for most cases, we should probably consider all of the perimeter
extruders and take the one with, say, the smallest index.
The same logic should be applied to the code that selects the extruder during G-code
generation as well. */
//use default region, but current object config.
PrintRegionConfig tempConf = m_default_region_config;
tempConf.parent = &brim_config;
return Flow::new_from_config_width(
frPerimeter,
width,
*Flow::extrusion_option("brim_extrusion_width", tempConf),
(float)m_config.nozzle_diameter.get_at(extruder_id),
(float)this->skirt_first_layer_height()
);
@ -1679,27 +1671,14 @@ Flow Print::brim_flow(size_t extruder_id, const PrintObjectConfig& brim_config)
Flow Print::skirt_flow(size_t extruder_id) const
{
ConfigOptionFloatOrPercent width = m_config.skirt_extrusion_width;
if (width.value <= 0 && m_default_object_config.first_layer_extrusion_width.value > 0
&& m_config.skirt_height == 1 && !m_config.draft_shield)
width = m_default_object_config.first_layer_extrusion_width;
if (width.value <= 0)
width = m_default_region_config.perimeter_extrusion_width;
if (width.value <= 0)
width = m_default_object_config.extrusion_width;
/* We currently use a random object's support material extruder.
While this works for most cases, we should probably consider all of the support material
extruders and take the one with, say, the smallest index;
The same logic should be applied to the code that selects the extruder during G-code
generation as well. */
/* or select the used extruder with the highest nozzle diameter, to be on the safe side.*/
//send m_default_object_config becasue it's the lowest config needed (extrusion_option need config from object & print)
return Flow::new_from_config_width(
frPerimeter,
width,
(float)m_config.nozzle_diameter.get_at(extruder_id),
(float)this->skirt_first_layer_height()
*Flow::extrusion_option("skirt_extrusion_width", m_default_region_config),
(float)m_config.nozzle_diameter.get_at(extruder_id),
(float)this->skirt_first_layer_height()
);
}
bool Print::has_support_material() const
@ -1855,7 +1834,7 @@ void Print::process()
std::vector<uint16_t> set_extruders = this->object_extruders(m_objects);
append(set_extruders, this->support_material_extruders());
sort_remove_duplicates(set_extruders);
Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front(), obj_group.front()->config());
Flow flow = this->brim_flow(set_extruders.empty() ? m_regions.front()->config().perimeter_extruder - 1 : set_extruders.front(), m_default_object_config);
if (brim_config.brim_ears)
this->_make_brim_ears(flow, obj_group, brim_area, m_brim);
else

View File

@ -5671,48 +5671,56 @@ double PrintConfig::min_object_distance(const ConfigBase *config, double ref_hei
// min object distance is max(duplicate_distance, clearance_radius)
// /2 becasue we only count the grawing for the current object
//add 1 as safety offset.
//add 1 as safety offset.
double extruder_clearance_radius = config->option("extruder_clearance_radius")->getFloat() / 2 + 1;
if (extruder_clearance_radius > base_dist) {
base_dist = extruder_clearance_radius;
}
//std::cout << " min_object_distance add extruder_clearance_radius ("<< extruder_clearance_radius <<") =>" << base_dist << "\n";
//FIXME: now brim can be per-object, so you ahve to get a different min_object_distance per object
//add brim width
// note: now brim can be per-object, so you have to get a different min_object_distance per object
// You should increase/reduce the size of the polygons that have a model-wide setting.
const double first_layer_height = config->get_abs_value("first_layer_height");
if (ref_height <= first_layer_height && ref_height != 0) {
//FIXME: does not take into account object-defined brim !!! you can crash yoursefl with it
if (config->option("brim_width")->getFloat() > 0) {
brim_dist += config->option("brim_width")->getFloat();
//std::cout << " Set brim=" << config->option("brim_width")->getFloat() << " => " << brim_dist << "\n";
}
} else if (config->option("brim_width")->getFloat() + 1 > base_dist) {
base_dist = config->option("brim_width")->getFloat();
}
else //if (config->option("brim_width")->getFloat() + 1 > base_dist) {
base_dist += config->option("brim_width")->getFloat();
//}
//add the skirt
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() == 1 && ref_height == 0) {
skirt_dist = config->option("skirt_distance")->getFloat();
const double first_layer_width = config->get_abs_value("skirt_extrusion_width");
Flow flow(first_layer_width, first_layer_height, max_nozzle_diam);
skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
base_dist = std::max(base_dist, skirt_dist + 1);
skirt_dist = 0;
}else if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() > 0 && !config->option("complete_objects_one_skirt")->getBool()) {
double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height;
if (ref_height <= skirt_height) {
if (config->option("skirts")->getInt() > 0 && config->option("skirt_height")->getInt() >= 1 && !config->option("complete_objects_one_skirt")->getBool()) {
if (ref_height == 0) {
skirt_dist = config->option("skirt_distance")->getFloat();
const double first_layer_width = config->get_abs_value("skirt_extrusion_width");
Flow flow(first_layer_width, first_layer_height, max_nozzle_diam);
skirt_dist += first_layer_width + (flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
//std::cout << " Set skirt_dist=" << config->option("skirt_distance")->getFloat() << " => " << skirt_dist << "\n";
Flow skirt_flow = Flow::new_from_config_width(
frPerimeter,
*Flow::extrusion_option("skirt_extrusion_width", *config),
(float)max_nozzle_diam,
(float)first_layer_height
);
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
base_dist = std::max(base_dist, skirt_dist + 1);
//set to 0 becasue it's incorporated into the base_dist, so we don't want to be added in to it again.
skirt_dist = 0;
} else {
double skirt_height = ((double)config->option("skirt_height")->getInt() - 1) * config->get_abs_value("layer_height") + first_layer_height;
if (ref_height <= skirt_height) {
skirt_dist = config->option("skirt_distance")->getFloat();
Flow skirt_flow = Flow::new_from_config_width(
frPerimeter,
*Flow::extrusion_option("skirt_extrusion_width", *config),
(float)max_nozzle_diam,
(float)first_layer_height
);
skirt_dist += skirt_flow.width + (skirt_flow.spacing() * ((double)config->option("skirts")->getInt() - 1));
}
}
}
}
catch (const std::exception & ex) {
boost::nowide::cerr << ex.what() << std::endl;
}
//std::cout << "END min_object_distance =>" << (base_dist + std::max(skirt_dist, brim_dist)) << "\n";
return base_dist + std::max(skirt_dist, brim_dist);
}
return base_dist;

View File

@ -1980,10 +1980,14 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
"complete_objects_one_skirt",
"duplicate_distance", "extruder_clearance_radius",
"skirt_extrusion_width",
"skirts", "skirt_distance", "skirt_height",
"first_layer_extrusion_width",
"perimeter_extrusion_width",
"extrusion_width",
"skirts", "skirt_distance", "skirt_height", "draft_shield",
"brim_width", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle",
"wipe_tower_brim", "extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology",
"wipe_tower_brim",
"extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
"layer_height", "first_layer_height", "min_layer_height", "max_layer_height",
"brim_width", "perimeters", "perimeter_extruder", "fill_density", "infill_extruder", "top_solid_layers",