mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 23:17:35 -06:00
Detection of curled edges to enhance slowdown for overhangs algorithm (#2056)
* Overhang perimeter handling Updated code to handle overhang perimeters as an overhang and not as a bridge. * Preparing to add curled extrusions identification * Porting curling calculations from Prusa Slier 2.6.1 * Prototype 1 - slowdown extended to detect curled edges and further reduce speed First prototype of the code submitted. * Working prototype - 2 Code is now finally working - external perimeters are slowed down as needed when there is likelyhood of curling up. ToDo: 1. Reslicing the model causes the algorithm not to run - need to find where this fails to trigger the call for this. 2. Slowdown of internal perimeters not working yet. * Updated to use overhang wall speed instead of bridging speed for this algorithm * Fixed bug in speed calculation and tweaked parameters for high speed printer Fixed bug in speed calculation and tweaked parameters for high speed printer * Attempting to fix "set started" not being set * Parameter tweak after print tests * Fixed estimation not running when model is re-sliced. * Removing debug printf statements and fixed threading flag. * Fixed threading * Parameter tweaks following print tests * Made this as an option in the GUI * Reintroduced handling of bridges as per original design * UI line toggling when option makes sense to be visible. * Fixed bug in field visibility & made it default to off * Code optimisation --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
bcedb431ab
commit
61437b2c76
16 changed files with 322 additions and 143 deletions
|
@ -234,6 +234,7 @@ namespace AABBTreeLines {
|
||||||
return found_lines;
|
return found_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// return 1 if true, -1 if false, 0 for point on contour (or if cannot be determined)
|
// return 1 if true, -1 if false, 0 for point on contour (or if cannot be determined)
|
||||||
template <typename LineType, typename TreeType, typename VectorType>
|
template <typename LineType, typename TreeType, typename VectorType>
|
||||||
inline int point_outside_closed_contours(const std::vector<LineType>& lines, const TreeType& tree, const VectorType& point)
|
inline int point_outside_closed_contours(const std::vector<LineType>& lines, const TreeType& tree, const VectorType& point)
|
||||||
|
@ -350,9 +351,9 @@ namespace AABBTreeLines {
|
||||||
return dist;
|
return dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<size_t> all_lines_in_radius(const Vec<2, typename LineType::Scalar>& point, Floating radius)
|
std::vector<size_t> all_lines_in_radius(const Vec<2, Scalar> &point, Floating radius)
|
||||||
{
|
{
|
||||||
return all_lines_in_radius(this->lines, this->tree, point, radius * radius);
|
return AABBTreeLines::all_lines_in_radius(this->lines, this->tree, point.template cast<Floating>(), radius * radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool sorted>
|
template <bool sorted>
|
||||||
|
|
|
@ -46,6 +46,13 @@ public:
|
||||||
~ExtrusionEntityCollection() { clear(); }
|
~ExtrusionEntityCollection() { clear(); }
|
||||||
explicit operator ExtrusionPaths() const;
|
explicit operator ExtrusionPaths() const;
|
||||||
|
|
||||||
|
ExtrusionEntitiesPtr::const_iterator cbegin() const { return this->entities.cbegin(); }
|
||||||
|
ExtrusionEntitiesPtr::const_iterator cend() const { return this->entities.cend(); }
|
||||||
|
ExtrusionEntitiesPtr::const_iterator begin() const { return this->entities.cbegin(); }
|
||||||
|
ExtrusionEntitiesPtr::const_iterator end() const { return this->entities.cend(); }
|
||||||
|
ExtrusionEntitiesPtr::iterator begin() { return this->entities.begin(); }
|
||||||
|
ExtrusionEntitiesPtr::iterator end() { return this->entities.end(); }
|
||||||
|
|
||||||
bool is_collection() const override { return true; }
|
bool is_collection() const override { return true; }
|
||||||
ExtrusionRole role() const override {
|
ExtrusionRole role() const override {
|
||||||
ExtrusionRole out = erNone;
|
ExtrusionRole out = erNone;
|
||||||
|
@ -112,6 +119,7 @@ public:
|
||||||
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
|
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
|
||||||
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
|
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
|
||||||
size_t items_count() const;
|
size_t items_count() const;
|
||||||
|
size_t size() const { return entities.size(); }
|
||||||
/// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections.
|
/// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections.
|
||||||
/// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
|
/// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
|
||||||
/// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False).
|
/// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False).
|
||||||
|
|
|
@ -4530,8 +4530,40 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
|
|
||||||
if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic && !this->on_first_layer() &&
|
if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic && !this->on_first_layer() &&
|
||||||
(is_bridge(path.role()) || is_perimeter(path.role()))) {
|
(is_bridge(path.role()) || is_perimeter(path.role()))) {
|
||||||
|
|
||||||
double out_wall_ref_speed = m_config.get_abs_value("outer_wall_speed");
|
double out_wall_ref_speed = m_config.get_abs_value("outer_wall_speed");
|
||||||
ConfigOptionPercents overhang_overlap_levels({75, 50, 25, 13, 12.99, 0});
|
ConfigOptionPercents overhang_overlap_levels({75, 50, 25, 13, 12.99, 0});
|
||||||
|
|
||||||
|
if (m_config.slowdown_for_curled_perimeters){
|
||||||
|
ConfigOptionFloatsOrPercents dynamic_overhang_speeds(
|
||||||
|
{(m_config.get_abs_value("overhang_1_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_1_4_speed") * 100 / out_wall_ref_speed, true},
|
||||||
|
(m_config.get_abs_value("overhang_2_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_2_4_speed") * 100 / out_wall_ref_speed, true},
|
||||||
|
(m_config.get_abs_value("overhang_3_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_3_4_speed") * 100 / out_wall_ref_speed, true},
|
||||||
|
(m_config.get_abs_value("overhang_4_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed") * 100 / out_wall_ref_speed, true},
|
||||||
|
(m_config.get_abs_value("overhang_4_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed") * 100 / out_wall_ref_speed, true},
|
||||||
|
(m_config.get_abs_value("overhang_4_4_speed") < 0.5) ?
|
||||||
|
FloatOrPercent{100, true} :
|
||||||
|
FloatOrPercent{m_config.get_abs_value("overhang_4_4_speed") * 100 / out_wall_ref_speed, true}});
|
||||||
|
if (out_wall_ref_speed == 0)
|
||||||
|
out_wall_ref_speed = EXTRUDER_CONFIG(filament_max_volumetric_speed) / _mm3_per_mm;
|
||||||
|
|
||||||
|
if (EXTRUDER_CONFIG(filament_max_volumetric_speed) > 0) {
|
||||||
|
out_wall_ref_speed = std::min(out_wall_ref_speed, EXTRUDER_CONFIG(filament_max_volumetric_speed) / path.mm3_per_mm);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhang_overlap_levels, dynamic_overhang_speeds,
|
||||||
|
out_wall_ref_speed, speed, m_config.slowdown_for_curled_perimeters);
|
||||||
|
}else{
|
||||||
ConfigOptionFloatsOrPercents dynamic_overhang_speeds(
|
ConfigOptionFloatsOrPercents dynamic_overhang_speeds(
|
||||||
{(m_config.get_abs_value("overhang_1_4_speed") < 0.5) ?
|
{(m_config.get_abs_value("overhang_1_4_speed") < 0.5) ?
|
||||||
FloatOrPercent{100, true} :
|
FloatOrPercent{100, true} :
|
||||||
|
@ -4556,9 +4588,10 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhang_overlap_levels, dynamic_overhang_speeds,
|
new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, overhang_overlap_levels, dynamic_overhang_speeds,
|
||||||
out_wall_ref_speed, speed);
|
out_wall_ref_speed, speed, m_config.slowdown_for_curled_perimeters);
|
||||||
|
}
|
||||||
variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; });
|
variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double F = speed * 60; // convert mm/sec to mm/min
|
double F = speed * 60; // convert mm/sec to mm/min
|
||||||
|
|
|
@ -247,6 +247,8 @@ class ExtrusionQualityEstimator
|
||||||
{
|
{
|
||||||
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
|
||||||
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
|
||||||
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> prev_curled_extrusions;
|
||||||
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<CurledLine>> next_curled_extrusions;
|
||||||
const PrintObject *current_object;
|
const PrintObject *current_object;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -258,16 +260,22 @@ public:
|
||||||
const PrintObject *object = obj;
|
const PrintObject *object = obj;
|
||||||
prev_layer_boundaries[object] = next_layer_boundaries[object];
|
prev_layer_boundaries[object] = next_layer_boundaries[object];
|
||||||
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
|
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
|
||||||
|
prev_curled_extrusions[object] = next_curled_extrusions[object];
|
||||||
|
next_curled_extrusions[object] = AABBTreeLines::LinesDistancer<CurledLine>{layer->curled_lines};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ProcessedPoint> estimate_extrusion_quality(const ExtrusionPath &path,
|
std::vector<ProcessedPoint> estimate_extrusion_quality(const ExtrusionPath &path,
|
||||||
const ConfigOptionPercents &overlaps,
|
const ConfigOptionPercents &overlaps,
|
||||||
const ConfigOptionFloatsOrPercents &speeds,
|
const ConfigOptionFloatsOrPercents &speeds,
|
||||||
float ext_perimeter_speed,
|
float ext_perimeter_speed,
|
||||||
float original_speed)
|
float original_speed,
|
||||||
|
bool slowdown_for_curled_edges)
|
||||||
{
|
{
|
||||||
size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size());
|
size_t speed_sections_count = std::min(overlaps.values.size(), speeds.values.size());
|
||||||
std::vector<std::pair<float, float>> speed_sections;
|
std::vector<std::pair<float, float>> speed_sections;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < speed_sections_count; i++) {
|
for (size_t i = 0; i < speed_sections_count; i++) {
|
||||||
float distance = path.width * (1.0 - (overlaps.get_at(i) / 100.0));
|
float distance = path.width * (1.0 - (overlaps.get_at(i) / 100.0));
|
||||||
float speed = speeds.get_at(i).percent ? (ext_perimeter_speed * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value;
|
float speed = speeds.get_at(i).percent ? (ext_perimeter_speed * speeds.get_at(i).value / 100.0) : speeds.get_at(i).value;
|
||||||
|
@ -298,6 +306,56 @@ public:
|
||||||
const ExtendedPoint &curr = extended_points[i];
|
const ExtendedPoint &curr = extended_points[i];
|
||||||
const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
|
const ExtendedPoint &next = extended_points[i + 1 < extended_points.size() ? i + 1 : i];
|
||||||
|
|
||||||
|
float artificial_distance_to_curled_lines = 0.0;
|
||||||
|
if(slowdown_for_curled_edges) {
|
||||||
|
// The following code artifically increases the distance to provide slowdown for extrusions that are over curled lines
|
||||||
|
const double dist_limit = 10.0 * path.width;
|
||||||
|
{
|
||||||
|
Vec2d middle = 0.5 * (curr.position + next.position);
|
||||||
|
auto line_indices = prev_curled_extrusions[current_object].all_lines_in_radius(Point::new_scale(middle), scale_(dist_limit));
|
||||||
|
if (!line_indices.empty()) {
|
||||||
|
double len = (next.position - curr.position).norm();
|
||||||
|
// For long lines, there is a problem with the additional slowdown. If by accident, there is small curled line near the middle of this long line
|
||||||
|
// The whole segment gets slower unnecesarily. For these long lines, we do additional check whether it is worth slowing down.
|
||||||
|
// NOTE that this is still quite rough approximation, e.g. we are still checking lines only near the middle point
|
||||||
|
// TODO maybe split the lines into smaller segments before running this alg? but can be demanding, and GCode will be huge
|
||||||
|
if (len > 8) {
|
||||||
|
Vec2d dir = Vec2d(next.position - curr.position) / len;
|
||||||
|
Vec2d right = Vec2d(-dir.y(), dir.x());
|
||||||
|
|
||||||
|
Polygon box_of_influence = {
|
||||||
|
scaled(Vec2d(curr.position + right * dist_limit)),
|
||||||
|
scaled(Vec2d(next.position + right * dist_limit)),
|
||||||
|
scaled(Vec2d(next.position - right * dist_limit)),
|
||||||
|
scaled(Vec2d(curr.position - right * dist_limit)),
|
||||||
|
};
|
||||||
|
|
||||||
|
double projected_lengths_sum = 0;
|
||||||
|
for (size_t idx : line_indices) {
|
||||||
|
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
|
||||||
|
Lines inside = intersection_ln({{line.a, line.b}}, {box_of_influence});
|
||||||
|
if (inside.empty())
|
||||||
|
continue;
|
||||||
|
double projected_length = abs(dir.dot(unscaled(Vec2d((inside.back().b - inside.back().a).cast<double>()))));
|
||||||
|
projected_lengths_sum += projected_length;
|
||||||
|
}
|
||||||
|
if (projected_lengths_sum < 0.4 * len) {
|
||||||
|
line_indices.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t idx : line_indices) {
|
||||||
|
const CurledLine &line = prev_curled_extrusions[current_object].get_line(idx);
|
||||||
|
float distance_from_curled = unscaled(line_alg::distance_to(line, Point::new_scale(middle)));
|
||||||
|
float dist = path.width * (1.0 - (distance_from_curled / dist_limit)) *
|
||||||
|
(1.0 - (distance_from_curled / dist_limit)) *
|
||||||
|
(line.curled_height / (path.height * 10.0f)); // max_curled_height_factor from SupportSpotGenerator
|
||||||
|
artificial_distance_to_curled_lines = std::max(artificial_distance_to_curled_lines, dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto calculate_speed = [&speed_sections, &original_speed](float distance) {
|
auto calculate_speed = [&speed_sections, &original_speed](float distance) {
|
||||||
float final_speed;
|
float final_speed;
|
||||||
if (distance <= speed_sections.front().first) {
|
if (distance <= speed_sections.front().first) {
|
||||||
|
@ -318,6 +376,11 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
||||||
|
if(slowdown_for_curled_edges) {
|
||||||
|
float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
|
||||||
|
extrusion_speed = std::min(curled_speed, extrusion_speed); // adjust extrusion speed based on what is smallest - the calculated overhang speed or the artificial curled speed
|
||||||
|
}
|
||||||
|
|
||||||
float overlap = std::min(1 - curr.distance * width_inv, 1 - next.distance * width_inv);
|
float overlap = std::min(1 - curr.distance * width_inv, 1 - next.distance * width_inv);
|
||||||
|
|
||||||
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
|
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
|
||||||
|
|
|
@ -132,6 +132,9 @@ public:
|
||||||
coordf_t height; // layer height in unscaled coordinates
|
coordf_t height; // layer height in unscaled coordinates
|
||||||
coordf_t bottom_z() const { return this->print_z - this->height; }
|
coordf_t bottom_z() const { return this->print_z - this->height; }
|
||||||
|
|
||||||
|
//Extrusions estimated to be seriously malformed, estimated during "Estimating curled extrusions" step. These lines should be avoided during fast travels.
|
||||||
|
CurledLines curled_lines;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
mutable ExPolygons sharp_tails;
|
mutable ExPolygons sharp_tails;
|
||||||
mutable ExPolygons cantilevers;
|
mutable ExPolygons cantilevers;
|
||||||
|
|
|
@ -209,6 +209,18 @@ public:
|
||||||
double a_width, b_width;
|
double a_width, b_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CurledLine : public Line
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CurledLine() : curled_height(0.0f) {}
|
||||||
|
CurledLine(const Point& a, const Point& b) : Line(a, b), curled_height(0.0f) {}
|
||||||
|
CurledLine(const Point& a, const Point& b, float curled_height) : Line(a, b), curled_height(curled_height) {}
|
||||||
|
|
||||||
|
float curled_height;
|
||||||
|
};
|
||||||
|
|
||||||
|
using CurledLines = std::vector<CurledLine>;
|
||||||
|
|
||||||
class Line3
|
class Line3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -752,7 +752,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||||
"tree_support_branch_diameter", "tree_support_branch_diameter_angle", "tree_support_branch_diameter_double_wall",
|
"tree_support_branch_diameter", "tree_support_branch_diameter_angle", "tree_support_branch_diameter_double_wall",
|
||||||
"detect_narrow_internal_solid_infill",
|
"detect_narrow_internal_solid_infill",
|
||||||
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/
|
"gcode_add_line_number", "enable_arc_fitting", "infill_combination", /*"adaptive_layer_height",*/
|
||||||
"support_bottom_interface_spacing", "enable_overhang_speed", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
|
"support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed",
|
||||||
"initial_layer_infill_speed", "only_one_wall_top",
|
"initial_layer_infill_speed", "only_one_wall_top",
|
||||||
"timelapse_type", "internal_bridge_support_thickness",
|
"timelapse_type", "internal_bridge_support_thickness",
|
||||||
"wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
"wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
|
||||||
|
|
|
@ -282,6 +282,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||||
|| opt_key == "enable_arc_fitting"
|
|| opt_key == "enable_arc_fitting"
|
||||||
|| opt_key == "wall_infill_order") {
|
|| opt_key == "wall_infill_order") {
|
||||||
osteps.emplace_back(posPerimeters);
|
osteps.emplace_back(posPerimeters);
|
||||||
|
osteps.emplace_back(posEstimateCurledExtrusions);
|
||||||
osteps.emplace_back(posInfill);
|
osteps.emplace_back(posInfill);
|
||||||
osteps.emplace_back(posSupportMaterial);
|
osteps.emplace_back(posSupportMaterial);
|
||||||
osteps.emplace_back(posSimplifyPath);
|
osteps.emplace_back(posSimplifyPath);
|
||||||
|
@ -1666,6 +1667,15 @@ void Print::process(bool use_cache)
|
||||||
obj->set_done(posPerimeters);
|
obj->set_done(posPerimeters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (PrintObject *obj : m_objects) {
|
||||||
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
|
obj->estimate_curled_extrusions();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (obj->set_started(posEstimateCurledExtrusions))
|
||||||
|
obj->set_done(posEstimateCurledExtrusions);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (PrintObject *obj : m_objects) {
|
for (PrintObject *obj : m_objects) {
|
||||||
if (need_slicing_objects.count(obj) != 0) {
|
if (need_slicing_objects.count(obj) != 0) {
|
||||||
obj->infill();
|
obj->infill();
|
||||||
|
@ -1723,6 +1733,7 @@ void Print::process(bool use_cache)
|
||||||
obj->infill();
|
obj->infill();
|
||||||
obj->ironing();
|
obj->ironing();
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
|
obj->estimate_curled_extrusions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ enum PrintStep {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PrintObjectStep {
|
enum PrintObjectStep {
|
||||||
posSlice, posPerimeters, posPrepareInfill,
|
posSlice, posPerimeters,posEstimateCurledExtrusions, posPrepareInfill,
|
||||||
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
|
posInfill, posIroning, posSupportMaterial, posSimplifyPath, posSimplifySupportPath,
|
||||||
// BBS
|
// BBS
|
||||||
posSimplifyInfill,
|
posSimplifyInfill,
|
||||||
|
@ -468,6 +468,7 @@ private:
|
||||||
void infill();
|
void infill();
|
||||||
void ironing();
|
void ironing();
|
||||||
void generate_support_material();
|
void generate_support_material();
|
||||||
|
void estimate_curled_extrusions();
|
||||||
void simplify_extrusion_path();
|
void simplify_extrusion_path();
|
||||||
|
|
||||||
void slice_volumes();
|
void slice_volumes();
|
||||||
|
|
|
@ -801,6 +801,13 @@ void PrintConfigDef::init_fff_params()
|
||||||
def->mode = comAdvanced;
|
def->mode = comAdvanced;
|
||||||
def->set_default_value(new ConfigOptionBool{ true });
|
def->set_default_value(new ConfigOptionBool{ true });
|
||||||
|
|
||||||
|
def = this->add("slowdown_for_curled_perimeters", coBool);
|
||||||
|
def->label = L("Slow down for curled perimeters");
|
||||||
|
def->category = L("Speed");
|
||||||
|
def->tooltip = L("Enable this option to slow printing down in areas where potential curled perimeters may exist");
|
||||||
|
def->mode = comAdvanced;
|
||||||
|
def->set_default_value(new ConfigOptionBool{ false });
|
||||||
|
|
||||||
def = this->add("overhang_1_4_speed", coFloatOrPercent);
|
def = this->add("overhang_1_4_speed", coFloatOrPercent);
|
||||||
def->label = "(10%, 25%)";
|
def->label = "(10%, 25%)";
|
||||||
def->category = L("Speed");
|
def->category = L("Speed");
|
||||||
|
|
|
@ -816,6 +816,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||||
// Orca
|
// Orca
|
||||||
((ConfigOptionBool, make_overhang_printable))
|
((ConfigOptionBool, make_overhang_printable))
|
||||||
((ConfigOptionBool, extra_perimeters_on_overhangs))
|
((ConfigOptionBool, extra_perimeters_on_overhangs))
|
||||||
|
((ConfigOptionBool, slowdown_for_curled_perimeters))
|
||||||
)
|
)
|
||||||
|
|
||||||
PRINT_CONFIG_CLASS_DEFINE(
|
PRINT_CONFIG_CLASS_DEFINE(
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "MutablePolygon.hpp"
|
#include "MutablePolygon.hpp"
|
||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
#include "SupportMaterial.hpp"
|
#include "SupportMaterial.hpp"
|
||||||
|
#include "SupportSpotsGenerator.hpp"
|
||||||
#include "Support/TreeSupport.hpp"
|
#include "Support/TreeSupport.hpp"
|
||||||
#include "Surface.hpp"
|
#include "Surface.hpp"
|
||||||
#include "Slicing.hpp"
|
#include "Slicing.hpp"
|
||||||
|
@ -499,6 +500,25 @@ void PrintObject::generate_support_material()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintObject::estimate_curled_extrusions()
|
||||||
|
{
|
||||||
|
if (this->set_started(posEstimateCurledExtrusions)) {
|
||||||
|
if ( std::any_of(this->print()->m_print_regions.begin(), this->print()->m_print_regions.end(),
|
||||||
|
[](const PrintRegion *region) { return region->config().enable_overhang_speed.getBool(); })) {
|
||||||
|
|
||||||
|
// Estimate curling of support material and add it to the malformaition lines of each layer
|
||||||
|
float support_flow_width = support_material_flow(this, this->config().layer_height).width();
|
||||||
|
SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values,
|
||||||
|
float(this->print()->m_config.inner_wall_acceleration.getFloat()),
|
||||||
|
this->config().raft_layers.getInt(), this->config().brim_type.value,
|
||||||
|
float(this->config().brim_width.getFloat())};
|
||||||
|
SupportSpotsGenerator::estimate_malformations(this->layers(), params);
|
||||||
|
m_print->throw_if_canceled();
|
||||||
|
}
|
||||||
|
//this->set_done(posEstimateCurledExtrusions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PrintObject::simplify_extrusion_path()
|
void PrintObject::simplify_extrusion_path()
|
||||||
{
|
{
|
||||||
if (this->set_started(posSimplifyPath)) {
|
if (this->set_started(posSimplifyPath)) {
|
||||||
|
@ -756,6 +776,7 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||||
|| opt_key == "raft_contact_distance"
|
|| opt_key == "raft_contact_distance"
|
||||||
|| opt_key == "slice_closing_radius"
|
|| opt_key == "slice_closing_radius"
|
||||||
|| opt_key == "slicing_mode"
|
|| opt_key == "slicing_mode"
|
||||||
|
|| opt_key == "slowdown_for_curled_perimeters"
|
||||||
|| opt_key == "make_overhang_printable"
|
|| opt_key == "make_overhang_printable"
|
||||||
|| opt_key == "make_overhang_printable_angle"
|
|| opt_key == "make_overhang_printable_angle"
|
||||||
|| opt_key == "make_overhang_printable_hole_size") {
|
|| opt_key == "make_overhang_printable_hole_size") {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "SupportSpotsGenerator.hpp"
|
#include "SupportSpotsGenerator.hpp"
|
||||||
/*
|
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
#include "ExPolygon.hpp"
|
#include "ExPolygon.hpp"
|
||||||
#include "ExtrusionEntity.hpp"
|
#include "ExtrusionEntity.hpp"
|
||||||
|
@ -45,6 +45,7 @@
|
||||||
#include "libslic3r/Color.hpp"
|
#include "libslic3r/Color.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
class ExtrusionLine
|
class ExtrusionLine
|
||||||
|
@ -85,6 +86,113 @@ namespace SupportSpotsGenerator {
|
||||||
|
|
||||||
using LD = AABBTreeLines::LinesDistancer<ExtrusionLine>;
|
using LD = AABBTreeLines::LinesDistancer<ExtrusionLine>;
|
||||||
|
|
||||||
|
float get_flow_width(const LayerRegion *region, ExtrusionRole role)
|
||||||
|
{
|
||||||
|
if (role == ExtrusionRole::erBridgeInfill) return region->flow(FlowRole::frExternalPerimeter).width();
|
||||||
|
if (role == ExtrusionRole::erExternalPerimeter) return region->flow(FlowRole::frExternalPerimeter).width();
|
||||||
|
if (role == ExtrusionRole::erGapFill) return region->flow(FlowRole::frInfill).width();
|
||||||
|
if (role == ExtrusionRole::erPerimeter) return region->flow(FlowRole::frPerimeter).width();
|
||||||
|
if (role == ExtrusionRole::erSolidInfill) return region->flow(FlowRole::frSolidInfill).width();
|
||||||
|
if (role == ExtrusionRole::erInternalInfill) return region->flow(FlowRole::frInfill).width();
|
||||||
|
if (role == ExtrusionRole::erTopSolidInfill) return region->flow(FlowRole::frTopSolidInfill).width();
|
||||||
|
// default
|
||||||
|
return region->flow(FlowRole::frPerimeter).width();
|
||||||
|
}
|
||||||
|
|
||||||
|
float estimate_curled_up_height(
|
||||||
|
float distance, float curvature, float layer_height, float flow_width, float prev_line_curled_height, Params params)
|
||||||
|
{
|
||||||
|
float curled_up_height = 0;
|
||||||
|
if (fabs(distance) < 3.0 * flow_width) {
|
||||||
|
curled_up_height = std::max(prev_line_curled_height - layer_height * 0.75f, 0.0f);
|
||||||
|
//printf("If 1 %d\n",curled_up_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("distance %f, params.malformation_distance_factors.first %f, params.malformation_distance_factors.second %f, flow_width %f\n", distance, params.malformation_distance_factors.first, params.malformation_distance_factors.second, flow_width);
|
||||||
|
//printf("distance %f,params.malformation_distance_factors.first * flow_width %f, params.malformation_distance_factors.second * flow_width %f\n", distance, params.malformation_distance_factors.first * flow_width, params.malformation_distance_factors.second * flow_width);
|
||||||
|
|
||||||
|
if (distance > params.malformation_distance_factors.first * flow_width &&
|
||||||
|
distance < params.malformation_distance_factors.second * flow_width) {
|
||||||
|
|
||||||
|
// imagine the extrusion profile. The part that has been glued (melted) with the previous layer will be called anchored section
|
||||||
|
// and the rest will be called curling section
|
||||||
|
// float anchored_section = flow_width - point.distance;
|
||||||
|
float curling_section = distance;
|
||||||
|
|
||||||
|
// after extruding, the curling (floating) part of the extrusion starts to shrink back to the rounded shape of the nozzle
|
||||||
|
// The anchored part not, because the melted material holds to the previous layer well.
|
||||||
|
// We can assume for simplicity perfect equalization of layer height and raising part width, from which:
|
||||||
|
float swelling_radius = (layer_height + curling_section) / 2.0f;
|
||||||
|
curled_up_height += std::max(0.f, (swelling_radius - layer_height) / 2.0f);
|
||||||
|
|
||||||
|
// On convex turns, there is larger tension on the floating edge of the extrusion then on the middle section.
|
||||||
|
// The tension is caused by the shrinking tendency of the filament, and on outer edge of convex trun, the expansion is greater and
|
||||||
|
// thus shrinking force is greater. This tension will cause the curling section to curle up
|
||||||
|
if (curvature > 0.01) {
|
||||||
|
float radius = (1.0 / curvature);
|
||||||
|
float curling_t = sqrt(radius / 100);
|
||||||
|
float b = curling_t * flow_width;
|
||||||
|
float a = curling_section;
|
||||||
|
float c = sqrt(std::max(0.0f, a * a - b * b));
|
||||||
|
|
||||||
|
curled_up_height += c;
|
||||||
|
}
|
||||||
|
curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return curled_up_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
||||||
|
{
|
||||||
|
LD prev_layer_lines{};
|
||||||
|
for (Layer *l : layers) {
|
||||||
|
l->curled_lines.clear();
|
||||||
|
std::vector<Linef> boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector<Linef>();
|
||||||
|
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
||||||
|
std::vector<ExtrusionLine> current_layer_lines;
|
||||||
|
for (const LayerRegion *layer_region : l->regions()) {
|
||||||
|
for (const ExtrusionEntity *extrusion : layer_region->perimeters.flatten().entities) {
|
||||||
|
if (extrusion->role() != Slic3r::erExternalPerimeter)
|
||||||
|
continue;
|
||||||
|
Points extrusion_pts;
|
||||||
|
extrusion->collect_points(extrusion_pts);
|
||||||
|
float flow_width = get_flow_width(layer_region, extrusion->role());
|
||||||
|
auto annotated_points = estimate_points_properties<true, true, false, false>(extrusion_pts, prev_layer_lines, flow_width,
|
||||||
|
params.bridge_distance);
|
||||||
|
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
||||||
|
const ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
|
||||||
|
const ExtendedPoint &b = annotated_points[i];
|
||||||
|
ExtrusionLine line_out{a.position.cast<float>(), b.position.cast<float>(), float((a.position - b.position).norm()),
|
||||||
|
extrusion};
|
||||||
|
Vec2f middle = 0.5 * (line_out.a + line_out.b);
|
||||||
|
auto [middle_distance, bottom_line_idx, x] = prev_layer_lines.distance_from_lines_extra<false>(middle);
|
||||||
|
ExtrusionLine bottom_line = prev_layer_lines.get_lines().empty() ? ExtrusionLine{} :
|
||||||
|
prev_layer_lines.get_line(bottom_line_idx);
|
||||||
|
|
||||||
|
// correctify the distance sign using slice polygons
|
||||||
|
float sign = (prev_layer_boundary.distance_from_lines<true>(middle.cast<double>()) + 0.5f * flow_width) < 0.0f ? -1.0f : 1.0f;
|
||||||
|
|
||||||
|
line_out.curled_up_height = estimate_curled_up_height(middle_distance * sign, 0.5 * (a.curvature + b.curvature),
|
||||||
|
l->height, flow_width, bottom_line.curled_up_height, params);
|
||||||
|
|
||||||
|
current_layer_lines.push_back(line_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
|
if (line.curled_up_height > params.curling_tolerance_limit) {
|
||||||
|
l->curled_lines.push_back(CurledLine{Point::new_scale(line.a), Point::new_scale(line.b), line.curled_up_height});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_layer_lines = LD{current_layer_lines};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
struct SupportGridFilter
|
struct SupportGridFilter
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -169,18 +277,7 @@ struct SliceConnection
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
float get_flow_width(const LayerRegion *region, ExtrusionRole role)
|
|
||||||
{
|
|
||||||
if (role == ExtrusionRole::erBridgeInfill) return region->flow(FlowRole::frExternalPerimeter).width();
|
|
||||||
if (role == ExtrusionRole::erExternalPerimeter) return region->flow(FlowRole::frExternalPerimeter).width();
|
|
||||||
if (role == ExtrusionRole::erGapFill) return region->flow(FlowRole::frInfill).width();
|
|
||||||
if (role == ExtrusionRole::erPerimeter) return region->flow(FlowRole::frPerimeter).width();
|
|
||||||
if (role == ExtrusionRole::erSolidInfill) return region->flow(FlowRole::frSolidInfill).width();
|
|
||||||
if (role == ExtrusionRole::erInternalInfill) return region->flow(FlowRole::frInfill).width();
|
|
||||||
if (role == ExtrusionRole::erTopSolidInfill) return region->flow(FlowRole::frTopSolidInfill).width();
|
|
||||||
// default
|
|
||||||
return region->flow(FlowRole::frPerimeter).width();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit)
|
std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit)
|
||||||
{
|
{
|
||||||
|
@ -205,24 +302,7 @@ std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
float estimate_curled_up_height(
|
|
||||||
const ExtendedPoint &point, float layer_height, float flow_width, float prev_line_curled_height, Params params)
|
|
||||||
{
|
|
||||||
float curled_up_height = 0.0f;
|
|
||||||
if (fabs(point.distance) < 1.5 * flow_width) {
|
|
||||||
curled_up_height = 0.85 * prev_line_curled_height;
|
|
||||||
}
|
|
||||||
if (point.distance > params.malformation_distance_factors.first * flow_width &&
|
|
||||||
point.distance < params.malformation_distance_factors.second * flow_width && point.curvature > -0.1f) {
|
|
||||||
float dist_factor = std::max(point.distance - params.malformation_distance_factors.first * flow_width, 0.01f) /
|
|
||||||
((params.malformation_distance_factors.second - params.malformation_distance_factors.first) * flow_width);
|
|
||||||
|
|
||||||
curled_up_height = layer_height * sqrt(sqrt(dist_factor)) * std::clamp(3.0f * point.curvature, 1.0f, 3.0f);
|
|
||||||
curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
return curled_up_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
||||||
const LayerRegion *layer_region,
|
const LayerRegion *layer_region,
|
||||||
|
@ -1104,78 +1184,7 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG_FILES
|
|
||||||
FILE *debug_file = boost::nowide::fopen(debug_out_path("object_malformations.obj").c_str(), "w");
|
|
||||||
FILE *full_file = boost::nowide::fopen(debug_out_path("object_full.obj").c_str(), "w");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LD prev_layer_lines{};
|
|
||||||
|
|
||||||
for (Layer *l : layers) {
|
|
||||||
std::vector<Linef> boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector<Linef>();
|
|
||||||
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
|
||||||
std::vector<ExtrusionLine> current_layer_lines;
|
|
||||||
for (const LayerRegion *layer_region : l->regions()) {
|
|
||||||
for (const ExtrusionEntity *extrusion : layer_region->perimeters().flatten().entities) {
|
|
||||||
|
|
||||||
if (!extrusion->role().is_external_perimeter()) continue;
|
|
||||||
|
|
||||||
Points extrusion_pts;
|
|
||||||
extrusion->collect_points(extrusion_pts);
|
|
||||||
float flow_width = get_flow_width(layer_region, extrusion->role());
|
|
||||||
auto annotated_points = estimate_points_properties<true, false, false, false>(extrusion_pts, prev_layer_lines, flow_width,
|
|
||||||
params.bridge_distance);
|
|
||||||
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
|
||||||
ExtendedPoint &curr_point = annotated_points[i];
|
|
||||||
float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
|
|
||||||
ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
|
|
||||||
curr_point.position.cast<float>(), line_len, extrusion};
|
|
||||||
|
|
||||||
const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
|
|
||||||
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
|
|
||||||
ExtrusionLine{};
|
|
||||||
|
|
||||||
float sign = (prev_layer_boundary.distance_from_lines<true>(curr_point.position) + 0.5f * flow_width) < 0.0f ? -1.0f :
|
|
||||||
1.0f;
|
|
||||||
curr_point.distance *= sign;
|
|
||||||
|
|
||||||
line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width,
|
|
||||||
nearest_prev_layer_line.curled_up_height, params);
|
|
||||||
|
|
||||||
current_layer_lines.push_back(line_out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ExtrusionLine &line : current_layer_lines) {
|
|
||||||
if (line.curled_up_height > 0.3f) {
|
|
||||||
l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
|
||||||
for (const ExtrusionLine &line : current_layer_lines) {
|
|
||||||
if (line.curled_up_height > 0.3f) {
|
|
||||||
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height);
|
|
||||||
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const ExtrusionLine &line : current_layer_lines) {
|
|
||||||
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height);
|
|
||||||
fprintf(full_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prev_layer_lines = LD{current_layer_lines};
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
|
||||||
fclose(debug_file);
|
|
||||||
fclose(full_file);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<SupportPointCause, bool>> gather_issues(const SupportPoints &support_points, PartialObjects &partial_objects)
|
std::vector<std::pair<SupportPointCause, bool>> gather_issues(const SupportPoints &support_points, PartialObjects &partial_objects)
|
||||||
{
|
{
|
||||||
|
@ -1262,6 +1271,7 @@ std::vector<std::pair<SupportPointCause, bool>> gather_issues(const SupportPoint
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
} // namespace SupportSpotsGenerator
|
} // namespace SupportSpotsGenerator
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
*/
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
#ifndef SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
#define SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_
|
||||||
/*
|
|
||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
#include "Line.hpp"
|
#include "Line.hpp"
|
||||||
#include "PrintBase.hpp"
|
#include "PrintBase.hpp"
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
namespace SupportSpotsGenerator {
|
namespace SupportSpotsGenerator {
|
||||||
|
@ -42,8 +43,9 @@ struct Params
|
||||||
BrimType brim_type;
|
BrimType brim_type;
|
||||||
const float brim_width;
|
const float brim_width;
|
||||||
|
|
||||||
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.5, 1.1 };
|
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.33, 0.7 };
|
||||||
const float max_curled_height_factor = 10.0f;
|
const float max_curled_height_factor = 10.0f;
|
||||||
|
const float curling_tolerance_limit = 0.1f;
|
||||||
|
|
||||||
const float min_distance_between_support_points = 3.0f; //mm
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
const float support_points_interface_radius = 1.5f; // mm
|
const float support_points_interface_radius = 1.5f; // mm
|
||||||
|
@ -77,6 +79,9 @@ struct Params
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void estimate_malformations(std::vector<Layer *> &layers, const Params ¶ms);
|
||||||
|
|
||||||
|
|
||||||
enum class SupportPointCause {
|
enum class SupportPointCause {
|
||||||
LongBridge, // point generated on bridge and straight perimeter extrusion longer than the allowed length
|
LongBridge, // point generated on bridge and straight perimeter extrusion longer than the allowed length
|
||||||
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
FloatingBridgeAnchor, // point generated on unsupported bridge endpoint
|
||||||
|
@ -97,7 +102,7 @@ enum class SupportPointCause {
|
||||||
// between forces that destabilize the object (extruder conflicts with curled filament, weight if instable center of mass, bed movements etc)
|
// between forces that destabilize the object (extruder conflicts with curled filament, weight if instable center of mass, bed movements etc)
|
||||||
// and forces that stabilize the object (bed adhesion, other support spots adhesion, weight if stable center of mass).
|
// and forces that stabilize the object (bed adhesion, other support spots adhesion, weight if stable center of mass).
|
||||||
// Note that the force is only the difference - the amount needed to stabilize the object again.
|
// Note that the force is only the difference - the amount needed to stabilize the object again.
|
||||||
struct SupportPoint
|
/*struct SupportPoint
|
||||||
{
|
{
|
||||||
SupportPoint(SupportPointCause cause, const Vec3f &position, float force, float spot_radius, const Vec2f &direction)
|
SupportPoint(SupportPointCause cause, const Vec3f &position, float force, float spot_radius, const Vec2f &direction)
|
||||||
: cause(cause), position(position), force(force), spot_radius(spot_radius), direction(direction)
|
: cause(cause), position(position), force(force), spot_radius(spot_radius), direction(direction)
|
||||||
|
@ -147,13 +152,12 @@ using PartialObjects = std::vector<PartialObject>;
|
||||||
std::tuple<SupportPoints, PartialObjects> full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms);
|
std::tuple<SupportPoints, PartialObjects> full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms);
|
||||||
|
|
||||||
void estimate_supports_malformations(std::vector<SupportLayer *> &layers, float supports_flow_width, const Params ¶ms);
|
void estimate_supports_malformations(std::vector<SupportLayer *> &layers, float supports_flow_width, const Params ¶ms);
|
||||||
void estimate_malformations(std::vector<Layer *> &layers, const Params ¶ms);
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: the boolean marks if the issue is critical or not for now.
|
// NOTE: the boolean marks if the issue is critical or not for now.
|
||||||
std::vector<std::pair<SupportPointCause, bool>> gather_issues(const SupportPoints &support_points,
|
std::vector<std::pair<SupportPointCause, bool>> gather_issues(const SupportPoints &support_points,
|
||||||
PartialObjects &partial_objects);
|
PartialObjects &partial_objects);
|
||||||
|
|
||||||
}} // namespace Slic3r::SupportSpotsGenerator
|
|
||||||
*/
|
*/
|
||||||
|
}} // namespace Slic3r::SupportSpotsGenerator
|
||||||
|
|
||||||
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */
|
#endif /* SRC_LIBSLIC3R_SUPPORTABLEISSUESSEARCH_HPP_ */
|
||||||
|
|
|
@ -678,6 +678,9 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||||
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
|
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
|
||||||
toggle_line(el, has_overhang_speed);
|
toggle_line(el, has_overhang_speed);
|
||||||
|
|
||||||
|
bool has_overhang_speed_classic = config->opt_bool("overhang_speed_classic");
|
||||||
|
toggle_line("slowdown_for_curled_perimeters",!has_overhang_speed_classic && has_overhang_speed);
|
||||||
|
|
||||||
toggle_line("flush_into_objects", !is_global_config);
|
toggle_line("flush_into_objects", !is_global_config);
|
||||||
|
|
||||||
bool has_fuzzy_skin = (config->opt_enum<FuzzySkinType>("fuzzy_skin") != FuzzySkinType::None);
|
bool has_fuzzy_skin = (config->opt_enum<FuzzySkinType>("fuzzy_skin") != FuzzySkinType::None);
|
||||||
|
|
|
@ -1957,6 +1957,7 @@ void TabPrint::build()
|
||||||
optgroup = page->new_optgroup(L("Overhang speed"), L"param_speed", 15);
|
optgroup = page->new_optgroup(L("Overhang speed"), L"param_speed", 15);
|
||||||
optgroup->append_single_option_line("enable_overhang_speed", "slow-down-for-overhang");
|
optgroup->append_single_option_line("enable_overhang_speed", "slow-down-for-overhang");
|
||||||
optgroup->append_single_option_line("overhang_speed_classic", "slow-down-for-overhang");
|
optgroup->append_single_option_line("overhang_speed_classic", "slow-down-for-overhang");
|
||||||
|
optgroup->append_single_option_line("slowdown_for_curled_perimeters");
|
||||||
Line line = { L("Overhang speed"), L("This is the speed for various overhang degrees. Overhang degrees are expressed as a percentage of line width. 0 speed means no slowing down for the overhang degree range and wall speed is used") };
|
Line line = { L("Overhang speed"), L("This is the speed for various overhang degrees. Overhang degrees are expressed as a percentage of line width. 0 speed means no slowing down for the overhang degree range and wall speed is used") };
|
||||||
line.label_path = "slow-down-for-overhang";
|
line.label_path = "slow-down-for-overhang";
|
||||||
line.append_option(optgroup->get_option("overhang_1_4_speed"));
|
line.append_option(optgroup->get_option("overhang_1_4_speed"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue