mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-07-29 16:52:01 +08:00
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:
parent
10c0f7f255
commit
c6858d41bd
@ -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)) {
|
||||||
|
@ -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);
|
||||||
|
@ -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 ¶ms)
|
|||||||
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];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user