Center estiamted curvature values,

Center esimtated curling - transfering data by nearest line caused CCW or CW shift, based on which point of the current line was used. By switching the points on layer basis, this problem disapeared
This commit is contained in:
PavelMikus 2023-04-11 16:40:14 +02:00 committed by Pavel Mikuš
parent da6b972a79
commit aa0e21eed1
2 changed files with 77 additions and 110 deletions

View File

@ -27,78 +27,6 @@
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] = {{1.0},{4.0}, {10.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
{
Vec2d position;
@ -118,7 +46,6 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
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>(); };
std::vector<ExtendedPoint> points;
@ -227,6 +154,9 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
points = new_points;
}
std::vector<float> angles_for_curvature(points.size());
std::vector<float> distances_for_curvature(points.size());
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];
@ -234,22 +164,59 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
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; }
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 ((a.position - points[next_point_index].position).squaredNorm() > EPSILON) {
break;
}
}
distances_for_curvature[point_idx] = (prev.position - a.position).norm();
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);
}
float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position);
angles_for_curvature[point_idx] = alfa;
} // else keep zero
}
a.curvature = cestim.get_curvature();
for (float window_size : {3.0f, 9.0f, 16.0f}) {
size_t tail_point = 0;
float tail_window_acc = 0;
float tail_angle_acc = 0;
size_t head_point = 0;
float head_window_acc = 0;
float head_angle_acc = 0;
for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) {
if (point_idx > 0) {
tail_window_acc += distances_for_curvature[point_idx - 1];
tail_angle_acc += angles_for_curvature[point_idx - 1];
head_window_acc -= distances_for_curvature[point_idx - 1];
head_angle_acc -= angles_for_curvature[point_idx - 1];
}
while (tail_window_acc > window_size * 0.5 && tail_point < point_idx) {
tail_window_acc -= distances_for_curvature[tail_point];
tail_angle_acc -= angles_for_curvature[tail_point];
tail_point++;
}
while (head_window_acc < window_size * 0.5 && head_point < int(points.size()) - 1) {
head_window_acc += distances_for_curvature[head_point];
head_angle_acc += angles_for_curvature[head_point];
head_point++;
}
float curvature = (tail_angle_acc + head_angle_acc) / (tail_window_acc + head_window_acc);
if (std::abs(curvature) > std::abs(points[point_idx].curvature)) {
points[point_idx].curvature = curvature;
}
}
}
return points;

View File

@ -234,7 +234,7 @@ float estimate_curled_up_height(
// faster or slower than thin air, thus the extrusion always curles up)
if (point.curvature > 0.01){
float radius = std::max(1.0 / point.curvature - flow_width / 2.0, 0.001);
float radius = (1.0 / point.curvature);
float curling_t = sqrt(radius / 100);
float b = curling_t * flow_width;
float a = curling_section;
@ -397,8 +397,8 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
bridged_distance = 0.0f;
}
line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width,
prev_layer_curling, params);
line_out.curled_up_height = estimate_curled_up_height(layer_region->layer()->id() % 2 == 0 ? curr_point : prev_point,
layer_region->layer()->height, flow_width, prev_layer_curling, params);
lines_out.push_back(line_out);
}
@ -1102,25 +1102,25 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width,
auto annotated_points = estimate_points_properties<true, true, false, false>(pol.points, prev_layer_lines, flow_width);
for (size_t i = 0; i < annotated_points.size(); ++i) {
ExtendedPoint &curr_point = annotated_points[i];
float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
curr_point.position.cast<float>(), line_len, extrusion};
ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
ExtendedPoint &b = annotated_points[i];
ExtrusionLine line_out{a.position.cast<float>(), b.position.cast<float>(), float((a.position - b.position).norm()),
extrusion};
auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, curr_point);
const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
ExtrusionLine{};
ExtendedPoint &pivot = l->id() % 2 == 0 ? a : b;
auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, pivot);
const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
prev_layer_lines.get_line(pivot.nearest_prev_layer_line) :
ExtrusionLine{};
Vec2f v1 = (nearest_prev_layer_line.b - nearest_prev_layer_line.a);
Vec2f v2 = (curr_point.position.cast<float>() - nearest_prev_layer_line.a);
Vec2f v2 = (pivot.position.cast<float>() - nearest_prev_layer_line.a);
auto d = (v1.x() * v2.y()) - (v1.y() * v2.x());
if (d > 0) {
curr_point.distance *= -1.0f;
pivot.distance *= -1.0f;
}
line_out.curled_up_height = estimate_curled_up_height(curr_point, l->height, flow_width,
prev_layer_curling, params);
line_out.curled_up_height = estimate_curled_up_height(pivot, l->height, flow_width, prev_layer_curling, params);
current_layer_lines.push_back(line_out);
}
@ -1158,7 +1158,7 @@ void estimate_malformations(LayerPtrs &layers, const Params &params)
{
#ifdef DEBUG_FILES
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");
FILE *full_file = boost::nowide::fopen(debug_out_path("object_full.obj").c_str(), "w");
#endif
LD prev_layer_lines{};
@ -1170,8 +1170,8 @@ void estimate_malformations(LayerPtrs &layers, const Params &params)
std::vector<ExtrusionLine> current_layer_lines;
for (const LayerRegion *layer_region : l->regions()) {
for (const ExtrusionEntity *extrusion : layer_region->perimeters().flatten().entities) {
if (!extrusion->role().is_external_perimeter()) continue;
if (!extrusion->role().is_external_perimeter())
continue;
Points extrusion_pts;
extrusion->collect_points(extrusion_pts);
@ -1179,18 +1179,18 @@ void estimate_malformations(LayerPtrs &layers, const Params &params)
auto annotated_points = estimate_points_properties<true, false, false, false>(extrusion_pts, prev_layer_lines, flow_width,
params.bridge_distance);
for (size_t i = 0; i < annotated_points.size(); ++i) {
ExtendedPoint &curr_point = annotated_points[i];
float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f;
ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
curr_point.position.cast<float>(), line_len, extrusion};
ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
ExtendedPoint &b = annotated_points[i];
ExtrusionLine line_out{a.position.cast<float>(), b.position.cast<float>(), float((a.position - b.position).norm()),
extrusion};
auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, curr_point);
ExtendedPoint &pivot = l->id() % 2 == 0 ? a : b;
auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, pivot);
float sign = (prev_layer_boundary.distance_from_lines<true>(curr_point.position) + 0.5f * flow_width) < 0.0f ? -1.0f :
1.0f;
curr_point.distance *= sign;
float sign = (prev_layer_boundary.distance_from_lines<true>(pivot.position) + 0.5f * flow_width) < 0.0f ? -1.0f : 1.0f;
pivot.distance *= sign;
line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width,
line_out.curled_up_height = estimate_curled_up_height(pivot, layer_region->layer()->height, flow_width,
prev_layer_curling, params);
current_layer_lines.push_back(line_out);
@ -1211,9 +1211,9 @@ void estimate_malformations(LayerPtrs &layers, const Params &params)
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]);
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