mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-06-26 09:25:26 -06:00
Remove classic overhang speed code (#9934)
* Remove code related to classic overhang speed * Remove `overhang_degree` and `curve_degree`
This commit is contained in:
parent
dec21efe7f
commit
7cbd0d2b74
17 changed files with 31 additions and 860 deletions
|
@ -59,8 +59,6 @@ set(lisbslic3r_sources
|
|||
Color.hpp
|
||||
Config.cpp
|
||||
Config.hpp
|
||||
CurveAnalyzer.cpp
|
||||
CurveAnalyzer.hpp
|
||||
EdgeGrid.cpp
|
||||
EdgeGrid.hpp
|
||||
ElephantFootCompensation.cpp
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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}
|
||||
}}
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue