mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-20 05:07:51 -06:00
Fixed a bug that caused curled edge detection not to work as expected for left facing edges when using Arachne. Enabled fan speed control for curled overhangs (#3034)
* Update malformation distance factors (curled edge detection) * Updated curled detection logic from latest prusa 2.7 release, including updated estimate_points_properties algorithm Updated curled detection logic from latest prusa 2.7 release, including updated estimate_points_properties algorithm * Curled distance expansion const introduction * Enable overhang fan speed logic for curled edges slow downs * Reverted erroneous change
This commit is contained in:
parent
325009bc48
commit
7a8e1929ee
3 changed files with 182 additions and 152 deletions
|
@ -27,125 +27,81 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
class SlidingWindowCurvatureAccumulator
|
||||
{
|
||||
float window_size;
|
||||
float total_distance = 0; // accumulated distance
|
||||
float total_curvature = 0; // accumulated signed ccw angles
|
||||
deque<float> distances;
|
||||
deque<float> angles;
|
||||
|
||||
public:
|
||||
SlidingWindowCurvatureAccumulator(float window_size) : window_size(window_size) {}
|
||||
|
||||
void add_point(float distance, float angle)
|
||||
{
|
||||
total_distance += distance;
|
||||
total_curvature += angle;
|
||||
distances.push_back(distance);
|
||||
angles.push_back(angle);
|
||||
|
||||
while (distances.size() > 1 && total_distance > window_size) {
|
||||
total_distance -= distances.front();
|
||||
total_curvature -= angles.front();
|
||||
distances.pop_front();
|
||||
angles.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
float get_curvature() const
|
||||
{
|
||||
return total_curvature / window_size;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
total_curvature = 0;
|
||||
total_distance = 0;
|
||||
distances.clear();
|
||||
angles.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class CurvatureEstimator
|
||||
{
|
||||
static const size_t sliders_count = 3;
|
||||
SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{3.0},{9.0}, {16.0}};
|
||||
|
||||
public:
|
||||
void add_point(float distance, float angle)
|
||||
{
|
||||
if (distance < EPSILON)
|
||||
return;
|
||||
for (SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||
slider.add_point(distance, angle);
|
||||
}
|
||||
}
|
||||
float get_curvature()
|
||||
{
|
||||
float max_curvature = 0.0f;
|
||||
for (const SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||
if (abs(slider.get_curvature()) > abs(max_curvature)) {
|
||||
max_curvature = slider.get_curvature();
|
||||
}
|
||||
}
|
||||
return max_curvature;
|
||||
}
|
||||
void reset()
|
||||
{
|
||||
for (SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||
slider.reset();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ExtendedPoint
|
||||
{
|
||||
ExtendedPoint(Vec2d position, float distance = 0.0, size_t nearest_prev_layer_line = size_t(-1), float curvature = 0.0)
|
||||
: position(position), distance(distance), nearest_prev_layer_line(nearest_prev_layer_line), curvature(curvature)
|
||||
{}
|
||||
|
||||
Vec2d position;
|
||||
float distance;
|
||||
size_t nearest_prev_layer_line;
|
||||
float curvature;
|
||||
Vec2d position;
|
||||
float distance;
|
||||
float curvature;
|
||||
};
|
||||
|
||||
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename P, typename L>
|
||||
std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P> &input_points,
|
||||
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename POINTS, typename L>
|
||||
std::vector<ExtendedPoint> estimate_points_properties(const POINTS &input_points,
|
||||
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
|
||||
float flow_width,
|
||||
float max_line_length = -1.0f)
|
||||
{
|
||||
bool looped = input_points.front() == input_points.back();
|
||||
std::function<size_t(size_t,size_t)> get_prev_index = [](size_t idx, size_t count) {
|
||||
if (idx > 0) {
|
||||
return idx - 1;
|
||||
} else
|
||||
return idx;
|
||||
};
|
||||
if (looped) {
|
||||
get_prev_index = [](size_t idx, size_t count) {
|
||||
if (idx == 0)
|
||||
idx = count;
|
||||
return --idx;
|
||||
};
|
||||
};
|
||||
std::function<size_t(size_t,size_t)> get_next_index = [](size_t idx, size_t size) {
|
||||
if (idx + 1 < size) {
|
||||
return idx + 1;
|
||||
} else
|
||||
return idx;
|
||||
};
|
||||
if (looped) {
|
||||
get_next_index = [](size_t idx, size_t count) {
|
||||
if (++idx == count)
|
||||
idx = 0;
|
||||
return idx;
|
||||
};
|
||||
};
|
||||
|
||||
using P = typename POINTS::value_type;
|
||||
|
||||
using AABBScalar = typename AABBTreeLines::LinesDistancer<L>::Scalar;
|
||||
if (input_points.empty())
|
||||
return {};
|
||||
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
|
||||
CurvatureEstimator cestim;
|
||||
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
|
||||
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
|
||||
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
|
||||
|
||||
std::vector<ExtendedPoint> points;
|
||||
points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
|
||||
|
||||
{
|
||||
ExtendedPoint start_point{maybe_unscale(input_points.front())};
|
||||
auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
|
||||
start_point.distance = distance + boundary_offset;
|
||||
start_point.nearest_prev_layer_line = nearest_line;
|
||||
auto [distance, nearest_line,
|
||||
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
|
||||
start_point.distance = distance + boundary_offset;
|
||||
points.push_back(start_point);
|
||||
}
|
||||
for (size_t i = 1; i < input_points.size(); i++) {
|
||||
ExtendedPoint next_point{maybe_unscale(input_points[i])};
|
||||
auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
|
||||
next_point.distance = distance + boundary_offset;
|
||||
next_point.nearest_prev_layer_line = nearest_line;
|
||||
auto [distance, nearest_line,
|
||||
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
|
||||
next_point.distance = distance + boundary_offset;
|
||||
|
||||
if (ADD_INTERSECTIONS &&
|
||||
((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) {
|
||||
const ExtendedPoint &prev_point = points.back();
|
||||
auto intersections = unscaled_prev_layer.template intersections_with_line<true>(L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()});
|
||||
const ExtendedPoint &prev_point = points.back();
|
||||
auto intersections = unscaled_prev_layer.template intersections_with_line<true>(
|
||||
L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()});
|
||||
for (const auto &intersection : intersections) {
|
||||
points.emplace_back(intersection.first.template cast<double>(), boundary_offset, intersection.second);
|
||||
ExtendedPoint p{};
|
||||
p.position = intersection.first.template cast<double>();
|
||||
p.distance = boundary_offset;
|
||||
points.push_back(p);
|
||||
}
|
||||
}
|
||||
points.push_back(next_point);
|
||||
|
@ -153,41 +109,49 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
|
|||
|
||||
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
|
||||
std::vector<ExtendedPoint> new_points;
|
||||
new_points.reserve(points.size()*2);
|
||||
new_points.reserve(points.size() * 2);
|
||||
new_points.push_back(points.front());
|
||||
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
||||
const ExtendedPoint &curr = points[point_idx];
|
||||
const ExtendedPoint &next = points[point_idx + 1];
|
||||
|
||||
if ((curr.distance > 0 && curr.distance < boundary_offset + 2.0f) ||
|
||||
(next.distance > 0 && next.distance < boundary_offset + 2.0f)) {
|
||||
if ((curr.distance > -boundary_offset && curr.distance < boundary_offset + 2.0f) ||
|
||||
(next.distance > -boundary_offset && next.distance < boundary_offset + 2.0f)) {
|
||||
double line_len = (next.position - curr.position).norm();
|
||||
if (line_len > 4.0f) {
|
||||
double a0 = std::clamp((curr.distance + 2 * boundary_offset) / line_len, 0.0, 1.0);
|
||||
double a1 = std::clamp(1.0f - (next.distance + 2 * boundary_offset) / line_len, 0.0, 1.0);
|
||||
double a0 = std::clamp((curr.distance + 3 * boundary_offset) / line_len, 0.0, 1.0);
|
||||
double a1 = std::clamp(1.0f - (next.distance + 3 * boundary_offset) / line_len, 0.0, 1.0);
|
||||
double t0 = std::min(a0, a1);
|
||||
double t1 = std::max(a0, a1);
|
||||
|
||||
if (t0 < 1.0) {
|
||||
auto p0 = curr.position + t0 * (next.position - curr.position);
|
||||
auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p0.cast<AABBScalar>());
|
||||
new_points.push_back(ExtendedPoint{p0, float(p0_dist + boundary_offset), p0_near_l});
|
||||
auto p0 = curr.position + t0 * (next.position - curr.position);
|
||||
auto [p0_dist, p0_near_l,
|
||||
p0_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p0.cast<AABBScalar>());
|
||||
ExtendedPoint new_p{};
|
||||
new_p.position = p0;
|
||||
new_p.distance = float(p0_dist + boundary_offset);
|
||||
new_points.push_back(new_p);
|
||||
}
|
||||
if (t1 > 0.0) {
|
||||
auto p1 = curr.position + t1 * (next.position - curr.position);
|
||||
auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p1.cast<AABBScalar>());
|
||||
new_points.push_back(ExtendedPoint{p1, float(p1_dist + boundary_offset), p1_near_l});
|
||||
auto p1 = curr.position + t1 * (next.position - curr.position);
|
||||
auto [p1_dist, p1_near_l,
|
||||
p1_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p1.cast<AABBScalar>());
|
||||
ExtendedPoint new_p{};
|
||||
new_p.position = p1;
|
||||
new_p.distance = float(p1_dist + boundary_offset);
|
||||
new_points.push_back(new_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
new_points.push_back(next);
|
||||
}
|
||||
points = new_points;
|
||||
points = std::move(new_points);
|
||||
}
|
||||
|
||||
if (max_line_length > 0) {
|
||||
std::vector<ExtendedPoint> new_points;
|
||||
new_points.reserve(points.size()*2);
|
||||
new_points.reserve(points.size() * 2);
|
||||
{
|
||||
for (size_t i = 0; i + 1 < points.size(); i++) {
|
||||
const ExtendedPoint &curr = points[i];
|
||||
|
@ -200,39 +164,79 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
|
|||
Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t);
|
||||
auto [p_dist, p_near_l,
|
||||
p_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(pos.cast<AABBScalar>());
|
||||
new_points.push_back(ExtendedPoint{pos, float(p_dist + boundary_offset), p_near_l});
|
||||
ExtendedPoint new_p{};
|
||||
new_p.position = pos;
|
||||
new_p.distance = float(p_dist + boundary_offset);
|
||||
new_points.push_back(new_p);
|
||||
}
|
||||
}
|
||||
new_points.push_back(points.back());
|
||||
}
|
||||
points = new_points;
|
||||
points = std::move(new_points);
|
||||
}
|
||||
|
||||
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
|
||||
ExtendedPoint &a = points[point_idx];
|
||||
ExtendedPoint &prev = points[point_idx > 0 ? point_idx - 1 : point_idx];
|
||||
float accumulated_distance = 0;
|
||||
std::vector<float> distances_for_curvature(points.size());
|
||||
for (size_t point_idx = 0; point_idx < points.size(); ++point_idx) {
|
||||
const ExtendedPoint &a = points[point_idx];
|
||||
const ExtendedPoint &b = points[get_prev_index(point_idx, points.size())];
|
||||
|
||||
int prev_point_idx = point_idx;
|
||||
while (prev_point_idx > 0) {
|
||||
prev_point_idx--;
|
||||
if ((a.position - points[prev_point_idx].position).squaredNorm() > EPSILON) { break; }
|
||||
}
|
||||
|
||||
int next_point_index = point_idx;
|
||||
while (next_point_index < int(points.size()) - 1) {
|
||||
next_point_index++;
|
||||
if ((a.position - points[next_point_index].position).squaredNorm() > EPSILON) { break; }
|
||||
}
|
||||
|
||||
if (prev_point_idx != point_idx && next_point_index != point_idx) {
|
||||
float distance = (prev.position - a.position).norm();
|
||||
float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position);
|
||||
cestim.add_point(distance, alfa);
|
||||
}
|
||||
|
||||
a.curvature = cestim.get_curvature();
|
||||
distances_for_curvature[point_idx] = (b.position - a.position).norm();
|
||||
accumulated_distance += distances_for_curvature[point_idx];
|
||||
}
|
||||
|
||||
if (accumulated_distance > EPSILON)
|
||||
for (float window_size : {3.0f, 9.0f, 16.0f}) {
|
||||
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
|
||||
ExtendedPoint ¤t = points[point_idx];
|
||||
|
||||
Vec2d back_position = current.position;
|
||||
{
|
||||
size_t back_point_index = point_idx;
|
||||
float dist_backwards = 0;
|
||||
while (dist_backwards < window_size * 0.5 && back_point_index != get_prev_index(back_point_index, points.size())) {
|
||||
float line_dist = distances_for_curvature[get_prev_index(back_point_index, points.size())];
|
||||
if (dist_backwards + line_dist > window_size * 0.5) {
|
||||
back_position = points[back_point_index].position +
|
||||
(window_size * 0.5 - dist_backwards) *
|
||||
(points[get_prev_index(back_point_index, points.size())].position -
|
||||
points[back_point_index].position)
|
||||
.normalized();
|
||||
dist_backwards += window_size * 0.5 - dist_backwards + EPSILON;
|
||||
} else {
|
||||
dist_backwards += line_dist;
|
||||
back_point_index = get_prev_index(back_point_index, points.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec2d front_position = current.position;
|
||||
{
|
||||
size_t front_point_index = point_idx;
|
||||
float dist_forwards = 0;
|
||||
while (dist_forwards < window_size * 0.5 && front_point_index != get_next_index(front_point_index, points.size())) {
|
||||
float line_dist = distances_for_curvature[front_point_index];
|
||||
if (dist_forwards + line_dist > window_size * 0.5) {
|
||||
front_position = points[front_point_index].position +
|
||||
(window_size * 0.5 - dist_forwards) *
|
||||
(points[get_next_index(front_point_index, points.size())].position -
|
||||
points[front_point_index].position)
|
||||
.normalized();
|
||||
dist_forwards += window_size * 0.5 - dist_forwards + EPSILON;
|
||||
} else {
|
||||
dist_forwards += line_dist;
|
||||
front_point_index = get_next_index(front_point_index, points.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float new_curvature = angle(current.position - back_position, front_position - current.position) / window_size;
|
||||
if (abs(current.curvature) < abs(new_curvature)) {
|
||||
current.curvature = new_curvature;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
|
@ -377,11 +381,11 @@ public:
|
|||
|
||||
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
||||
if(slowdown_for_curled_edges) {
|
||||
float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
|
||||
float curled_speed = calculate_speed(artificial_distance_to_curled_lines);
|
||||
extrusion_speed = std::min(curled_speed, extrusion_speed); // adjust extrusion speed based on what is smallest - the calculated overhang speed or the artificial curled speed
|
||||
}
|
||||
|
||||
float overlap = std::min(1 - curr.distance * width_inv, 1 - next.distance * width_inv);
|
||||
float overlap = std::min(1 - (curr.distance+artificial_distance_to_curled_lines) * width_inv, 1 - (next.distance+artificial_distance_to_curled_lines) * width_inv);
|
||||
|
||||
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue