mirror of
https://git.mirrors.martin98.com/https://github.com/bambulab/BambuStudio.git
synced 2025-09-28 15:53:14 +08:00
ENH: smooth overhang degree in arachne mode
jira: STUDIO-12110,STUDIO-11630 Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: I4e430dd2cea4bd4ad206e699d574abed3a656ce2
This commit is contained in:
parent
f2304fe1fc
commit
4b022b8287
@ -278,7 +278,17 @@ double ExtrusionLine::area() const
|
|||||||
} // namespace Slic3r::Arachne
|
} // namespace Slic3r::Arachne
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, int overhang)
|
|
||||||
|
void extrusion_paths_append(std::list<ExtrusionPath> &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang)
|
||||||
|
{
|
||||||
|
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
|
||||||
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
|
||||||
|
ExtrusionPaths path = thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON), overhang).paths;
|
||||||
|
dst.insert(dst.end(), std::make_move_iterator(path.begin()), std::make_move_iterator(path.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang)
|
||||||
{
|
{
|
||||||
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
|
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
|
||||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
|
||||||
@ -286,13 +296,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, int overhang)
|
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, double overhang)
|
||||||
{
|
{
|
||||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
|
||||||
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON), overhang).paths);
|
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON), overhang).paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, int overhang)
|
void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, double overhang)
|
||||||
{
|
{
|
||||||
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON), overhang).paths);
|
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON), overhang).paths);
|
||||||
}
|
}
|
||||||
|
@ -301,9 +301,10 @@ using VariableWidthLines = std::vector<ExtrusionLine>; //<! The ExtrusionLines g
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, int overhang = 0);
|
void extrusion_paths_append(std::list<ExtrusionPath> &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang = 0);
|
||||||
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, int overhang = 0);
|
void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extrusion_paths, const ExtrusionRole role, const Flow &flow, double overhang = 0);
|
||||||
void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, int overhang = 0);
|
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow, double overhang = 0);
|
||||||
|
void extrusion_path_append(ExtrusionPaths &dst, const ThickPolyline &thick_polyline, const ExtrusionRole role, const Flow &flow, double overhang = 0);
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif // UTILS_EXTRUSION_LINE_H
|
#endif // UTILS_EXTRUSION_LINE_H
|
||||||
|
@ -19,11 +19,12 @@ public:
|
|||||||
|
|
||||||
MultiPoint() {}
|
MultiPoint() {}
|
||||||
MultiPoint(const MultiPoint &other) : points(other.points) {}
|
MultiPoint(const MultiPoint &other) : points(other.points) {}
|
||||||
MultiPoint(MultiPoint &&other) : points(std::move(other.points)) {}
|
MultiPoint(MultiPoint &&other) noexcept : points(std::move(other.points)) {}
|
||||||
MultiPoint(std::initializer_list<Point> list) : points(list) {}
|
MultiPoint(std::initializer_list<Point> list) : points(list) {}
|
||||||
explicit MultiPoint(const Points &_points) : points(_points) {}
|
explicit MultiPoint(const Points &_points) : points(_points) {}
|
||||||
|
MultiPoint(Points&& _points) noexcept: points(std::move(_points)){}
|
||||||
MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; }
|
MultiPoint& operator=(const MultiPoint &other) { points = other.points; return *this; }
|
||||||
MultiPoint& operator=(MultiPoint &&other) { points = std::move(other.points); return *this; }
|
MultiPoint& operator=(MultiPoint &&other) noexcept { points = std::move(other.points); return *this; }
|
||||||
void scale(double factor);
|
void scale(double factor);
|
||||||
void scale(double factor_x, double factor_y);
|
void scale(double factor_x, double factor_y);
|
||||||
void translate(double x, double y) { this->translate(Point(coord_t(x), coord_t(y))); }
|
void translate(double x, double y) { this->translate(Point(coord_t(x), coord_t(y))); }
|
||||||
|
@ -173,6 +173,7 @@ namespace Slic3r {
|
|||||||
const double nozzle_diameter)
|
const double nozzle_diameter)
|
||||||
{
|
{
|
||||||
ExtrusionPaths ret_paths;
|
ExtrusionPaths ret_paths;
|
||||||
|
std::list<ExtrusionPath> ret_path_list;
|
||||||
ZPaths paths_in_range = clip_extrusion(extrusion_path, clip_paths, ClipperLib_Z::ctIntersection); //doing intersection first would be faster.
|
ZPaths paths_in_range = clip_extrusion(extrusion_path, clip_paths, ClipperLib_Z::ctIntersection); //doing intersection first would be faster.
|
||||||
|
|
||||||
paths_in_range = add_sampling_points(paths_in_range, scale_(2));// enough?
|
paths_in_range = add_sampling_points(paths_in_range, scale_(2));// enough?
|
||||||
@ -184,13 +185,15 @@ namespace Slic3r {
|
|||||||
for (auto& p : path) { assert(p.z() != 0); }
|
for (auto& p : path) { assert(p.z() != 0); }
|
||||||
}
|
}
|
||||||
|
|
||||||
auto in_same_degree_range = [](double a, double b) -> bool {
|
auto get_base_degree = [](double d){
|
||||||
int ceil_a = std::ceil(a);
|
return std::floor(d/min_degree_gap_arachne) * min_degree_gap_arachne;
|
||||||
int floor_a = std::floor(a);
|
};
|
||||||
int ceil_b = std::ceil(b);
|
|
||||||
int floor_b = std::floor(b);
|
auto in_same_degree_range = [&](double a, double b) -> bool {
|
||||||
return ceil_a == ceil_b && floor_a == floor_b;
|
double base_a = get_base_degree(a);
|
||||||
};
|
double base_b = get_base_degree(b);
|
||||||
|
return std::abs(base_a - base_b) < EPSILON;
|
||||||
|
};
|
||||||
|
|
||||||
struct SplitPoint
|
struct SplitPoint
|
||||||
{
|
{
|
||||||
@ -199,11 +202,10 @@ namespace Slic3r {
|
|||||||
double degree;
|
double degree;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto get_split_points = [](const Point& pa, const Point& pb, const coord_t wa, const coord_t wb, const double da, const double db) -> std::vector<SplitPoint> {
|
auto get_split_points = [&](const Point& pa, const Point& pb, const coord_t wa, const coord_t wb, const double da, const double db) -> std::vector<SplitPoint> {
|
||||||
std::vector<SplitPoint> ret;
|
std::vector<SplitPoint> ret;
|
||||||
|
double start_d = get_base_degree(std::min(da, db)) + min_degree_gap_arachne;
|
||||||
int start_d = (int)(std::ceil(std::min(da, db)));
|
double end_d = get_base_degree(std::max(da, db));
|
||||||
int end_d = (int)(std::floor(std::max(da, db)));
|
|
||||||
|
|
||||||
if (start_d > end_d) return ret;
|
if (start_d > end_d) return ret;
|
||||||
|
|
||||||
@ -211,7 +213,7 @@ namespace Slic3r {
|
|||||||
if (std::abs(delta_d) < 1e-6) return ret;
|
if (std::abs(delta_d) < 1e-6) return ret;
|
||||||
|
|
||||||
if (da < db) {
|
if (da < db) {
|
||||||
for (int k = start_d; k <= end_d; ++k) {
|
for (double k = start_d; k <= end_d; k+=min_degree_gap_arachne) {
|
||||||
const double t = (k - da) / delta_d;
|
const double t = (k - da) / delta_d;
|
||||||
const Point pt = pa + (pb - pa) * t;
|
const Point pt = pa + (pb - pa) * t;
|
||||||
const coord_t w = wa + coord_t((wb - wa) * t);
|
const coord_t w = wa + coord_t((wb - wa) * t);
|
||||||
@ -219,14 +221,13 @@ namespace Slic3r {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int k = end_d; k >= start_d; --k) {
|
for (double k = end_d; k >= start_d; k-=min_degree_gap_arachne) {
|
||||||
const double t = (k - da) / delta_d;
|
const double t = (k - da) / delta_d;
|
||||||
const Point pt = pa + (pb - pa) * t;
|
const Point pt = pa + (pb - pa) * t;
|
||||||
const coord_t w = wa + coord_t((wb - wa) * t);
|
const coord_t w = wa + coord_t((wb - wa) * t);
|
||||||
ret.emplace_back(SplitPoint{ pt, w, (double)k });
|
ret.emplace_back(SplitPoint{ pt, w, (double)k });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -287,11 +288,11 @@ namespace Slic3r {
|
|||||||
for (auto& split_point : split_points) {
|
for (auto& split_point : split_points) {
|
||||||
prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w });
|
prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w });
|
||||||
double target_degree = 0;
|
double target_degree = 0;
|
||||||
if (prev_d < curr_d)
|
if( prev_d < curr_d)
|
||||||
target_degree = split_point.degree - 1;
|
target_degree = split_point.degree - min_degree_gap_arachne;
|
||||||
else
|
else
|
||||||
target_degree = split_point.degree;
|
target_degree = split_point.degree;
|
||||||
extrusion_paths_append(ret_paths, { prev_line }, role, flow, target_degree);
|
extrusion_paths_append(ret_path_list , { prev_line }, role, flow, target_degree);
|
||||||
prev_line.clear();
|
prev_line.clear();
|
||||||
prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w });
|
prev_line.push_back({ split_point.p.x(), split_point.p.y(), split_point.w });
|
||||||
}
|
}
|
||||||
@ -301,8 +302,12 @@ namespace Slic3r {
|
|||||||
prev_line.push_back(path[idx]);
|
prev_line.push_back(path[idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (prev_line.size() > 1) { extrusion_paths_append(ret_paths, { prev_line }, role, flow, std::floor(prev_d)); }
|
if (prev_line.size() > 1) { extrusion_paths_append(ret_path_list, { prev_line }, role, flow, get_base_degree(prev_d)); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret_paths.reserve(ret_path_list.size());
|
||||||
|
ret_paths.insert(ret_paths.end(), std::make_move_iterator(ret_path_list.begin()), std::make_move_iterator(ret_path_list.end()));
|
||||||
|
|
||||||
return ret_paths;
|
return ret_paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@ using ZPath = ClipperLib_Z::Path;
|
|||||||
using ZPaths = ClipperLib_Z::Paths;
|
using ZPaths = ClipperLib_Z::Paths;
|
||||||
|
|
||||||
static const int overhang_sampling_number = 6;
|
static const int overhang_sampling_number = 6;
|
||||||
static const double min_degree_gap = 0.1;
|
static const double min_degree_gap_classic = 0.1;
|
||||||
|
static const double min_degree_gap_arachne = 0.25;
|
||||||
static const int max_overhang_degree = overhang_sampling_number - 1;
|
static const int max_overhang_degree = overhang_sampling_number - 1;
|
||||||
static const std::vector<double> non_uniform_degree_map = { 0, 10, 25, 50, 75, 100};
|
static const std::vector<double> non_uniform_degree_map = { 0, 10, 25, 50, 75, 100};
|
||||||
static const int insert_point_count = 3;
|
static const int insert_point_count = 3;
|
||||||
|
@ -243,14 +243,14 @@ static std::deque<PolylineWithDegree> split_polyline_by_degree(const Polyline &p
|
|||||||
size_t poly_size = polyline_with_insert_points.size();
|
size_t poly_size = polyline_with_insert_points.size();
|
||||||
// BBS: merge degree in limited range
|
// BBS: merge degree in limited range
|
||||||
//find first degee base
|
//find first degee base
|
||||||
double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap) * min_degree_gap + min_degree_gap;
|
double degree_base = int(points_overhang[points_overhang.size() - 1] / min_degree_gap_classic) * min_degree_gap_classic + min_degree_gap_classic;
|
||||||
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
|
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
|
||||||
double short_poly_len = 0;
|
double short_poly_len = 0;
|
||||||
for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) {
|
for (int point_idx = points_overhang.size() - 2; point_idx > 0; --point_idx) {
|
||||||
|
|
||||||
double degree = points_overhang[point_idx];
|
double degree = points_overhang[point_idx];
|
||||||
|
|
||||||
if ( degree <= degree_base && degree >= degree_base - min_degree_gap )
|
if ( degree <= degree_base && degree >= degree_base - min_degree_gap_classic )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
temp_copy.split_at_index(point_idx, &left, &right);
|
temp_copy.split_at_index(point_idx, &left, &right);
|
||||||
@ -258,7 +258,7 @@ static std::deque<PolylineWithDegree> split_polyline_by_degree(const Polyline &p
|
|||||||
temp_copy = std::move(left);
|
temp_copy = std::move(left);
|
||||||
out.push_back(PolylineWithDegree(right, degree_base));
|
out.push_back(PolylineWithDegree(right, degree_base));
|
||||||
|
|
||||||
degree_base = int(degree / min_degree_gap) * min_degree_gap + min_degree_gap;
|
degree_base = int(degree / min_degree_gap_classic) * min_degree_gap_classic + min_degree_gap_classic;
|
||||||
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
|
degree_base = degree_base > max_overhang_degree ? max_overhang_degree : degree_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ static void insert_point_to_line( double left_point_degree,
|
|||||||
{
|
{
|
||||||
Line line_temp(left_point, right_point);
|
Line line_temp(left_point, right_point);
|
||||||
double line_length = line_temp.length();
|
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))
|
if (std::abs(left_point_degree - right_point_degree) <= 0.5 * min_degree_gap_classic || line_length<scale_(1.5))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Point middle_pt((left_point + right_point) / 2);
|
Point middle_pt((left_point + right_point) / 2);
|
||||||
|
@ -20,7 +20,7 @@ class Polyline : public MultiPoint {
|
|||||||
public:
|
public:
|
||||||
Polyline() {};
|
Polyline() {};
|
||||||
Polyline(const Polyline& other) : MultiPoint(other.points), fitting_result(other.fitting_result) {}
|
Polyline(const Polyline& other) : MultiPoint(other.points), fitting_result(other.fitting_result) {}
|
||||||
Polyline(Polyline &&other) : MultiPoint(std::move(other.points)), fitting_result(std::move(other.fitting_result)) {}
|
Polyline(Polyline &&other) noexcept : MultiPoint(std::move(other.points)), fitting_result(std::move(other.fitting_result)) {}
|
||||||
Polyline(std::initializer_list<Point> list) : MultiPoint(list) {
|
Polyline(std::initializer_list<Point> list) : MultiPoint(list) {
|
||||||
fitting_result.clear();
|
fitting_result.clear();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, int overhang)
|
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, double overhang)
|
||||||
{
|
{
|
||||||
ExtrusionMultiPath multi_path;
|
ExtrusionMultiPath multi_path;
|
||||||
ExtrusionPath path(role);
|
ExtrusionPath path(role);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "Flow.hpp"
|
#include "Flow.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, int overhang);
|
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance, double overhang);
|
||||||
void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow& flow, std::vector<ExtrusionEntity*>& out);
|
void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const Flow& flow, std::vector<ExtrusionEntity*>& out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user