mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-06 22:47:32 -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 {
|
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
|
struct ExtendedPoint
|
||||||
{
|
{
|
||||||
ExtendedPoint(Vec2d position, float distance = 0.0, size_t nearest_prev_layer_line = size_t(-1), float curvature = 0.0)
|
Vec2d position;
|
||||||
: position(position), distance(distance), nearest_prev_layer_line(nearest_prev_layer_line), curvature(curvature)
|
float distance;
|
||||||
{}
|
float curvature;
|
||||||
|
|
||||||
Vec2d position;
|
|
||||||
float distance;
|
|
||||||
size_t nearest_prev_layer_line;
|
|
||||||
float curvature;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename P, typename L>
|
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 std::vector<P> &input_points,
|
std::vector<ExtendedPoint> estimate_points_properties(const POINTS &input_points,
|
||||||
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
|
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
|
||||||
float flow_width,
|
float flow_width,
|
||||||
float max_line_length = -1.0f)
|
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;
|
using AABBScalar = typename AABBTreeLines::LinesDistancer<L>::Scalar;
|
||||||
if (input_points.empty())
|
if (input_points.empty())
|
||||||
return {};
|
return {};
|
||||||
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
|
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>(); };
|
||||||
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
|
|
||||||
|
|
||||||
std::vector<ExtendedPoint> points;
|
std::vector<ExtendedPoint> points;
|
||||||
points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
|
points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
|
||||||
|
|
||||||
{
|
{
|
||||||
ExtendedPoint start_point{maybe_unscale(input_points.front())};
|
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>());
|
auto [distance, nearest_line,
|
||||||
start_point.distance = distance + boundary_offset;
|
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
|
||||||
start_point.nearest_prev_layer_line = nearest_line;
|
start_point.distance = distance + boundary_offset;
|
||||||
points.push_back(start_point);
|
points.push_back(start_point);
|
||||||
}
|
}
|
||||||
for (size_t i = 1; i < input_points.size(); i++) {
|
for (size_t i = 1; i < input_points.size(); i++) {
|
||||||
ExtendedPoint next_point{maybe_unscale(input_points[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>());
|
auto [distance, nearest_line,
|
||||||
next_point.distance = distance + boundary_offset;
|
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
|
||||||
next_point.nearest_prev_layer_line = nearest_line;
|
next_point.distance = distance + boundary_offset;
|
||||||
|
|
||||||
if (ADD_INTERSECTIONS &&
|
if (ADD_INTERSECTIONS &&
|
||||||
((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) {
|
((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) {
|
||||||
const ExtendedPoint &prev_point = points.back();
|
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>()});
|
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) {
|
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);
|
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) {
|
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
|
||||||
std::vector<ExtendedPoint> new_points;
|
std::vector<ExtendedPoint> new_points;
|
||||||
new_points.reserve(points.size()*2);
|
new_points.reserve(points.size() * 2);
|
||||||
new_points.push_back(points.front());
|
new_points.push_back(points.front());
|
||||||
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
||||||
const ExtendedPoint &curr = points[point_idx];
|
const ExtendedPoint &curr = points[point_idx];
|
||||||
const ExtendedPoint &next = points[point_idx + 1];
|
const ExtendedPoint &next = points[point_idx + 1];
|
||||||
|
|
||||||
if ((curr.distance > 0 && curr.distance < boundary_offset + 2.0f) ||
|
if ((curr.distance > -boundary_offset && curr.distance < boundary_offset + 2.0f) ||
|
||||||
(next.distance > 0 && next.distance < boundary_offset + 2.0f)) {
|
(next.distance > -boundary_offset && next.distance < boundary_offset + 2.0f)) {
|
||||||
double line_len = (next.position - curr.position).norm();
|
double line_len = (next.position - curr.position).norm();
|
||||||
if (line_len > 4.0f) {
|
if (line_len > 4.0f) {
|
||||||
double a0 = std::clamp((curr.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 + 2 * 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 t0 = std::min(a0, a1);
|
||||||
double t1 = std::max(a0, a1);
|
double t1 = std::max(a0, a1);
|
||||||
|
|
||||||
if (t0 < 1.0) {
|
if (t0 < 1.0) {
|
||||||
auto p0 = curr.position + t0 * (next.position - curr.position);
|
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>());
|
auto [p0_dist, p0_near_l,
|
||||||
new_points.push_back(ExtendedPoint{p0, float(p0_dist + boundary_offset), 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) {
|
if (t1 > 0.0) {
|
||||||
auto p1 = curr.position + t1 * (next.position - curr.position);
|
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>());
|
auto [p1_dist, p1_near_l,
|
||||||
new_points.push_back(ExtendedPoint{p1, float(p1_dist + boundary_offset), 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);
|
new_points.push_back(next);
|
||||||
}
|
}
|
||||||
points = new_points;
|
points = std::move(new_points);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max_line_length > 0) {
|
if (max_line_length > 0) {
|
||||||
std::vector<ExtendedPoint> new_points;
|
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++) {
|
for (size_t i = 0; i + 1 < points.size(); i++) {
|
||||||
const ExtendedPoint &curr = points[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);
|
Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t);
|
||||||
auto [p_dist, p_near_l,
|
auto [p_dist, p_near_l,
|
||||||
p_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(pos.cast<AABBScalar>());
|
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());
|
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) {
|
float accumulated_distance = 0;
|
||||||
ExtendedPoint &a = points[point_idx];
|
std::vector<float> distances_for_curvature(points.size());
|
||||||
ExtendedPoint &prev = points[point_idx > 0 ? point_idx - 1 : point_idx];
|
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;
|
distances_for_curvature[point_idx] = (b.position - a.position).norm();
|
||||||
while (prev_point_idx > 0) {
|
accumulated_distance += distances_for_curvature[point_idx];
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +381,11 @@ public:
|
||||||
|
|
||||||
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
float extrusion_speed = std::min(calculate_speed(curr.distance), calculate_speed(next.distance));
|
||||||
if(slowdown_for_curled_edges) {
|
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
|
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 });
|
processed_points.push_back({ scaled(curr.position), extrusion_speed, overlap });
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,15 +105,10 @@ float estimate_curled_up_height(
|
||||||
float curled_up_height = 0;
|
float curled_up_height = 0;
|
||||||
if (fabs(distance) < 3.0 * flow_width) {
|
if (fabs(distance) < 3.0 * flow_width) {
|
||||||
curled_up_height = std::max(prev_line_curled_height - layer_height * 0.75f, 0.0f);
|
curled_up_height = std::max(prev_line_curled_height - layer_height * 0.75f, 0.0f);
|
||||||
//printf("If 1 %d\n",curled_up_height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("distance %f, params.malformation_distance_factors.first %f, params.malformation_distance_factors.second %f, flow_width %f\n", distance, params.malformation_distance_factors.first, params.malformation_distance_factors.second, flow_width);
|
|
||||||
//printf("distance %f,params.malformation_distance_factors.first * flow_width %f, params.malformation_distance_factors.second * flow_width %f\n", distance, params.malformation_distance_factors.first * flow_width, params.malformation_distance_factors.second * flow_width);
|
|
||||||
|
|
||||||
if (distance > params.malformation_distance_factors.first * flow_width &&
|
if (distance > params.malformation_distance_factors.first * flow_width &&
|
||||||
distance < params.malformation_distance_factors.second * flow_width) {
|
distance < params.malformation_distance_factors.second * flow_width) {
|
||||||
|
|
||||||
// imagine the extrusion profile. The part that has been glued (melted) with the previous layer will be called anchored section
|
// imagine the extrusion profile. The part that has been glued (melted) with the previous layer will be called anchored section
|
||||||
// and the rest will be called curling section
|
// and the rest will be called curling section
|
||||||
// float anchored_section = flow_width - point.distance;
|
// float anchored_section = flow_width - point.distance;
|
||||||
|
@ -145,49 +140,79 @@ float estimate_curled_up_height(
|
||||||
|
|
||||||
void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
||||||
{
|
{
|
||||||
LD prev_layer_lines{};
|
#ifdef DEBUG_FILES
|
||||||
for (Layer *l : layers) {
|
FILE *debug_file = boost::nowide::fopen(debug_out_path("object_malformations.obj").c_str(), "w");
|
||||||
|
FILE *full_file = boost::nowide::fopen(debug_out_path("object_full.obj").c_str(), "w");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LD prev_layer_lines{};
|
||||||
|
|
||||||
|
for (Layer *l : layers) {
|
||||||
l->curled_lines.clear();
|
l->curled_lines.clear();
|
||||||
std::vector<Linef> boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector<Linef>();
|
std::vector<Linef> boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector<Linef>();
|
||||||
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
||||||
std::vector<ExtrusionLine> current_layer_lines;
|
std::vector<ExtrusionLine> current_layer_lines;
|
||||||
for (const LayerRegion *layer_region : l->regions()) {
|
for (const LayerRegion *layer_region : l->regions()) {
|
||||||
for (const ExtrusionEntity *extrusion : layer_region->perimeters.flatten().entities) {
|
for (const ExtrusionEntity *extrusion : layer_region->perimeters.flatten().entities) {
|
||||||
if (extrusion->role() != Slic3r::erExternalPerimeter)
|
if (extrusion->role() != Slic3r::erExternalPerimeter)
|
||||||
continue;
|
continue;
|
||||||
Points extrusion_pts;
|
|
||||||
|
Points extrusion_pts;
|
||||||
extrusion->collect_points(extrusion_pts);
|
extrusion->collect_points(extrusion_pts);
|
||||||
float flow_width = get_flow_width(layer_region, extrusion->role());
|
float flow_width = get_flow_width(layer_region, extrusion->role());
|
||||||
auto annotated_points = estimate_points_properties<true, true, false, false>(extrusion_pts, prev_layer_lines, flow_width,
|
auto annotated_points = estimate_points_properties<true, true, false, false>(extrusion_pts,
|
||||||
params.bridge_distance);
|
prev_layer_lines,
|
||||||
|
flow_width,
|
||||||
|
params.bridge_distance);
|
||||||
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
||||||
const ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
|
const ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
|
||||||
const ExtendedPoint &b = annotated_points[i];
|
const ExtendedPoint &b = annotated_points[i];
|
||||||
ExtrusionLine line_out{a.position.cast<float>(), b.position.cast<float>(), float((a.position - b.position).norm()),
|
ExtrusionLine line_out{a.position.cast<float>(), b.position.cast<float>(), float((a.position - b.position).norm()),
|
||||||
extrusion};
|
extrusion};
|
||||||
|
|
||||||
Vec2f middle = 0.5 * (line_out.a + line_out.b);
|
Vec2f middle = 0.5 * (line_out.a + line_out.b);
|
||||||
auto [middle_distance, bottom_line_idx, x] = prev_layer_lines.distance_from_lines_extra<false>(middle);
|
auto [middle_distance, bottom_line_idx, x] = prev_layer_lines.distance_from_lines_extra<false>(middle);
|
||||||
ExtrusionLine bottom_line = prev_layer_lines.get_lines().empty() ? ExtrusionLine{} :
|
ExtrusionLine bottom_line = prev_layer_lines.get_lines().empty() ? ExtrusionLine{} :
|
||||||
prev_layer_lines.get_line(bottom_line_idx);
|
prev_layer_lines.get_line(bottom_line_idx);
|
||||||
|
|
||||||
// correctify the distance sign using slice polygons
|
// correctify the distance sign using slice polygons
|
||||||
float sign = (prev_layer_boundary.distance_from_lines<true>(middle.cast<double>()) + 0.5f * flow_width) < 0.0f ? -1.0f : 1.0f;
|
float sign = (prev_layer_boundary.distance_from_lines<true>(middle.cast<double>()) + 0.5f * flow_width) < 0.0f ? -1.0f :
|
||||||
|
1.0f;
|
||||||
|
|
||||||
line_out.curled_up_height = estimate_curled_up_height(middle_distance * sign, 0.5 * (a.curvature + b.curvature),
|
line_out.curled_up_height = estimate_curled_up_height(middle_distance * sign * params.curled_distance_expansion, 0.5 * (a.curvature + b.curvature),
|
||||||
l->height, flow_width, bottom_line.curled_up_height, params);
|
l->height, flow_width, bottom_line.curled_up_height, params);
|
||||||
|
|
||||||
current_layer_lines.push_back(line_out);
|
current_layer_lines.push_back(line_out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const ExtrusionLine &line : current_layer_lines) {
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
if (line.curled_up_height > params.curling_tolerance_limit) {
|
if (line.curled_up_height > params.curling_tolerance_limit) {
|
||||||
l->curled_lines.push_back(CurledLine{Point::new_scale(line.a), Point::new_scale(line.b), line.curled_up_height});
|
l->curled_lines.push_back(CurledLine{Point::new_scale(line.a), Point::new_scale(line.b), line.curled_up_height});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_FILES
|
||||||
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
|
if (line.curled_up_height > params.curling_tolerance_limit) {
|
||||||
|
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height);
|
||||||
|
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
|
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height);
|
||||||
|
fprintf(full_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
prev_layer_lines = LD{current_layer_lines};
|
prev_layer_lines = LD{current_layer_lines};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_FILES
|
||||||
|
fclose(debug_file);
|
||||||
|
fclose(full_file);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -43,8 +43,9 @@ struct Params
|
||||||
BrimType brim_type;
|
BrimType brim_type;
|
||||||
const float brim_width;
|
const float brim_width;
|
||||||
|
|
||||||
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.33, 0.7 };
|
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.2, 1.1 };
|
||||||
const float max_curled_height_factor = 10.0f;
|
const float max_curled_height_factor = 10.0f;
|
||||||
|
const float curled_distance_expansion = 1.0f; // controls the spread of the area where slow down for curled overhangs is applied
|
||||||
const float curling_tolerance_limit = 0.1f;
|
const float curling_tolerance_limit = 0.1f;
|
||||||
|
|
||||||
const float min_distance_between_support_points = 3.0f; //mm
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue