Remove classic overhang speed code (#9934)
Some checks failed
Build all / Build All (push) Has been cancelled
Build all / Flatpak (push) Has been cancelled
Publish docs to Wiki / Publish docs to Wiki (push) Has been cancelled

* Remove code related to classic overhang speed

* Remove `overhang_degree` and `curve_degree`
This commit is contained in:
Noisyfox 2025-06-20 23:01:09 +08:00 committed by GitHub
parent dec21efe7f
commit 7cbd0d2b74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 31 additions and 860 deletions

View file

@ -59,8 +59,6 @@ set(lisbslic3r_sources
Color.hpp
Config.cpp
Config.hpp
CurveAnalyzer.cpp
CurveAnalyzer.hpp
EdgeGrid.cpp
EdgeGrid.hpp
ElephantFootCompensation.cpp

View file

@ -1,203 +0,0 @@
#include "CurveAnalyzer.hpp"
#include <cmath>
#include <cassert>
static const int curvatures_sampling_number = 6;
static const double curvatures_densify_width = 1; // mm
static const double curvatures_sampling_width = 6; // mm
static const double curvatures_angle_best = PI/6;
static const double curvatures_angle_worst = 5*PI/6;
static const double curvatures_best = (curvatures_angle_best * 1000 / curvatures_sampling_width);
static const double curvatures_worst = (curvatures_angle_worst * 1000 / curvatures_sampling_width);
namespace Slic3r {
// This function is used to calculate curvature for paths.
// Paths must be generated from a closed polygon.
// Data in paths may be modify, and paths will be spilited and regenerated
// arrording to different curve degree.
void CurveAnalyzer::calculate_curvatures(ExtrusionPaths& paths, ECurveAnalyseMode mode)
{
Polygon polygon;
std::vector<float> paths_length(paths.size(), 0.0);
for (size_t i = 0; i < paths.size(); i++) {
if (i == 0) {
paths_length[i] = paths[i].polyline.length();
}
else {
paths_length[i] = paths_length[i - 1] + paths[i].polyline.length();
}
polygon.points.insert(polygon.points.end(), paths[i].polyline.points.begin(), paths[i].polyline.points.end() - 1);
}
// 1 generate point series which is on the line of polygon, point distance along the polygon is smaller than 1mm
polygon.densify(scale_(curvatures_densify_width));
std::vector<float> polygon_length = polygon.parameter_by_length();
// 2 calculate angle of every segment
size_t point_num = polygon.points.size();
std::vector<float> angles(point_num, 0.f);
for (size_t i = 0; i < point_num; i++) {
size_t curr = i;
size_t prev = (curr == 0) ? point_num - 1 : curr - 1;
size_t next = (curr == point_num - 1) ? 0 : curr + 1;
const Point v1 = polygon.points[curr] - polygon.points[prev];
const Point v2 = polygon.points[next] - polygon.points[curr];
int64_t dot = int64_t(v1(0)) * int64_t(v2(0)) + int64_t(v1(1)) * int64_t(v2(1));
int64_t cross = int64_t(v1(0)) * int64_t(v2(1)) - int64_t(v1(1)) * int64_t(v2(0));
if (mode == ECurveAnalyseMode::RelativeMode)
cross = abs(cross);
angles[curr] = float(atan2(double(cross), double(dot)));
}
// 3 generate sum of angle and length of the adjacent segment for eveny point, range is approximately curvatures_sampling_width.
// And then calculate the curvature
std::vector<float> sum_angles(point_num, 0.f);
std::vector<double> average_curvatures(point_num, 0.f);
if (paths_length.back() < scale_(curvatures_sampling_width)) {
// loop is too short, so the curvatures is max
double temp = 1000.0 * 2.0 * PI / ((double)(paths_length.back()) * SCALING_FACTOR);
for (size_t i = 0; i < point_num; i++) {
average_curvatures[i] = temp;
}
}
else {
for (size_t i = 0; i < point_num; i++) {
// right segment
size_t j = i;
float right_length = 0;
while (right_length < scale_(curvatures_sampling_width / 2)) {
int next_j = (j + 1 >= point_num) ? 0 : j + 1;
sum_angles[i] += angles[j];
right_length += (polygon.points[next_j] - polygon.points[j]).cast<float>().norm();
j = next_j;
}
// left segment
size_t k = i;
float left_length = 0;
while (left_length < scale_(curvatures_sampling_width / 2)) {
size_t next_k = (k < 1) ? point_num - 1 : k - 1;
sum_angles[i] += angles[k];
left_length += (polygon.points[k] - polygon.points[next_k]).cast<float>().norm();
k = next_k;
}
sum_angles[i] = sum_angles[i] - angles[i];
average_curvatures[i] = (1000.0 * (double)abs(sum_angles[i]) / (double)curvatures_sampling_width);
}
}
// 4 calculate the degree of curve
// For angle >= curvatures_angle_worst, we think it's enough to be worst. Should make the speed to be slowest.
// For angle <= curvatures_angle_best, we thins it's enough to be best. Should make the speed to be fastest.
// Use several steps [0 1 2...curvatures_sampling_number - 1] to describe the degree of curve. 0 is the flatest. curvatures_sampling_number - 1 is the sharpest
std::vector<int> curvatures_norm(point_num, 0.f);
std::vector<int> sampling_step(curvatures_sampling_number - 1, 0);
for (size_t i = 0; i < curvatures_sampling_number - 1; i++) {
sampling_step[i] = (2 * i + 1) * 50 / (curvatures_sampling_number - 1);
}
sampling_step[0] = 0;
sampling_step[curvatures_sampling_number - 2] = 100;
for (size_t i = 0; i < point_num; i++) {
curvatures_norm[i] = (int)(100 * (average_curvatures[i] - curvatures_best) / (curvatures_worst - curvatures_best));
if (curvatures_norm[i] >= 100)
curvatures_norm[i] = curvatures_sampling_number - 1;
else
for (size_t j = 0; j < curvatures_sampling_number - 1; j++) {
if (curvatures_norm[i] < sampling_step[j]) {
curvatures_norm[i] = j;
break;
}
}
}
std::vector<std::pair<std::pair<Point, int>, int>> curvature_list; // point, index, curve_degree
int last_curvature_norm = -1;
for (int i = 0; i < point_num; i++) {
if (curvatures_norm[i] != last_curvature_norm) {
last_curvature_norm = curvatures_norm[i];
curvature_list.push_back(std::pair<std::pair<Point, int>, int>(std::pair<Point, int>(polygon.points[i], i), last_curvature_norm));
}
}
curvature_list.push_back(std::pair<std::pair<Point, int>, int>(std::pair<Point, int>(polygon.points[0], point_num), curvatures_norm[0])); // the last point should be the first point
//5 split and modify the path according to the degree of curve
if (curvature_list.size() == 2) { // all paths has same curva_degree
for (size_t i = 0; i < paths.size(); i++) {
paths[i].set_curve_degree(curvature_list[0].second);
}
}
else {
ExtrusionPaths out;
out.reserve(paths.size() + curvature_list.size() - 1);
size_t j = 1;
int current_curva_norm = curvature_list[0].second;
for (size_t i = 0; i < paths.size() && j < curvature_list.size(); i++) {
if (paths[i].last_point() == curvature_list[j].first.first) {
paths[i].set_curve_degree(current_curva_norm);
out.push_back(paths[i]);
current_curva_norm = curvature_list[j].second;
j++;
continue;
}
else if (paths[i].first_point() == curvature_list[j].first.first) {
if (paths[i].polyline.points.front() == paths[i].polyline.points.back()) {
paths[i].set_curve_degree(current_curva_norm);
out.push_back(paths[i]);
current_curva_norm = curvature_list[j].second;
j++;
continue;
}
else {
// should never happen
assert(0);
}
}
if (paths_length[i] <= polygon_length[curvature_list[j].first.second] ||
paths[i].last_point() == curvature_list[j].first.first) {
// save paths[i] directly
paths[i].set_curve_degree(current_curva_norm);
out.push_back(paths[i]);
if (paths[i].last_point() == curvature_list[j].first.first) {
current_curva_norm = curvature_list[j].second;
j++;
}
}
else {
//split paths[i]
ExtrusionPath current_path = paths[i];
while (j < curvature_list.size()) {
Polyline left, right;
current_path.polyline.split_at(curvature_list[j].first.first, &left, &right);
ExtrusionPath left_path(left, current_path);
left_path.set_curve_degree(current_curva_norm);
out.push_back(left_path);
ExtrusionPath right_path(right, current_path);
current_path = right_path;
current_curva_norm = curvature_list[j].second;
j++;
if (j < curvature_list.size() &&
(paths_length[i] <= polygon_length[curvature_list[j].first.second] ||
paths[i].last_point() == curvature_list[j].first.first)) {
current_path.set_curve_degree(current_curva_norm);
out.push_back(current_path);
if (current_path.last_point() == curvature_list[j].first.first) {
current_curva_norm = curvature_list[j].second;
j++;
}
break;
}
}
}
}
paths.clear();
paths.reserve(out.size());
for (int i = 0; i < out.size(); i++) {
paths.push_back(out[i]);
}
}
}
}

View file

@ -1,27 +0,0 @@
#ifndef slic3r_CurvaAnalyzer_hpp_
#define slic3r_CurvaAnalyzer_hpp_
#include "ExtrusionEntityCollection.hpp"
namespace Slic3r {
enum class ECurveAnalyseMode : unsigned char
{
RelativeMode,
AbsoluteMode,
Count
};
//BBS: CurvaAnalyzer, ansolutely new file
class CurveAnalyzer {
public:
// This function is used to calculate curvature for paths.
// Paths must be generated from a closed polygon.
// Data in paths may be modify, and paths will be spilited and regenerated
// arrording to different curve degree.
void calculate_curvatures(ExtrusionPaths& paths, ECurveAnalyseMode mode = ECurveAnalyseMode::RelativeMode);
};
}
#endif

View file

@ -264,8 +264,8 @@ void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang, const
// now split path_idx in two parts
const ExtrusionPath &path = this->paths[path_idx];
ExtrusionPath p1(path.overhang_degree, path.curve_degree, path.role(), path.mm3_per_mm, path.width, path.height);
ExtrusionPath p2(path.overhang_degree, path.curve_degree, path.role(), path.mm3_per_mm, path.width, path.height);
ExtrusionPath p1(path.role(), path.mm3_per_mm, path.width, path.height);
ExtrusionPath p2(path.role(), path.mm3_per_mm, path.width, path.height);
path.polyline.split_at(p, &p1.polyline, &p2.polyline);
if (this->paths.size() == 1) {

View file

@ -151,8 +151,6 @@ class ExtrusionPath : public ExtrusionEntity
{
public:
Polyline polyline;
double overhang_degree = 0;
int curve_degree = 0;
// Volumetric velocity. mm^3 of plastic per mm of linear head motion. Used by the G-code generator.
double mm3_per_mm;
// Width of the extrusion, used for visualization purposes.
@ -163,12 +161,9 @@ public:
ExtrusionPath() : mm3_per_mm(-1), width(-1), height(-1), m_role(erNone), m_no_extrusion(false) {}
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {}
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height, bool no_extrusion = false) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role), m_no_extrusion(no_extrusion) {}
ExtrusionPath(double overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {}
ExtrusionPath(const ExtrusionPath &rhs)
: polyline(rhs.polyline)
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
@ -178,8 +173,6 @@ public:
{}
ExtrusionPath(ExtrusionPath &&rhs)
: polyline(std::move(rhs.polyline))
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
@ -189,8 +182,6 @@ public:
{}
ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs)
: polyline(polyline)
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
@ -200,8 +191,6 @@ public:
{}
ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs)
: polyline(std::move(polyline))
, overhang_degree(rhs.overhang_degree)
, curve_degree(rhs.curve_degree)
, mm3_per_mm(rhs.mm3_per_mm)
, width(rhs.width)
, height(rhs.height)
@ -217,8 +206,6 @@ public:
this->mm3_per_mm = rhs.mm3_per_mm;
this->width = rhs.width;
this->height = rhs.height;
this->overhang_degree = rhs.overhang_degree;
this->curve_degree = rhs.curve_degree;
this->polyline = rhs.polyline;
return *this;
}
@ -229,8 +216,6 @@ public:
this->mm3_per_mm = rhs.mm3_per_mm;
this->width = rhs.width;
this->height = rhs.height;
this->overhang_degree = rhs.overhang_degree;
this->curve_degree = rhs.curve_degree;
this->polyline = std::move(rhs.polyline);
return *this;
}
@ -272,22 +257,6 @@ public:
void collect_points(Points &dst) const override { append(dst, this->polyline.points); }
double total_volume() const override { return mm3_per_mm * unscale<double>(length()); }
void set_overhang_degree(int overhang) {
if (is_perimeter(m_role) || is_bridge(m_role))
overhang_degree = (overhang < 0)?0:(overhang > 10 ? 10 : overhang);
};
int get_overhang_degree() const {
// only perimeter has overhang degree. Other return 0;
if (is_perimeter(m_role))
return (int)overhang_degree;
return 0;
};
void set_curve_degree(int curve) {
curve_degree = (curve < 0)?0:(curve > 10 ? 10 : curve);
};
int get_curve_degree() const {
return curve_degree;
};
//BBS: add new simplifing method by fitting arc
void simplify_by_fitting_arc(double tolerance);
//BBS:
@ -525,17 +494,7 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, Ex
dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height));
dst.back().polyline = polyline;
}
}
inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.push_back(ExtrusionPath(overhang_degree, curva_degree, role, mm3_per_mm, width, height));
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = polyline;
}
}
@ -545,31 +504,19 @@ inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, E
dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height));
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = std::move(polyline);
}
polylines.clear();
}
inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + polylines.size());
for (Polyline &polyline : polylines)
if (polyline.is_valid()) {
dst.push_back(ExtrusionPath(overhang_degree, curva_degree, role, mm3_per_mm, width, height));
dst.back().polyline = std::move(polyline);
}
polylines.clear();
}
inline void extrusion_paths_append(ExtrusionPaths &dst, Polyline &&polyline, double overhang_degree, int curva_degree, ExtrusionRole role, double mm3_per_mm, float width, float height)
inline void extrusion_paths_append(ExtrusionPaths &dst, Polyline &&polyline, ExtrusionRole role, double mm3_per_mm, float width, float height)
{
dst.reserve(dst.size() + 1);
if (polyline.is_valid()) {
dst.push_back(ExtrusionPath(overhang_degree, curva_degree, role, mm3_per_mm, width, height));
dst.emplace_back(role, mm3_per_mm, width, height);
dst.back().polyline = std::move(polyline);
}
polyline.clear();
}
inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height, bool can_reverse = true)
@ -609,7 +556,7 @@ inline void extrusion_entities_append_paths_with_wipe(ExtrusionEntitiesPtr &dst,
if (last_end_point_valid) {
Point temp = polyline.first_point() - last_end_point;
if (Vec2d(temp.x(), temp.y()).norm() <= 3 * scaled(width)) {
multi_path->paths.push_back(ExtrusionPath(role, mm3_per_mm, width, height, true));
multi_path->paths.emplace_back(role, mm3_per_mm, width, height, true);
multi_path->paths.back().polyline = std::move(Polyline(last_end_point, polyline.first_point()));
} else {
dst.push_back(multi_path);
@ -617,7 +564,7 @@ inline void extrusion_entities_append_paths_with_wipe(ExtrusionEntitiesPtr &dst,
}
}
multi_path->paths.push_back(ExtrusionPath(role, mm3_per_mm, width, height));
multi_path->paths.emplace_back(role, mm3_per_mm, width, height);
multi_path->paths.back().polyline = std::move(polyline);
last_end_point_valid = true;
last_end_point = multi_path->paths.back().polyline.last_point();

View file

@ -3904,7 +3904,7 @@ LayerResult GCode::process_layer(
if (layer_to_print.object_layer) {
const auto& regions = layer_to_print.object_layer->regions();
const bool enable_overhang_speed = std::any_of(regions.begin(), regions.end(), [](const LayerRegion* r) {
return r->has_extrusions() && r->region().config().enable_overhang_speed && !r->region().config().overhang_speed_classic;
return r->has_extrusions() && r->region().config().enable_overhang_speed;
});
if (enable_overhang_speed) {
m_extrusion_quality_estimator.prepare_for_new_layer(layer_to_print.original_object,
@ -4787,7 +4787,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
const auto speed_for_path = [&speed, &small_peri_speed](const ExtrusionPath& path) {
// don't apply small perimeter setting for overhangs/bridges/non-perimeters
const bool is_small_peri = is_perimeter(path.role()) && !is_bridge(path.role()) && small_peri_speed > 0 && (path.get_overhang_degree() == 0 || path.get_overhang_degree() > 5);
const bool is_small_peri = is_perimeter(path.role()) && !is_bridge(path.role()) && small_peri_speed > 0;
return is_small_peri ? small_peri_speed : speed;
};
@ -5166,39 +5166,6 @@ void GCode::GCodeOutputStream::write_format(const char* format, ...)
va_end(args);
}
static std::map<int, std::string> overhang_speed_key_map =
{
{1, "overhang_1_4_speed"},
{2, "overhang_2_4_speed"},
{3, "overhang_3_4_speed"},
{4, "overhang_4_4_speed"},
{5, "bridge_speed"},
};
double GCode::get_overhang_degree_corr_speed(float normal_speed, double path_degree) {
//BBS: protection: overhang degree is float, make sure it not excess degree range
if (path_degree <= 0)
return normal_speed;
if (path_degree >= 5 )
return m_config.get_abs_value(overhang_speed_key_map[5].c_str());
int lower_degree_bound = int(path_degree);
if (path_degree==lower_degree_bound)
return m_config.get_abs_value(overhang_speed_key_map[lower_degree_bound].c_str());
int upper_degree_bound = lower_degree_bound + 1;
double lower_speed_bound = lower_degree_bound == 0 ? normal_speed : m_config.get_abs_value(overhang_speed_key_map[lower_degree_bound].c_str());
double upper_speed_bound = upper_degree_bound == 0 ? normal_speed : m_config.get_abs_value(overhang_speed_key_map[upper_degree_bound].c_str());
lower_speed_bound = lower_speed_bound == 0 ? normal_speed : lower_speed_bound;
upper_speed_bound = upper_speed_bound == 0 ? normal_speed : upper_speed_bound;
double speed_out = lower_speed_bound + (upper_speed_bound - lower_speed_bound) * (path_degree - lower_degree_bound);
return speed_out;
}
bool GCode::_needSAFC(const ExtrusionPath &path)
{
if (!m_small_area_infill_flow_compensator || !m_config.small_area_infill_flow_compensation.value)
@ -5338,22 +5305,11 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
if (speed == -1) {
if (path.role() == erPerimeter) {
speed = m_config.get_abs_value("inner_wall_speed");
if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value) {
double new_speed = 0;
new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree);
speed = new_speed == 0.0 ? speed : new_speed;
}
if (sloped) {
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(m_config.get_abs_value("inner_wall_speed")));
}
} else if (path.role() == erExternalPerimeter) {
speed = m_config.get_abs_value("outer_wall_speed");
if (m_config.overhang_speed_classic.value && m_config.enable_overhang_speed.value ) {
double new_speed = 0;
new_speed = get_overhang_degree_corr_speed(speed, path.overhang_degree);
speed = new_speed == 0.0 ? speed : new_speed;
}
if (sloped) {
speed = std::min(speed, m_config.scarf_joint_speed.get_abs_value(m_config.get_abs_value("outer_wall_speed")));
}
@ -5461,7 +5417,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
bool variable_speed = false;
std::vector<ProcessedPoint> new_points {};
if (m_config.enable_overhang_speed && !m_config.overhang_speed_classic && !this->on_first_layer() &&
if (m_config.enable_overhang_speed && !this->on_first_layer() &&
(is_bridge(path.role()) || is_perimeter(path.role()))) {
bool is_external = is_external_perimeter(path.role());
double ref_speed = is_external ? m_config.get_abs_value("outer_wall_speed") : m_config.get_abs_value("inner_wall_speed");
@ -5746,11 +5702,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
if (enable_overhang_bridge_fan) {
// BBS: Overhang_threshold_none means Overhang_threshold_1_4 and forcing cooling for all external
// perimeter
int overhang_threshold = overhang_fan_threshold == Overhang_threshold_none ? Overhang_threshold_none
: overhang_fan_threshold - 1;
if ((overhang_fan_threshold == Overhang_threshold_none && is_external_perimeter(path.role())) ||
(path.get_overhang_degree() > overhang_threshold ||
(path.role() == erBridgeInfill || path.role() == erOverhangPerimeter))) { // ORCA: Add support for separate internal bridge fan speed control
(path.role() == erBridgeInfill || path.role() == erOverhangPerimeter)) { // ORCA: Add support for separate internal bridge fan speed control
if (!m_is_overhang_fan_on) {
gcode += ";_OVERHANG_FAN_START\n";
m_is_overhang_fan_on = true;

View file

@ -606,7 +606,6 @@ private:
std::string _extrude(const ExtrusionPath &path, std::string description = "", double speed = -1);
bool _needSAFC(const ExtrusionPath &path);
double get_overhang_degree_corr_speed(float speed, double path_degree);
void print_machine_envelope(GCodeOutputStream &file, Print &print);
void _print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);
void _print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait);

View file

@ -7,7 +7,6 @@
#include "PrintConfig.hpp"
#include "ShortestPath.hpp"
#include "VariableWidth.hpp"
#include "CurveAnalyzer.hpp"
#include "Arachne/WallToolPaths.hpp"
#include "Geometry/ConvexHull.hpp"
#include "ExPolygonCollection.hpp"
@ -24,8 +23,6 @@
#include "libnoise/noise.h"
static const int overhang_sampling_number = 6;
static const double narrow_loop_length_threshold = 10;
static const double min_degree_gap = 0.1;
static const int max_overhang_degree = overhang_sampling_number - 1;
//BBS: when the width of expolygon is smaller than
//ext_perimeter_width + ext_perimeter_spacing * (1 - SMALLER_EXT_INSET_OVERLAP_TOLERANCE),
//we think it's small detail area and will generate smaller line width for it
@ -194,273 +191,6 @@ static void fuzzy_extrusion_line(std::vector<Arachne::ExtrusionJunction>& ext_li
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
static void lowpass_filter_by_paths_overhang_degree(ExtrusionPaths& paths) {
const double filter_range = scale_(6.5);
const double threshold_length = scale_(1.2);
//0.save old overhang series first which is input of filter
const int path_num = paths.size();
if (path_num < 2)
//don't need to do filting if only has one path in vector
return;
std::vector<int> old_overhang_series;
old_overhang_series.reserve(path_num);
for (int i = 0; i < path_num; i++)
old_overhang_series.push_back(paths[i].get_overhang_degree());
//1.lowpass filter
for (int i = 0; i < path_num; i++) {
double current_length = paths[i].length();
int current_overhang_degree = old_overhang_series[i];
if (current_length < threshold_length &&
(paths[i].role() == erPerimeter || paths[i].role() == erExternalPerimeter)) {
double left_total_length = (filter_range - current_length) / 2;
double right_total_length = left_total_length;
double temp_length;
int j = i - 1;
int index;
std::vector<std::pair<double, int>> neighbor_path;
while (left_total_length > 0) {
index = (j < 0) ? path_num - 1 : j;
if (paths[index].role() == erOverhangPerimeter)
break;
temp_length = paths[index].length();
if (temp_length > left_total_length)
neighbor_path.emplace_back(std::pair<double, int>(left_total_length, old_overhang_series[index]));
else
neighbor_path.emplace_back(std::pair<double, int>(temp_length, old_overhang_series[index]));
left_total_length -= temp_length;
j = index;
j--;
}
j = i + 1;
while (right_total_length > 0) {
index = j % path_num;
if (paths[index].role() == erOverhangPerimeter)
break;
temp_length = paths[index].length();
if (temp_length > right_total_length)
neighbor_path.emplace_back(std::pair<double, int>(right_total_length, old_overhang_series[index]));
else
neighbor_path.emplace_back(std::pair<double, int>(temp_length, old_overhang_series[index]));
right_total_length -= temp_length;
j++;
}
double sum = 0;
double length_sum = 0;
for (auto it = neighbor_path.begin(); it != neighbor_path.end(); it++) {
sum += (it->first * it->second);
length_sum += it->first;
}
double average_overhang = (double)(current_length * current_overhang_degree + sum) / (length_sum + current_length);
paths[i].set_overhang_degree((int)average_overhang);
}
}
//2.merge path if have same overhang degree. from back to front to avoid data copy
int last_overhang = paths[0].get_overhang_degree();
auto it = paths.begin() + 1;
while (it != paths.end())
{
if (last_overhang == it->get_overhang_degree()) {
//BBS: don't need to append duplicated points, remove the last point
if ((it-1)->polyline.last_point() == it->polyline.first_point())
(it-1)->polyline.points.pop_back();
(it-1)->polyline.append(std::move(it->polyline));
it = paths.erase(it);
} else {
last_overhang = it->get_overhang_degree();
it++;
}
}
}
struct PolylineWithDegree
{
PolylineWithDegree(Polyline polyline, double overhang_degree) : polyline(polyline), overhang_degree(overhang_degree){};
Polyline polyline;
double overhang_degree = 0;
};
static std::deque<PolylineWithDegree> split_polyline_by_degree(const Polyline &polyline_with_insert_points, const std::deque<double> &points_overhang)
{
std::deque<PolylineWithDegree> out;
Polyline left;
Polyline right;
Polyline temp_copy = polyline_with_insert_points;
size_t poly_size = polyline_with_insert_points.size();
// BBS: merge degree in limited range
//find first degee base
double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap) * min_degree_gap + min_degree_gap;
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
double short_poly_len = 0;
for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) {
double degree = points_overhang[point_idx];
if ( degree <= degree_base && degree >= degree_base - min_degree_gap )
continue;
temp_copy.split_at_index(point_idx, &left, &right);
temp_copy = std::move(left);
out.push_back(PolylineWithDegree(right, degree_base));
degree_base = int(degree / min_degree_gap) * min_degree_gap + min_degree_gap;
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
}
if (!temp_copy.empty()) {
out.push_back(PolylineWithDegree(temp_copy, degree_base));
}
return out;
}
static void insert_point_to_line( double left_point_degree,
Point left_point,
double right_point_degree,
Point right_point,
std::deque<double> &points_overhang,
Polyline& polyline,
double mini_length)
{
Line line_temp(left_point, right_point);
double line_length = line_temp.length();
if (std::abs(left_point_degree - right_point_degree) <= 0.5 * min_degree_gap || line_length<scale_(1.5))
return;
Point middle_pt((left_point + right_point) / 2);
std::deque<double> left_points_overhang;
std::deque<double> right_points_overhang;
double middle_degree = (left_point_degree + right_point_degree) / 2;
Polyline left_polyline;
Polyline right_polyline;
insert_point_to_line(left_point_degree, left_point, middle_degree, middle_pt, left_points_overhang, left_polyline, mini_length);
insert_point_to_line(middle_degree, middle_pt, right_point_degree, right_point, right_points_overhang, right_polyline, mini_length);
if (!left_polyline.empty()) {
polyline.points.insert(polyline.points.end(), std::make_move_iterator(left_polyline.points.begin()), std::make_move_iterator(left_polyline.points.end()));
points_overhang.insert(points_overhang.end(), std::make_move_iterator(left_points_overhang.begin()), std::make_move_iterator(left_points_overhang.end()));
}
polyline.append(middle_pt);
points_overhang.emplace_back(middle_degree);
if (!right_polyline.empty()) {
polyline.points.insert(polyline.points.end(), std::make_move_iterator(right_polyline.points.begin()), std::make_move_iterator(right_polyline.points.end()));
points_overhang.insert(points_overhang.end(), std::make_move_iterator(right_points_overhang.begin()), std::make_move_iterator(right_points_overhang.end()));
}
}
class OverhangDistancer
{
std::vector<Linef> lines;
AABBTreeIndirect::Tree<2, double> tree;
public:
OverhangDistancer(const Polygons layer_polygons)
{
for (const Polygon &island : layer_polygons) {
for (const auto &line : island.lines()) {
lines.emplace_back(line.a.cast<double>(), line.b.cast<double>());
}
}
tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines);
}
float distance_from_perimeter(const Vec2f &point) const
{
Vec2d p = point.cast<double>();
size_t hit_idx_out{};
Vec2d hit_point_out = Vec2d::Zero();
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out);
if (distance < 0) { return std::numeric_limits<float>::max(); }
distance = sqrt(distance);
return distance;
}
};
static std::deque<PolylineWithDegree> detect_overahng_degree(Polygons lower_polygons,
Polylines middle_overhang_polyines,
const double &lower_bound,
const double &upper_bound,
Polylines &too_short_polylines)
{
// BBS: collect lower_polygons points
//Polylines;
Points lower_polygon_points;
std::vector<size_t> polygons_bound;
std::unique_ptr<OverhangDistancer> prev_layer_distancer;
prev_layer_distancer = std::make_unique<OverhangDistancer>(lower_polygons);
std::deque<PolylineWithDegree> out;
std::deque<double> points_overhang;
//BBS: get overhang degree and split path
for (size_t polyline_idx = 0; polyline_idx < middle_overhang_polyines.size(); ++polyline_idx) {
//filter too short polyline
Polyline middle_poly = middle_overhang_polyines[polyline_idx];
if (middle_poly.length() < scale_(1.0)) {
too_short_polylines.push_back(middle_poly);
continue;
}
Polyline polyline_with_insert_points;
points_overhang.clear();
double last_degree = 0;
// BBS : calculate overhang dist
for (size_t point_idx = 0; point_idx < middle_poly.points.size(); ++point_idx) {
Point pt = middle_poly.points[point_idx];
float overhang_dist = prev_layer_distancer->distance_from_perimeter(pt.cast<float>());
overhang_dist = overhang_dist > upper_bound ? upper_bound : overhang_dist;
// BBS : calculate overhang degree
int max_overhang = max_overhang_degree;
int min_overhang = 0;
double t = (overhang_dist - lower_bound) / (upper_bound - lower_bound);
t = t > 1.0 ? 1: t;
t = t < EPSILON ? 0 : t;
double this_degree = (1.0 - t) * min_overhang + t * max_overhang;
// BBS: intert points
if (point_idx > 0) {
insert_point_to_line(last_degree, middle_poly.points[point_idx - 1], this_degree, pt, points_overhang, polyline_with_insert_points,
upper_bound - lower_bound);
}
points_overhang.push_back(this_degree);
polyline_with_insert_points.append(pt);
last_degree = this_degree;
}
// BBS : split path by degree
std::deque<PolylineWithDegree> polyline_with_merged_degree = split_polyline_by_degree(polyline_with_insert_points, points_overhang);
out.insert(out.end(), std::make_move_iterator(polyline_with_merged_degree.begin()), std::make_move_iterator(polyline_with_merged_degree.end()));
}
return out;
}
std::pair<double, double> PerimeterGenerator::dist_boundary(double width)
{
std::pair<double, double> out;
float nozzle_diameter = print_config->nozzle_diameter.get_at(config->wall_filament - 1);
float start_offset = -0.5 * width;
float end_offset = 0.5 * nozzle_diameter;
double degree_0 = scale_(start_offset + 0.5 * (end_offset - start_offset) / (overhang_sampling_number - 1));
out.first = 0;
out.second = scale_(end_offset) - degree_0;
return out;
}
template<class _T>
static bool detect_steep_overhang(const PrintRegionConfig *config,
bool is_contour,
@ -552,27 +282,23 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
// BBS: get lower polygons series, width, mm3_per_mm
const std::vector<Polygons> *lower_polygons_series;
const std::pair<double, double> *overhang_dist_boundary;
double extrusion_mm3_per_mm;
double extrusion_width;
if (is_external) {
if (is_small_width) {
//BBS: smaller width external perimeter
lower_polygons_series = &perimeter_generator.m_smaller_external_lower_polygons_series;
overhang_dist_boundary = &perimeter_generator.m_smaller_external_overhang_dist_boundary;
extrusion_mm3_per_mm = perimeter_generator.smaller_width_ext_mm3_per_mm();
extrusion_width = perimeter_generator.smaller_ext_perimeter_flow.width();
} else {
//BBS: normal external perimeter
lower_polygons_series = &perimeter_generator.m_external_lower_polygons_series;
overhang_dist_boundary = &perimeter_generator.m_external_overhang_dist_boundary;
extrusion_mm3_per_mm = perimeter_generator.ext_mm3_per_mm();
extrusion_width = perimeter_generator.ext_perimeter_flow.width();
}
} else {
//BBS: normal perimeter
lower_polygons_series = &perimeter_generator.m_lower_polygons_series;
overhang_dist_boundary = &perimeter_generator.m_lower_overhang_dist_boundary;
extrusion_mm3_per_mm = perimeter_generator.mm3_per_mm();
extrusion_width = perimeter_generator.perimeter_flow.width();
}
@ -704,70 +430,20 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
remain_polines = diff_pl({polygon}, lower_polygons_series_clipped);
bool detect_overhang_degree = perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && !perimeter_generator.has_fuzzy_skin;
if (!detect_overhang_degree) {
if (!inside_polines.empty())
extrusion_paths_append(
paths,
std::move(inside_polines),
0,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float)perimeter_generator.layer_height);
} else {
Polygons lower_polygons_series_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(lower_polygons_series->front(), bbox);
Polylines middle_overhang_polyines = diff_pl({inside_polines}, lower_polygons_series_clipped);
//BBS: add zero_degree_path
Polylines zero_degree_polines = intersection_pl({inside_polines}, lower_polygons_series_clipped);
if (!zero_degree_polines.empty())
extrusion_paths_append(
paths,
std::move(zero_degree_polines),
0,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float)perimeter_generator.layer_height);
//BBS: detect middle line overhang
if (!middle_overhang_polyines.empty()) {
Polylines too_short_polylines;
std::deque<PolylineWithDegree> polylines_degree_collection = detect_overahng_degree(lower_polygons_series->front(),
middle_overhang_polyines,
overhang_dist_boundary->first,
overhang_dist_boundary->second,
too_short_polylines);
if (!too_short_polylines.empty())
extrusion_paths_append(paths,
std::move(too_short_polylines),
0,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float) perimeter_generator.layer_height);
// BBS: add path with overhang degree
for (PolylineWithDegree polylines_collection : polylines_degree_collection) {
extrusion_paths_append(paths,
std::move(polylines_collection.polyline),
polylines_collection.overhang_degree,
int(0),
role,
extrusion_mm3_per_mm,
extrusion_width, (float) perimeter_generator.layer_height);
}
}
}
if (!inside_polines.empty())
extrusion_paths_append(
paths,
std::move(inside_polines),
role,
extrusion_mm3_per_mm,
extrusion_width,
(float)perimeter_generator.layer_height);
// get 100% overhang paths by checking what parts of this loop fall
// outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter
if (remain_polines.size() != 0) {
extrusion_paths_append(paths, std::move(remain_polines), overhang_sampling_number - 1, int(0),
extrusion_paths_append(paths, std::move(remain_polines),
erOverhangPerimeter, perimeter_generator.mm3_per_mm_overhang(),
perimeter_generator.overhang_flow.width(),
perimeter_generator.overhang_flow.height());
@ -787,8 +463,6 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
ExtrusionPath path(role);
//BBS.
path.polyline = polygon.split_at_first_point();
path.overhang_degree = 0;
path.curve_degree = 0;
path.mm3_per_mm = extrusion_mm3_per_mm;
path.width = extrusion_width;
path.height = (float)perimeter_generator.layer_height;
@ -926,90 +600,6 @@ struct PerimeterGeneratorArachneExtrusion
bool is_contour = false;
};
static void smooth_overhang_level(ExtrusionPaths &paths)
{
const double threshold_length = scale_(0.8);
const double filter_range = scale_(6.5);
// 0.save old overhang series first which is input of filter
const int path_num = paths.size();
if (path_num < 2)
// don't need to do filting if only has one path in vector
return;
std::vector<int> old_overhang_series;
old_overhang_series.reserve(path_num);
for (int i = 0; i < path_num; i++) old_overhang_series.push_back(paths[i].get_overhang_degree());
for (int i = 0; i < path_num;) {
if ((paths[i].role() != erPerimeter && paths[i].role() != erExternalPerimeter)) {
i++;
continue;
}
double current_length = paths[i].length();
int current_overhang_degree = old_overhang_series[i];
double total_lens = current_length;
int pt = i + 1;
for (; pt < path_num; pt++) {
if (paths[pt].get_overhang_degree() != current_overhang_degree || (paths[pt].role() != erPerimeter && paths[pt].role() != erExternalPerimeter)) {
break;
}
total_lens += paths[pt].length();
}
if (total_lens < threshold_length) {
double left_total_length = (filter_range - total_lens) / 2;
double right_total_length = left_total_length;
double temp_length;
int j = i - 1;
int index;
std::vector<std::pair<double, int>> neighbor_path;
while (left_total_length > 0) {
index = (j < 0) ? path_num - 1 : j;
if (paths[index].role() == erOverhangPerimeter) break;
temp_length = paths[index].length();
if (temp_length > left_total_length)
neighbor_path.emplace_back(std::pair<double, int>(left_total_length, old_overhang_series[index]));
else
neighbor_path.emplace_back(std::pair<double, int>(temp_length, old_overhang_series[index]));
left_total_length -= temp_length;
j = index;
j--;
}
j = pt;
while (right_total_length > 0) {
index = j % path_num;
if (paths[index].role() == erOverhangPerimeter) break;
temp_length = paths[index].length();
if (temp_length > right_total_length)
neighbor_path.emplace_back(std::pair<double, int>(right_total_length, old_overhang_series[index]));
else
neighbor_path.emplace_back(std::pair<double, int>(temp_length, old_overhang_series[index]));
right_total_length -= temp_length;
j++;
}
double sum = 0;
double length_sum = 0;
for (auto it = neighbor_path.begin(); it != neighbor_path.end(); it++) {
sum += (it->first * it->second);
length_sum += it->first;
}
double average_overhang = (double) (total_lens * current_overhang_degree + sum) / (length_sum + total_lens);
for (int idx=i; idx<pt;idx++)
paths[idx].set_overhang_degree((int) average_overhang);
}
i = pt;
}
}
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& perimeter_generator, std::vector<PerimeterGeneratorArachneExtrusion>& pg_extrusions,
bool &steep_overhang_contour, bool &steep_overhang_hole)
{
@ -1129,9 +719,8 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
}
}
ExtrusionPaths temp_paths;
// get non-overhang paths by intersecting this loop with the grown lower slices
extrusion_paths_append(temp_paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role,
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role,
is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
// Always reverse extrusion if use fuzzy skin: https://github.com/SoftFever/OrcaSlicer/pull/2413#issuecomment-1769735357
@ -1147,7 +736,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
bool found_steep_overhang = (pg_extrusion.is_contour && steep_overhang_contour) || (!pg_extrusion.is_contour && steep_overhang_hole);
if (overhangs_reverse && !found_steep_overhang) {
std::map<double, ExtrusionPaths> recognization_paths;
for (const ExtrusionPath &path : temp_paths) {
for (const ExtrusionPath &path : paths) {
if (recognization_paths.count(path.width))
recognization_paths[path.width].emplace_back(std::move(path));
else
@ -1169,56 +758,6 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
}
}
if (perimeter_generator.config->overhang_speed_classic && perimeter_generator.config->enable_overhang_speed && !perimeter_generator.has_fuzzy_skin) {
Flow flow = is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow;
std::map<double, std::vector<Polygons>> clipper_serise;
std::map<double,ExtrusionPaths> recognization_paths;
for (const ExtrusionPath &path : temp_paths) {
if (recognization_paths.count(path.width))
recognization_paths[path.width].emplace_back(std::move(path));
else
recognization_paths.insert(std::pair<double, ExtrusionPaths>(path.width, {std::move(path)}));
}
for (const auto &it : recognization_paths) {
Polylines be_clipped;
for (const ExtrusionPath &p : it.second) {
be_clipped.emplace_back(std::move(p.polyline));
}
BoundingBox extrusion_bboxs = get_extents(be_clipped);
//ExPolygons lower_slcier_chopped = *perimeter_generator.lower_slices;
Polygons lower_slcier_chopped=ClipperUtils::clip_clipper_polygons_with_subject_bbox(*perimeter_generator.lower_slices, extrusion_bboxs, true);
double start_pos = -it.first * 0.5;
double end_pos = 0.5 * it.first;
Polylines remain_polylines;
std::vector<Polygons> degree_polygons;
for (int j = 0; j < overhang_sampling_number; j++) {
Polygons limiton_polygons = offset(lower_slcier_chopped, float(scale_(start_pos + (j + 0.5) * (end_pos - start_pos) / (overhang_sampling_number - 1))));
Polylines inside_polines = j == 0 ? intersection_pl(be_clipped, limiton_polygons) : intersection_pl(remain_polylines, limiton_polygons);
remain_polylines = j == 0 ? diff_pl(be_clipped, limiton_polygons) : diff_pl(remain_polylines, limiton_polygons);
extrusion_paths_append(paths, std::move(inside_polines), j, int(0), role, it.second.front().mm3_per_mm, it.second.front().width, it.second.front().height);
if (remain_polylines.size() == 0) break;
}
if (remain_polylines.size() != 0) {
extrusion_paths_append(paths, std::move(remain_polylines), overhang_sampling_number - 1, int(0), erOverhangPerimeter, it.second.front().mm3_per_mm, it.second.front().width, it.second.front().height);
}
}
} else {
paths = std::move(temp_paths);
}
// get overhang paths by checking what parts of this loop fall
// outside the grown lower slices (thus where the distance between
// the loop centerline and original lower slices is >= half nozzle diameter
@ -1262,11 +801,6 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator& p
chain_and_reorder_extrusion_paths(paths, &start_point);
if (perimeter_generator.config->enable_overhang_speed && !perimeter_generator.has_fuzzy_skin) {
// BBS: filter the speed
smooth_overhang_level(paths);
}
if (overhangs_reverse) {
for (const ExtrusionPath& path : paths) {
if (path.role() == erOverhangPerimeter) {
@ -1998,16 +1532,12 @@ void PerimeterGenerator::process_classic()
// prepare grown lower layer slices for overhang detection
m_lower_polygons_series = generate_lower_polygons_series(this->perimeter_flow.width());
m_lower_overhang_dist_boundary = dist_boundary(this->perimeter_flow.width());
if (ext_perimeter_width == perimeter_width){
m_external_lower_polygons_series = m_lower_polygons_series;
m_external_overhang_dist_boundary=m_lower_overhang_dist_boundary;
} else {
m_external_lower_polygons_series = generate_lower_polygons_series(this->ext_perimeter_flow.width());
m_external_overhang_dist_boundary = dist_boundary(this->ext_perimeter_flow.width());
}
m_smaller_external_lower_polygons_series = generate_lower_polygons_series(this->smaller_ext_perimeter_flow.width());
m_smaller_external_overhang_dist_boundary = dist_boundary(this->smaller_ext_perimeter_flow.width());
// we need to process each island separately because we might have different
// extra perimeters for each one
Surfaces all_surfaces = this->slices->surfaces;

View file

@ -87,9 +87,6 @@ public:
std::vector<Polygons> m_lower_polygons_series;
std::vector<Polygons> m_external_lower_polygons_series;
std::vector<Polygons> m_smaller_external_lower_polygons_series;
std::pair<double, double> m_lower_overhang_dist_boundary;
std::pair<double, double> m_external_overhang_dist_boundary;
std::pair<double, double> m_smaller_external_overhang_dist_boundary;
bool has_fuzzy_skin = false;
bool has_fuzzy_hole = false;
@ -142,7 +139,6 @@ private:
void split_top_surfaces(const ExPolygons &orig_polygons, ExPolygons &top_fills, ExPolygons &non_top_polygons, ExPolygons &fill_clip) const;
void apply_extra_perimeters(ExPolygons& infill_area);
void process_no_bridge(Surfaces& all_surfaces, coord_t perimeter_spacing, coord_t ext_perimeter_width);
std::pair<double, double> dist_boundary(double width);
private:
bool m_spiral_vase;

View file

@ -826,7 +826,7 @@ static std::vector<std::string> s_Preset_print_options {
"default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk","default_junction_deviation",
"top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap",
"role_based_wipe_speed", "wipe_speed", "accel_to_decel_enable", "accel_to_decel_factor", "wipe_on_loops", "wipe_before_external_loop",
"bridge_density","internal_bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
"bridge_density","internal_bridge_density", "precise_outer_wall", "bridge_acceleration",
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max","initial_layer_min_bead_width",

View file

@ -3168,8 +3168,6 @@ const std::string PrintStatistics::TotalFilamentUsedWipeTowerValueMask = "; tota
#define JSON_EXTRUSION_TYPE_LOOP "loop"
#define JSON_EXTRUSION_TYPE_COLLECTION "collection"
#define JSON_EXTRUSION_POLYLINE "polyline"
#define JSON_EXTRUSION_OVERHANG_DEGREE "overhang_degree"
#define JSON_EXTRUSION_CURVE_DEGREE "curve_degree"
#define JSON_EXTRUSION_MM3_PER_MM "mm3_per_mm"
#define JSON_EXTRUSION_WIDTH "width"
#define JSON_EXTRUSION_HEIGHT "height"
@ -3263,8 +3261,6 @@ static void to_json(json& j, const Polyline& poly_line) {
static void to_json(json& j, const ExtrusionPath& extrusion_path) {
j[JSON_EXTRUSION_POLYLINE] = extrusion_path.polyline;
j[JSON_EXTRUSION_OVERHANG_DEGREE] = extrusion_path.overhang_degree;
j[JSON_EXTRUSION_CURVE_DEGREE] = extrusion_path.curve_degree;
j[JSON_EXTRUSION_MM3_PER_MM] = extrusion_path.mm3_per_mm;
j[JSON_EXTRUSION_WIDTH] = extrusion_path.width;
j[JSON_EXTRUSION_HEIGHT] = extrusion_path.height;
@ -3541,8 +3537,6 @@ static void from_json(const json& j, Polyline& poly_line) {
static void from_json(const json& j, ExtrusionPath& extrusion_path) {
extrusion_path.polyline = j[JSON_EXTRUSION_POLYLINE];
extrusion_path.overhang_degree = j[JSON_EXTRUSION_OVERHANG_DEGREE];
extrusion_path.curve_degree = j[JSON_EXTRUSION_CURVE_DEGREE];
extrusion_path.mm3_per_mm = j[JSON_EXTRUSION_MM3_PER_MM];
extrusion_path.width = j[JSON_EXTRUSION_WIDTH];
extrusion_path.height = j[JSON_EXTRUSION_HEIGHT];

View file

@ -1158,14 +1158,6 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloatOrPercent(50, true));
// Orca: deprecated
def = this->add("overhang_speed_classic", coBool);
def->label = L("Classic mode");
def->category = L("Speed");
def->tooltip = L("Enable this option to use classic mode.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool{ false });
def = this->add("enable_overhang_speed", coBool);
def->label = L("Slow down for overhang");
def->category = L("Speed");
@ -6693,8 +6685,6 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
}
else if (opt_key == "draft_shield" && value == "limited") {
value = "disabled";
} else if (opt_key == "overhang_speed_classic") {
value = "0";
}
// Ignore the following obsolete configuration keys:
@ -6713,7 +6703,8 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va
"retraction_distance_when_cut",
"extruder_type",
"internal_bridge_support_thickness","extruder_clearance_max_radius", "top_area_threshold", "reduce_wall_solid_infill","filament_load_time","filament_unload_time",
"smooth_coefficient", "overhang_totally_speed", "silent_mode"
"smooth_coefficient", "overhang_totally_speed", "silent_mode",
"overhang_speed_classic",
};
if (ignore.find(opt_key) != ignore.end()) {

View file

@ -1016,7 +1016,6 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, wipe_before_external_loop))
((ConfigOptionEnum<WallInfillOrder>, wall_infill_order))
((ConfigOptionBool, precise_outer_wall))
((ConfigOptionBool, overhang_speed_classic))
((ConfigOptionPercent, bridge_density))
((ConfigOptionFloat, filter_out_gap_fill))
((ConfigOptionFloatOrPercent, small_perimeter_speed))

View file

@ -1133,8 +1133,7 @@ bool PrintObject::invalidate_state_by_config_options(
//BBS
|| opt_key == "enable_overhang_speed"
|| opt_key == "detect_thin_wall"
|| opt_key == "precise_outer_wall"
|| opt_key == "overhang_speed_classic") {
|| opt_key == "precise_outer_wall") {
steps.emplace_back(posPerimeters);
steps.emplace_back(posSupportMaterial);
} else if (opt_key == "bridge_flow" || opt_key == "internal_bridge_flow") {

View file

@ -734,13 +734,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
toggle_line("max_travel_detour_distance", have_avoid_crossing_perimeters);
bool has_overhang_speed = config->opt_bool("enable_overhang_speed");
for (auto el :
{"overhang_speed_classic", "overhang_1_4_speed",
"overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed"})
for (auto el : {"overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_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("slowdown_for_curled_perimeters", has_overhang_speed);
toggle_line("flush_into_objects", !is_global_config);

View file

@ -110,7 +110,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
{"infill_combination", "",1}, {"infill_combination_max_layer_height", "",1}, {"infill_wall_overlap", "",1},{"top_bottom_infill_wall_overlap", "",1}, {"solid_infill_direction", "",1}, {"rotate_solid_infill_direction", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"internal_bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
}},
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
{"enable_overhang_speed", "",6}, {"overhang_speed_classic", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"enable_overhang_speed", "",6}, {"overhang_1_4_speed", "",7}, {"overhang_2_4_speed", "",8}, {"overhang_3_4_speed", "",9}, {"overhang_4_4_speed", "",10},
{"bridge_speed", "",11}, {"gap_infill_speed", "",12}, {"internal_bridge_speed", "", 13}
}}
};

View file

@ -2208,8 +2208,6 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Overhang speed"), L"param_overhang_speed", 15);
optgroup->append_single_option_line("enable_overhang_speed", "slow-down-for-overhang");
// Orca: DEPRECATED
// 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.label_path = "slow-down-for-overhang";