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<CurledLine> &prev_layer_curled_lines)
{
std::vector<ExtendedPoint> extended_points = estimate_points_properties<true, true, true, true>(path.polyline.points,
unscaled_prev_layer, path.width());
ExtrusionProcessor::PropertiesEstimationConfig config{};
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());
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)) {
ExtrusionLoop new_loop = *loop;
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);
new_loop.paths.insert(new_loop.paths.end(), paths.begin(), paths.end());
ExtrusionPaths paths{loop->paths};
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);
} else if (auto *mp = dynamic_cast<const ExtrusionMultiPath *>(e)) {

View File

@ -61,12 +61,19 @@ struct OverhangSpeeds
float fan_speed;
};
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,
struct PropertiesEstimationConfig {
bool add_corners{};
bool prev_layer_boundary_offset{};
float flow_width;
float max_line_length{-1.0f};
};
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,
float flow_width,
float max_line_length = -1.0f)
{
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) {
if (idx > 0) {
@ -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;
if (input_points.empty())
return {};
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>(); };
float boundary_offset = config.prev_layer_boundary_offset ? 0.5 * config.flow_width : 0.0f;
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,
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])};
ExtendedPoint next_point{unscaled(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;
if (ADD_INTERSECTIONS &&
((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) {
if (((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>()});
@ -134,7 +137,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
points.push_back(next_point);
}
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
if (config.add_corners) {
std::vector<ExtendedPoint> new_points;
new_points.reserve(points.size() * 2);
new_points.push_back(points.front());
@ -176,7 +179,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
points = std::move(new_points);
}
if (max_line_length > 0) {
if (config.max_line_length > 0) {
std::vector<ExtendedPoint> new_points;
new_points.reserve(points.size() * 2);
{
@ -185,7 +188,7 @@ std::vector<ExtendedPoint> estimate_points_properties(const POINTS
const ExtendedPoint &next = points[i + 1];
new_points.push_back(curr);
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;
for (size_t j = 1; j < new_point_count + 1; j++) {
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
///|/
#include "SupportSpotsGenerator.hpp"
#include <fstream>
#include <boost/log/trivial.hpp>
#include <oneapi/tbb/concurrent_vector.h>
@ -337,9 +338,16 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
return {};
}
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 =
ExtrusionProcessor::estimate_points_properties<true, true, true, true>(entity->as_polyline().points, prev_layer_boundary,
flow_width, params.bridge_distance);
ExtrusionProcessor::estimate_points_properties<
true>(entity->as_polyline().points, prev_layer_boundary, config);
std::vector<ExtrusionLine> lines_out;
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());
// 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 =
ExtrusionProcessor::estimate_points_properties<true, true, false, false>(entity->as_polyline().points, prev_layer_lines,
flow_width, params.bridge_distance);
ExtrusionProcessor::estimate_points_properties<false>(entity->as_polyline().points, prev_layer_lines, config);
std::vector<ExtrusionLine> lines_out;
lines_out.reserve(annotated_points.size());
@ -1248,8 +1259,10 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width,
Polygon pol(pl.points);
pol.make_counter_clockwise();
auto annotated_points = ExtrusionProcessor::estimate_points_properties<true, true, false, false>(pol.points, prev_layer_lines,
flow_width);
ExtrusionProcessor::PropertiesEstimationConfig config{};
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) {
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;
extrusion->collect_points(extrusion_pts);
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,
flow_width,
params.bridge_distance);
ExtrusionProcessor::PropertiesEstimationConfig config{};
config.max_line_length = 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) {
const ExtrusionProcessor::ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i];
const ExtrusionProcessor::ExtendedPoint &b = annotated_points[i];