Fix overhang perimeter dynamic speed.

* Use "corner" intersections when estimating the curl up height.
* If there is a redundant point in an extrusion loop at the end remove it.
This commit is contained in:
Martin Šach 2024-05-21 15:31:46 +02:00 committed by Lukas Matena
parent 10c0f7f255
commit c6858d41bd
3 changed files with 79 additions and 34 deletions

View File

@ -17,8 +17,14 @@ ExtrusionPaths calculate_and_split_overhanging_extrusions(const ExtrusionPath
const AABBTreeLines::LinesDistancer<Linef> &unscaled_prev_layer, const AABBTreeLines::LinesDistancer<Linef> &unscaled_prev_layer,
const AABBTreeLines::LinesDistancer<CurledLine> &prev_layer_curled_lines) const AABBTreeLines::LinesDistancer<CurledLine> &prev_layer_curled_lines)
{ {
std::vector<ExtendedPoint> extended_points = estimate_points_properties<true, true, true, true>(path.polyline.points, ExtrusionProcessor::PropertiesEstimationConfig config{};
unscaled_prev_layer, path.width()); config.add_corners = true;
config.prev_layer_boundary_offset = true;
config.flow_width = path.width();
std::vector<ExtendedPoint> extended_points = estimate_points_properties<true>(
path.polyline.points, unscaled_prev_layer, config
);
std::vector<std::pair<float, float>> calculated_distances(extended_points.size()); std::vector<std::pair<float, float>> calculated_distances(extended_points.size());
for (size_t i = 0; i < extended_points.size(); i++) { for (size_t i = 0; i < extended_points.size(); i++) {
@ -118,9 +124,28 @@ ExtrusionEntityCollection calculate_and_split_overhanging_extrusions(const Extru
} else if (auto *loop = dynamic_cast<const ExtrusionLoop *>(e)) { } else if (auto *loop = dynamic_cast<const ExtrusionLoop *>(e)) {
ExtrusionLoop new_loop = *loop; ExtrusionLoop new_loop = *loop;
new_loop.paths.clear(); new_loop.paths.clear();
for (const ExtrusionPath &p : loop->paths) {
auto paths = calculate_and_split_overhanging_extrusions(p, unscaled_prev_layer, prev_layer_curled_lines); ExtrusionPaths paths{loop->paths};
new_loop.paths.insert(new_loop.paths.end(), paths.begin(), paths.end()); if (!paths.empty()) {
ExtrusionPath& first_path{paths.front()};
ExtrusionPath& last_path{paths.back()};
if (first_path.attributes() == last_path.attributes()) {
if (first_path.polyline.size() > 1 && last_path.polyline.size() > 2) {
const Line start{first_path.polyline.front(), *std::next(first_path.polyline.begin())};
const Line end{last_path.polyline.back(), *std::next(last_path.polyline.rbegin())};
if (std::abs(start.direction() - end.direction()) < 1e-5) {
first_path.polyline.points.front() = *std::next(last_path.polyline.points.rbegin());
last_path.polyline.points.pop_back();
}
}
}
}
for (const ExtrusionPath &p : paths) {
auto resulting_paths = calculate_and_split_overhanging_extrusions(p, unscaled_prev_layer, prev_layer_curled_lines);
new_loop.paths.insert(new_loop.paths.end(), resulting_paths.begin(), resulting_paths.end());
} }
result.append(new_loop); result.append(new_loop);
} else if (auto *mp = dynamic_cast<const ExtrusionMultiPath *>(e)) { } else if (auto *mp = dynamic_cast<const ExtrusionMultiPath *>(e)) {

View File

@ -61,13 +61,20 @@ struct OverhangSpeeds
float fan_speed; float fan_speed;
}; };
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename POINTS, typename L> struct PropertiesEstimationConfig {
std::vector<ExtendedPoint> estimate_points_properties(const POINTS &input_points, bool add_corners{};
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer, bool prev_layer_boundary_offset{};
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();
template<bool SIGNED_DISTANCE, typename POINTS, typename L>
std::vector<ExtendedPoint> estimate_points_properties(
const POINTS &input_points,
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
const PropertiesEstimationConfig &config
) {
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) { std::function<size_t(size_t,size_t)> get_prev_index = [](size_t idx, size_t count) {
if (idx > 0) { if (idx > 0) {
return idx - 1; return idx - 1;
@ -95,32 +102,28 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
}; };
}; };
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 = config.prev_layer_boundary_offset ? 0.5 * config.flow_width : 0.0f;
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() * 1.5);
{ {
ExtendedPoint start_point{maybe_unscale(input_points.front())}; ExtendedPoint start_point{unscaled(input_points.front())};
auto [distance, nearest_line, auto [distance, nearest_line,
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>()); x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(start_point.position.cast<AABBScalar>());
start_point.distance = distance + boundary_offset; 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{unscaled(input_points[i])};
auto [distance, nearest_line, auto [distance, nearest_line,
x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>()); x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(next_point.position.cast<AABBScalar>());
next_point.distance = distance + boundary_offset; next_point.distance = distance + boundary_offset;
if (ADD_INTERSECTIONS && if (((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>( auto intersections = unscaled_prev_layer.template intersections_with_line<true>(
L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()}); L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()});
@ -134,7 +137,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
points.push_back(next_point); points.push_back(next_point);
} }
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) { if (config.add_corners) {
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());
@ -176,7 +179,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
points = std::move(new_points); points = std::move(new_points);
} }
if (max_line_length > 0) { if (config.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);
{ {
@ -185,7 +188,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
const ExtendedPoint &next = points[i + 1]; const ExtendedPoint &next = points[i + 1];
new_points.push_back(curr); new_points.push_back(curr);
double len = (next.position - curr.position).squaredNorm(); double len = (next.position - curr.position).squaredNorm();
double t = sqrt((max_line_length * max_line_length) / len); double t = sqrt((config.max_line_length * config.max_line_length) / len);
size_t new_point_count = 1.0 / t; size_t new_point_count = 1.0 / t;
for (size_t j = 1; j < new_point_count + 1; j++) { for (size_t j = 1; j < new_point_count + 1; j++) {
Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t); Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t);

View File

@ -4,6 +4,7 @@
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
///|/ ///|/
#include "SupportSpotsGenerator.hpp" #include "SupportSpotsGenerator.hpp"
#include <fstream>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <oneapi/tbb/concurrent_vector.h> #include <oneapi/tbb/concurrent_vector.h>
@ -337,9 +338,16 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
return {}; return {};
} }
const float flow_width = get_flow_width(layer_region, entity->role()); const float flow_width = get_flow_width(layer_region, entity->role());
ExtrusionProcessor::PropertiesEstimationConfig config{};
config.add_corners = true;
config.prev_layer_boundary_offset = true;
config.max_line_length = params.bridge_distance;
config.flow_width = flow_width;
std::vector<ExtrusionProcessor::ExtendedPoint> annotated_points = std::vector<ExtrusionProcessor::ExtendedPoint> annotated_points =
ExtrusionProcessor::estimate_points_properties<true, true, true, true>(entity->as_polyline().points, prev_layer_boundary, ExtrusionProcessor::estimate_points_properties<
flow_width, params.bridge_distance); true>(entity->as_polyline().points, prev_layer_boundary, config);
std::vector<ExtrusionLine> lines_out; std::vector<ExtrusionLine> lines_out;
lines_out.reserve(annotated_points.size()); lines_out.reserve(annotated_points.size());
@ -391,9 +399,12 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
const float flow_width = get_flow_width(layer_region, entity->role()); const float flow_width = get_flow_width(layer_region, entity->role());
// Compute only unsigned distance - prev_layer_lines can contain unconnected paths, thus the sign of the distance is unreliable // Compute only unsigned distance - prev_layer_lines can contain unconnected paths, thus the sign of the distance is unreliable
ExtrusionProcessor::PropertiesEstimationConfig config{};
config.max_line_length = params.bridge_distance;
config.flow_width = flow_width;
std::vector<ExtrusionProcessor::ExtendedPoint> annotated_points = std::vector<ExtrusionProcessor::ExtendedPoint> annotated_points =
ExtrusionProcessor::estimate_points_properties<true, true, false, false>(entity->as_polyline().points, prev_layer_lines, ExtrusionProcessor::estimate_points_properties<false>(entity->as_polyline().points, prev_layer_lines, config);
flow_width, params.bridge_distance);
std::vector<ExtrusionLine> lines_out; std::vector<ExtrusionLine> lines_out;
lines_out.reserve(annotated_points.size()); lines_out.reserve(annotated_points.size());
@ -1248,8 +1259,10 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width,
Polygon pol(pl.points); Polygon pol(pl.points);
pol.make_counter_clockwise(); pol.make_counter_clockwise();
auto annotated_points = ExtrusionProcessor::estimate_points_properties<true, true, false, false>(pol.points, prev_layer_lines, ExtrusionProcessor::PropertiesEstimationConfig config{};
flow_width); config.flow_width = flow_width;
auto annotated_points = ExtrusionProcessor::estimate_points_properties<
false>(pol.points, prev_layer_lines, config);
for (size_t i = 0; i < annotated_points.size(); ++i) { for (size_t i = 0; i < annotated_points.size(); ++i) {
const ExtrusionProcessor::ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; const ExtrusionProcessor::ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
@ -1324,10 +1337,14 @@ void estimate_malformations(LayerPtrs &layers, const Params &params)
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 = ExtrusionProcessor::estimate_points_properties<true, true, false, false>(extrusion_pts,
prev_layer_lines, ExtrusionProcessor::PropertiesEstimationConfig config{};
flow_width, config.max_line_length = params.bridge_distance;
params.bridge_distance); config.add_corners = true;
config.flow_width = flow_width;
auto annotated_points = ExtrusionProcessor::estimate_points_properties<
false>(extrusion_pts, prev_layer_lines, config);
for (size_t i = 0; i < annotated_points.size(); ++i) { for (size_t i = 0; i < annotated_points.size(); ++i) {
const ExtrusionProcessor::ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; const ExtrusionProcessor::ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
const ExtrusionProcessor::ExtendedPoint &b = annotated_points[i]; const ExtrusionProcessor::ExtendedPoint &b = annotated_points[i];