mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 00:45:54 +08:00
Fix sequential printing distance detection
* fix bug with skirt width * always takes brim into account
This commit is contained in:
parent
b4fb97e527
commit
4ed4ec0151
@ -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};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user