added curvature, fixed bugs, improved point placement
This commit is contained in:
parent
338d4f4a1e
commit
73f3b15507
2 changed files with 65 additions and 19 deletions
|
@ -2705,6 +2705,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::s
|
|||
|
||||
std::string GCode::extrude_entity(const ExtrusionEntity &entity, const std::string_view description, double speed)
|
||||
{
|
||||
m_extrusion_quality_estimator.reset_for_next_extrusion();
|
||||
if (const ExtrusionPath* path = dynamic_cast<const ExtrusionPath*>(&entity))
|
||||
return this->extrude_path(*path, description, speed);
|
||||
else if (const ExtrusionMultiPath* multipath = dynamic_cast<const ExtrusionMultiPath*>(&entity))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../BoundingBox.hpp"
|
||||
#include "../Polygon.hpp"
|
||||
#include "../ClipperUtils.hpp"
|
||||
#include "../Flow.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
@ -96,8 +97,11 @@ class ExtrusionQualityEstimator
|
|||
{
|
||||
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary;
|
||||
AABBTreeLines::LinesDistancer<Linef> next_layer_boundary;
|
||||
CurvatureEstimator cestim;
|
||||
|
||||
public:
|
||||
void reset_for_next_extrusion() { cestim.reset(); }
|
||||
|
||||
void prepare_for_new_layer(const std::vector<const Layer *> &layers)
|
||||
{
|
||||
std::vector<Linef> layer_lines;
|
||||
|
@ -157,49 +161,90 @@ public:
|
|||
float quality;
|
||||
};
|
||||
|
||||
float flow_width = path.width;
|
||||
float min_malformation_dist = 0.2;
|
||||
float peak_malformation_dist = 0.5;
|
||||
float flow_width = path.width;
|
||||
float min_malformation_dist = 0.1;
|
||||
float peak_malformation_dist = 1.0;
|
||||
|
||||
const Points &original_points = path.polyline.points;
|
||||
std::vector<ExtendedPoint> points;
|
||||
|
||||
float distance = prev_layer_boundary.signed_distance_from_lines(unscaled(original_points[0])) / flow_width + flow_width * 0.5f;
|
||||
float distance = prev_layer_boundary.signed_distance_from_lines(unscaled(original_points[0])) / flow_width + 0.5 * flow_width;
|
||||
points.push_back({unscaled(original_points[0]), distance, 1.0f});
|
||||
for (size_t i = 1; i < original_points.size(); i++) {
|
||||
Vec2d next_point_pos = unscaled(original_points[i]);
|
||||
float distance_of_next = prev_layer_boundary.signed_distance_from_lines(next_point_pos) / flow_width + flow_width * 0.5f;
|
||||
// if ((points.back().distance > min_malformation_dist) !=
|
||||
// (distance_of_next > min_malformation_dist)) { // not same sign, so one is grounded, one not
|
||||
if (true) {
|
||||
float distance_of_next = prev_layer_boundary.signed_distance_from_lines(next_point_pos) / flow_width + 0.5 * flow_width;
|
||||
if (points.back().distance < min_malformation_dist != distance_of_next < min_malformation_dist) { // one in air, one not
|
||||
auto intersections = prev_layer_boundary.intersections_with_line<true>({points.back().position, next_point_pos});
|
||||
for (const auto &intersection : intersections) { points.push_back({intersection, 0.0f, 1.0}); }
|
||||
points.push_back({next_point_pos, distance_of_next, 1.0});
|
||||
}
|
||||
|
||||
if (points.back().distance > min_malformation_dist && distance_of_next > min_malformation_dist) { // both in air
|
||||
double line_len = (points.back().position - next_point_pos).norm();
|
||||
if (line_len > 3.0) {
|
||||
double a0 = std::clamp((0.5 * flow_width + points.back().distance) / line_len, 0.0, 1.0);
|
||||
double a1 = std::clamp((0.5 * flow_width + distance_of_next) / line_len, 0.0, 1.0);
|
||||
double t0 = std::min(a0, a1);
|
||||
double t1 = std::max(a0, a1);
|
||||
|
||||
auto p0 = points.back().position + t0 * (next_point_pos - points.back().position);
|
||||
auto p0_dist = prev_layer_boundary.signed_distance_from_lines(p0) / flow_width + 0.5 * flow_width;
|
||||
points.push_back({p0, float(p0_dist), 1.0});
|
||||
auto p1 = points.back().position + t1 * (next_point_pos - points.back().position);
|
||||
auto p1_dist = prev_layer_boundary.signed_distance_from_lines(p1) / flow_width + 0.5 * flow_width;
|
||||
points.push_back({p1, float(p1_dist), 1.0});
|
||||
}
|
||||
}
|
||||
|
||||
points.push_back({next_point_pos, distance_of_next, 1.0});
|
||||
}
|
||||
|
||||
for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) {
|
||||
ExtendedPoint &a = points[point_idx];
|
||||
ExtendedPoint &b = points[point_idx + 1];
|
||||
if (b.distance < min_malformation_dist) {
|
||||
a.quality = 1.0;
|
||||
|
||||
float distance = std::min(a.distance, b.distance);
|
||||
|
||||
int prev_point_idx = point_idx;
|
||||
while (prev_point_idx > 0) {
|
||||
prev_point_idx--;
|
||||
if ((b.position - points[prev_point_idx].position).squaredNorm() > EPSILON) { break; }
|
||||
}
|
||||
if (b.distance < peak_malformation_dist) {
|
||||
a.quality = 1.0 - (distance - min_malformation_dist) / (peak_malformation_dist - min_malformation_dist);
|
||||
|
||||
int next_point_index = point_idx;
|
||||
while (next_point_index < int(points.size()) - 1) {
|
||||
next_point_index++;
|
||||
if ((b.position - points[next_point_index].position).squaredNorm() > EPSILON) { break; }
|
||||
}
|
||||
|
||||
if (prev_point_idx != point_idx && next_point_index != point_idx) {
|
||||
float distance = (b.position - a.position).norm();
|
||||
float alfa = angle(b.position - points[prev_point_idx].position, points[next_point_index].position - b.position);
|
||||
cestim.add_point(distance, alfa);
|
||||
}
|
||||
|
||||
if (distance < min_malformation_dist) {
|
||||
a.quality = 1.0;
|
||||
cestim.reset();
|
||||
} else if (distance < peak_malformation_dist) {
|
||||
a.quality = 1.0 - (distance - min_malformation_dist) / (peak_malformation_dist - min_malformation_dist);
|
||||
float curvature_penalty = 0.0f;
|
||||
float curvature = std::abs(cestim.get_curvature());
|
||||
if (curvature > 1.0f) {
|
||||
curvature_penalty = 1.0f;
|
||||
} else if (curvature > 0.1f) {
|
||||
curvature_penalty = fmin(1.0, distance - min_malformation_dist) * curvature;
|
||||
}
|
||||
|
||||
a.quality -= curvature_penalty;
|
||||
} else {
|
||||
a.quality = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// if (points.size() >= 3) {
|
||||
// points[0].quality = points[1].quality;
|
||||
// points[points.size()-2].quality = points[points.size()-3].quality;
|
||||
// }
|
||||
|
||||
std::vector<ProcessedPoint> result;
|
||||
result.reserve(points.size());
|
||||
for (const ExtendedPoint &p : points) {
|
||||
result.push_back({Point::new_scale(p.position), p.quality}); }
|
||||
for (const ExtendedPoint &p : points) { result.push_back({Point::new_scale(p.position), std::clamp(p.quality, 0.0f, 1.0f)}); }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue