use new extrusion quality estimator function in support spot generator; fix issue with local support points and incorrect distance sign;

This commit is contained in:
Pavel Mikus 2022-12-20 17:04:31 +01:00 committed by Pavel Mikuš
parent 0b655e4b60
commit 72a25e7ad0
6 changed files with 171 additions and 126 deletions

View file

@ -117,18 +117,18 @@ inline std::tuple<int, int> coordinate_aligned_ray_hit_count(size_t
}
template<typename LineType, typename TreeType, typename VectorType>
inline std::vector<VectorType> get_intersections_with_line(size_t node_idx,
const TreeType &tree,
const std::vector<LineType> &lines,
const LineType &line,
const typename TreeType::BoundingBox &line_bb)
inline std::vector<std::pair<VectorType, size_t>> get_intersections_with_line(size_t node_idx,
const TreeType &tree,
const std::vector<LineType> &lines,
const LineType &line,
const typename TreeType::BoundingBox &line_bb)
{
const auto &node = tree.node(node_idx);
assert(node.is_valid());
if (node.is_leaf()) {
VectorType intersection_pt;
if (line_alg::intersection(line, lines[node.idx], &intersection_pt)) {
return {intersection_pt};
return {std::pair<VectorType, size_t>(intersection_pt, node_idx)};
} else {
return {};
}
@ -140,17 +140,17 @@ inline std::vector<VectorType> get_intersections_with_line(size_t
assert(node_left.is_valid());
assert(node_right.is_valid());
std::vector<VectorType> result;
std::vector<std::pair<VectorType, size_t>> result;
if (node_left.bbox.intersects(line_bb)) {
std::vector<VectorType> intersections = get_intersections_with_line<LineType, TreeType, VectorType>(left_node_idx, tree, lines,
line, line_bb);
std::vector<std::pair<VectorType, size_t>> intersections =
get_intersections_with_line<LineType, TreeType, VectorType>(left_node_idx, tree, lines, line, line_bb);
result.insert(result.end(), intersections.begin(), intersections.end());
}
if (node_right.bbox.intersects(line_bb)) {
std::vector<VectorType> intersections = get_intersections_with_line<LineType, TreeType, VectorType>(right_node_idx, tree, lines,
line, line_bb);
std::vector<std::pair<VectorType, size_t>> intersections =
get_intersections_with_line<LineType, TreeType, VectorType>(right_node_idx, tree, lines, line, line_bb);
result.insert(result.end(), intersections.begin(), intersections.end());
}
@ -263,9 +263,13 @@ inline int point_outside_closed_contours(const std::vector<LineType> &lines, con
}
template<bool sorted, typename VectorType, typename LineType, typename TreeType>
inline std::vector<VectorType> get_intersections_with_line(const std::vector<LineType> &lines, const TreeType &tree, const LineType &line)
inline std::vector<std::pair<VectorType, size_t>> get_intersections_with_line(const std::vector<LineType> &lines,
const TreeType &tree,
const LineType &line)
{
if (tree.empty()) { return {}; }
if (tree.empty()) {
return {};
}
auto line_bb = typename TreeType::BoundingBox(line.a, line.a);
line_bb.extend(line.b);
@ -274,15 +278,16 @@ inline std::vector<VectorType> get_intersections_with_line(const std::vector<Lin
using Floating =
typename std::conditional<std::is_floating_point<typename LineType::Scalar>::value, typename LineType::Scalar, double>::type;
std::vector<std::pair<Floating, VectorType>> points_with_sq_distance{};
for (const VectorType &p : intersections) {
points_with_sq_distance.emplace_back((p - line.a).template cast<Floating>().squaredNorm(), p);
std::vector<std::pair<Floating, std::pair<VectorType, size_t>>> points_with_sq_distance{};
for (const auto &p : intersections) {
points_with_sq_distance.emplace_back((p.first - line.a).template cast<Floating>().squaredNorm(), p);
}
std::sort(points_with_sq_distance.begin(), points_with_sq_distance.end(),
[](const std::pair<Floating, VectorType> &left, std::pair<Floating, VectorType> &right) {
return left.first < right.first;
});
for (size_t i = 0; i < points_with_sq_distance.size(); i++) { intersections[i] = points_with_sq_distance[i].second; }
[](const std::pair<Floating, std::pair<VectorType, size_t>> &left,
std::pair<Floating, std::pair<VectorType, size_t>> &right) { return left.first < right.first; });
for (size_t i = 0; i < points_with_sq_distance.size(); i++) {
intersections[i] = points_with_sq_distance[i].second;
}
}
return intersections;
@ -290,10 +295,11 @@ inline std::vector<VectorType> get_intersections_with_line(const std::vector<Lin
template<typename LineType> class LinesDistancer
{
private:
std::vector<LineType> lines;
public:
using Scalar = typename LineType::Scalar;
using Floating = typename std::conditional<std::is_floating_point<Scalar>::value, Scalar, double>::type;
private:
std::vector<LineType> lines;
AABBTreeIndirect::Tree<2, Scalar> tree;
public:
@ -313,23 +319,29 @@ public:
int outside(const Vec<2, Scalar> &point) const { return point_outside_closed_contours(lines, tree, point); }
// negative sign means inside
std::tuple<Floating, size_t, Vec<2, Floating>> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const
template<bool SIGNED_DISTANCE>
std::tuple<Floating, size_t, Vec<2, Floating>> distance_from_lines_extra(const Vec<2, Scalar> &point) const
{
size_t nearest_line_index_out = size_t(-1);
Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero();
Vec<2, Floating> p = point.template cast<Floating>();
auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out);
if (distance < 0) { return {std::numeric_limits<Floating>::infinity(), nearest_line_index_out, nearest_point_out}; }
if (distance < 0) {
return {std::numeric_limits<Floating>::infinity(), nearest_line_index_out, nearest_point_out};
}
distance = sqrt(distance);
distance *= outside(point);
if (SIGNED_DISTANCE) {
distance *= outside(point);
}
return {distance, nearest_line_index_out, nearest_point_out};
}
Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const
template<bool SIGNED_DISTANCE> Floating distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const
{
auto [dist, idx, np] = signed_distance_from_lines_extra(point);
auto [dist, idx, np] = distance_from_lines_extra<SIGNED_DISTANCE>(point);
return dist;
}
@ -338,7 +350,7 @@ public:
return all_lines_in_radius(this->lines, this->tree, point, radius * radius);
}
template<bool sorted> std::vector<Vec<2, Scalar>> intersections_with_line(const LineType &line) const
template<bool sorted> std::vector<std::pair<Vec<2, Scalar>, size_t>> intersections_with_line(const LineType &line) const
{
return get_intersections_with_line<sorted, Vec<2, Scalar>>(lines, tree, line);
}

View file

@ -39,9 +39,9 @@ public:
void add_point(float distance, float angle)
{
total_distance += distance;
total_curvature += std::abs(angle);
total_curvature += angle;
distances.push_back(distance);
angles.push_back(std::abs(angle));
angles.push_back(angle);
while (distances.size() > 1 && total_distance > window_size) {
total_distance -= distances.front();
@ -53,8 +53,6 @@ public:
float get_curvature() const
{
if (total_distance < EPSILON) { return 0.0; }
return total_curvature / window_size;
}
@ -70,7 +68,7 @@ public:
class CurvatureEstimator
{
static const size_t sliders_count = 2;
SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{1.5}, {3.0}};
SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{4.0}, {12.0}};
public:
void add_point(float distance, float angle)
@ -102,45 +100,69 @@ struct ExtendedPoint
float curvature;
};
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_ONLY, bool CONCAVITY_RESETS_CURVATURE, typename P, typename L>
std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P> &extrusion_points,
template<bool SCALED_INPUT, bool ADD_INTERSECTIONS, bool PREV_LAYER_BOUNDARY_OFFSET, bool SIGNED_DISTANCE, typename P, typename L>
std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P> &input_points,
const AABBTreeLines::LinesDistancer<L> &unscaled_prev_layer,
float flow_width)
float flow_width,
float max_line_length = -1.0f)
{
if (extrusion_points.empty()) return {};
float boundary_offset = PREV_LAYER_BOUNDARY_ONLY ? 0.5 * flow_width : 0.0f;
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;
CurvatureEstimator cestim;
float min_malformation_dist = 0.55 * flow_width;
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
std::vector<P> extrusion_points;
{
if (max_line_length <= 0) {
extrusion_points = input_points;
} else {
extrusion_points.reserve(input_points.size() * 2);
for (size_t i = 0; i + 1 < input_points.size(); i++) {
const P &curr = input_points[i];
const P &next = input_points[i + 1];
extrusion_points.push_back(curr);
auto len = maybe_unscale(next - curr).squaredNorm();
double t = sqrt((max_line_length * max_line_length) / len);
size_t new_point_count = 1.0 / (t + EPSILON);
for (size_t j = 1; j < new_point_count + 1; j++) {
extrusion_points.push_back(curr * (1.0 - j * t) + next * (j * t));
}
}
extrusion_points.push_back(input_points.back());
}
}
std::vector<ExtendedPoint> points;
points.reserve(extrusion_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1));
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
{
ExtendedPoint start_point{maybe_unscale(extrusion_points.front())};
auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(start_point.position);
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;
start_point.nearest_prev_layer_line = nearest_line;
points.push_back(start_point);
}
for (size_t i = 1; i < extrusion_points.size(); i++) {
ExtendedPoint next_point{maybe_unscale(extrusion_points[i])};
auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(next_point.position);
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;
next_point.nearest_prev_layer_line = nearest_line;
if (ADD_INTERSECTIONS &&
((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, next_point.position});
auto intersections = unscaled_prev_layer.template intersections_with_line<true>(L{prev_point.position.cast<AABBScalar>(), next_point.position.cast<AABBScalar>()});
for (const auto &intersection : intersections) {
points.emplace_back(intersection, boundary_offset);
points.emplace_back(intersection.first.template cast<double>(), boundary_offset, intersection.second);
}
}
points.push_back(next_point);
}
if (PREV_LAYER_BOUNDARY_ONLY && ADD_INTERSECTIONS) {
if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) {
std::vector<ExtendedPoint> new_points;
new_points.reserve(points.size() * 2);
new_points.push_back(points.front());
@ -159,12 +181,12 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
if (t0 < 1.0) {
auto p0 = curr.position + t0 * (next.position - curr.position);
auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p0);
auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p0.cast<AABBScalar>());
new_points.push_back(ExtendedPoint{p0, float(p0_dist + boundary_offset), p0_near_l});
}
if (t1 > 0.0) {
auto p1 = curr.position + t1 * (next.position - curr.position);
auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p1);
auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra<SIGNED_DISTANCE>(p1.cast<AABBScalar>());
new_points.push_back(ExtendedPoint{p1, float(p1_dist + boundary_offset), p1_near_l});
}
}
@ -194,7 +216,6 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
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);
if (CONCAVITY_RESETS_CURVATURE && alfa < 0.0) { cestim.reset(); }
}
if (a.distance < min_malformation_dist) { cestim.reset(); }
@ -244,7 +265,7 @@ public:
[](const std::pair<float, float> &a, const std::pair<float, float> &b) { return a.first < b.first; });
std::vector<ExtendedPoint> extended_points =
estimate_points_properties<true, true, true, false>(path.polyline.points, prev_layer_boundaries[current_object], path.width);
estimate_points_properties<true, true, true, true>(path.polyline.points, prev_layer_boundaries[current_object], path.width);
std::vector<ProcessedPoint> processed_points;
processed_points.reserve(extended_points.size());

View file

@ -1071,7 +1071,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
for (SeamCandidate &perimeter_point : layers[layer_idx].points) {
Vec2f point = Vec2f { perimeter_point.position.head<2>() };
if (prev_layer_distancer.get() != nullptr) {
perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast<double>())
perimeter_point.overhang = prev_layer_distancer->distance_from_lines<true>(point.cast<double>())
+ 0.6f * perimeter_point.perimeter.flow_width
- tan(SeamPlacer::overhang_angle_threshold)
* po->layers()[layer_idx]->height;
@ -1080,7 +1080,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po)
}
if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam)
perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast<double>())
perimeter_point.embedded_distance = current_layer_distancer->distance_from_lines<true>(point.cast<double>())
+ 0.6f * perimeter_point.perimeter.flow_width;
}
}

View file

@ -664,11 +664,11 @@ bool paths_touch(const ExtrusionPath &path_one, const ExtrusionPath &path_two, d
AABBTreeLines::LinesDistancer<Line> lines_two{path_two.as_polyline().lines()};
for (size_t pt_idx = 0; pt_idx < path_one.polyline.size(); pt_idx++) {
if (std::abs(lines_two.signed_distance_from_lines(path_one.polyline.points[pt_idx])) < limit_distance) { return true; }
if (lines_two.distance_from_lines<false>(path_one.polyline.points[pt_idx]) < limit_distance) { return true; }
}
for (size_t pt_idx = 0; pt_idx < path_two.polyline.size(); pt_idx++) {
if (std::abs(lines_one.signed_distance_from_lines(path_two.polyline.points[pt_idx])) < limit_distance) { return true; }
if (lines_one.distance_from_lines<false>(path_two.polyline.points[pt_idx]) < limit_distance) { return true; }
}
return false;
}

View file

@ -3,6 +3,7 @@
#include "ExPolygon.hpp"
#include "ExtrusionEntity.hpp"
#include "ExtrusionEntityCollection.hpp"
#include "GCode/ExtrusionProcessor.hpp"
#include "Line.hpp"
#include "Point.hpp"
#include "Polygon.hpp"
@ -13,13 +14,16 @@
#include "tbb/blocked_range.h"
#include "tbb/blocked_range2d.h"
#include "tbb/parallel_reduce.h"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <cmath>
#include <cstddef>
#include <cstdio>
#include <functional>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <utility>
#include <vector>
#include "AABBTreeLines.hpp"
@ -41,12 +45,14 @@ namespace Slic3r {
class ExtrusionLine
{
public:
ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), len(0.0f), origin_entity(nullptr) {}
ExtrusionLine(const Vec2f &a, const Vec2f &b, const ExtrusionEntity *origin_entity)
: a(a), b(b), len((a - b).norm()), origin_entity(origin_entity)
ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), origin_entity(nullptr) {}
ExtrusionLine(const Vec2f &a, const Vec2f &b, float len, const ExtrusionEntity *origin_entity)
: a(a), b(b), len(len), origin_entity(origin_entity)
{}
float length() { return (a - b).norm(); }
ExtrusionLine(const Vec2f &a, const Vec2f &b)
: a(a), b(b), len((a-b).norm()), origin_entity(nullptr)
{}
bool is_external_perimeter() const
{
@ -60,7 +66,8 @@ public:
const ExtrusionEntity *origin_entity;
bool support_point_generated = false;
float malformation = 0.0f;
float form_quality = 1.0f;
float curled_up_height = 0.0f;
static const constexpr int Dim = 2;
using Scalar = Vec2f::Scalar;
@ -205,7 +212,6 @@ std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length
Polyline pl = e->as_polyline();
std::vector<ExtrusionLine> lines;
lines.reserve(pl.points.size() * 1.5f);
lines.emplace_back(unscaled(pl.points[0]).cast<float>(), unscaled(pl.points[0]).cast<float>(), e);
for (int point_idx = 0; point_idx < int(pl.points.size()) - 1; ++point_idx) {
Vec2f start = unscaled(pl.points[point_idx]).cast<float>();
Vec2f next = unscaled(pl.points[point_idx + 1]).cast<float>();
@ -217,87 +223,84 @@ std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length
for (int i = 0; i < lines_count; ++i) {
Vec2f a(start + v * (i * step_size));
Vec2f b(start + v * ((i + 1) * step_size));
lines.emplace_back(a, b, e);
lines.emplace_back(a, b, (a-b).norm(), e);
}
}
return lines;
}
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
const LayerRegion *layer_region,
const LD &prev_layer_lines,
const Params &params)
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
const LayerRegion *layer_region,
const LD &prev_layer_lines,
const AABBTreeLines::LinesDistancer<Linef> &prev_layer_boundary,
const Params &params)
{
if (entity->is_collection()) {
std::vector<ExtrusionLine> checked_lines_out;
checked_lines_out.reserve(prev_layer_lines.get_lines().size() / 3);
for (const auto *e : static_cast<const ExtrusionEntityCollection *>(entity)->entities) {
auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, params);
auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, prev_layer_boundary, params);
checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end());
}
return checked_lines_out;
} else { // single extrusion path, with possible varying parameters
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { return {}; }
std::vector<ExtrusionLine> lines = to_short_lines(entity, params.bridge_distance);
ExtrusionPropertiesAccumulator bridging_acc{};
ExtrusionPropertiesAccumulator malformation_acc{};
bridging_acc.add_distance(params.bridge_distance + 1.0f);
const float flow_width = get_flow_width(layer_region, entity->role());
float min_malformation_dist = flow_width - params.malformation_overlap_factor.first * flow_width;
float max_malformation_dist = flow_width - params.malformation_overlap_factor.second * flow_width;
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
ExtrusionLine &current_line = lines[line_idx];
if (line_idx + 1 == lines.size() && current_line.b != lines.begin()->a) {
bridging_acc.add_distance(params.bridge_distance + 1.0f);
}
float curr_angle = 0;
if (line_idx + 1 < lines.size()) {
const Vec2f v1 = current_line.b - current_line.a;
const Vec2f v2 = lines[line_idx + 1].b - lines[line_idx + 1].a;
curr_angle = angle(v1, v2);
}
bridging_acc.add_angle(curr_angle);
// malformation in concave angles does not happen
malformation_acc.add_angle(std::max(0.0f, curr_angle));
if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); }
std::vector<ExtendedPoint> annotated_points = estimate_points_properties<true, true, false, false>(entity->as_polyline().points,
prev_layer_lines, flow_width,
params.bridge_distance);
auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b);
if (dist_from_prev_layer < flow_width) {
bridging_acc.reset();
} else {
bridging_acc.add_distance(current_line.len);
std::vector<ExtrusionLine> lines_out;
lines_out.reserve(annotated_points.size());
float bridged_distance = annotated_points.front().position != annotated_points.back().position ? (params.bridge_distance + 1.0f) :
0.0f;
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, entity};
ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
ExtrusionLine{};
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;
if (curr_point.distance > 0.9f * flow_width) {
line_out.form_quality = 0.7f;
bridged_distance += line_len;
// if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports.
bool in_layer_dist_condition = bridging_acc.distance >
params.bridge_distance / (1.0f + (bridging_acc.max_curvature *
params.bridge_distance_decrease_by_curvature_factor / PI));
bool between_layers_condition = dist_from_prev_layer > max_malformation_dist;
if (in_layer_dist_condition && between_layers_condition) {
current_line.support_point_generated = true;
bridging_acc.reset();
bool in_layer_dist_condition = bridged_distance >
params.bridge_distance / (1.0f + std::abs(curr_point.curvature) *
params.bridge_distance_decrease_by_curvature_factor);
if (in_layer_dist_condition) {
line_out.support_point_generated = true;
bridged_distance = 0.0f;
}
} else if (curr_point.distance > flow_width * (0.8 + std::clamp(curr_point.curvature, -0.2f, 0.2f))) {
bridged_distance += line_len;
line_out.form_quality = nearest_prev_layer_line.form_quality -
std::abs(curr_point.curvature);
if (line_out.form_quality < 0) {
line_out.support_point_generated = true;
line_out.form_quality = 0.7f;
}
} else {
bridged_distance = 0.0f;
}
// malformation propagation from below
if (fabs(dist_from_prev_layer) < 2.0f * flow_width) {
const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx);
current_line.malformation += 0.85 * nearest_line.malformation;
}
// current line maformation
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
float factor = std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) /
(max_malformation_dist - min_malformation_dist);
malformation_acc.add_distance(current_line.len);
current_line.malformation += layer_region->layer()->height * factor * (2.0f + 3.0f * (malformation_acc.max_curvature / PI));
current_line.malformation = std::min(current_line.malformation,
float(layer_region->layer()->height * params.max_malformation_factor));
} else {
malformation_acc.reset();
line_out.curled_up_height = 0.8 * nearest_prev_layer_line.curled_up_height;
if (curr_point.distance > 0.6 * flow_width && curr_point.distance < 0.9 * flow_width && curr_point.curvature > 0.0) {
line_out.curled_up_height = layer_region->layer()->height * (0.6f + std::min(1.0f, curr_point.curvature));
}
lines_out.push_back(line_out);
}
return lines;
return lines_out;
}
}
@ -474,7 +477,7 @@ public:
float movement_force = params.max_acceleration * mass;
float extruder_conflict_force = params.standard_extruder_conflict_force +
std::min(extruded_line.malformation, 1.0f) * params.malformations_additive_conflict_extruder_force;
std::min(extruded_line.curled_up_height, 1.0f) * params.malformations_additive_conflict_extruder_force;
// section for bed calculations
{
@ -756,6 +759,15 @@ SupportPoints check_stability(const PrintObject *po, const Params &params)
const LayerSlice &slice = layer->lslices_ex.at(slice_idx);
ObjectPart &part = active_object_parts.access(prev_slice_idx_to_object_part_mapping[slice_idx]);
SliceConnection &weakest_conn = prev_slice_idx_to_weakest_connection[slice_idx];
std::vector<Linef> boundary_lines;
for (const auto &link : slice.overlaps_below) {
auto ls = to_unscaled_linesf({layer->lower_layer->lslices[link.slice_idx]});
boundary_lines.insert(boundary_lines.end(), ls.begin(), ls.end());
}
AABBTreeLines::LinesDistancer<Linef> boundary{std::move(boundary_lines)};
std::vector<ExtrusionLine> current_slice_ext_perims_lines{};
current_slice_ext_perims_lines.reserve(prev_layer_ext_perim_lines.get_lines().size() / layer->lslices_ex.size());
#ifdef DETAILED_DEBUG_LOGS
@ -791,7 +803,7 @@ SupportPoints check_stability(const PrintObject *po, const Params &params)
const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx];
if (entity->role() == erBridgeInfill) {
for (const ExtrusionLine &bridge :
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines, params)) {
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,boundary, params)) {
if (bridge.support_point_generated) {
reckon_new_support_point(create_support_point_position(bridge.b), -EPSILON, Vec2f::Zero());
}
@ -804,7 +816,7 @@ SupportPoints check_stability(const PrintObject *po, const Params &params)
for (const auto &perimeter_idx : island.perimeters) {
const ExtrusionEntity *entity = perimeter_region->perimeters().entities[perimeter_idx];
std::vector<ExtrusionLine> perims = check_extrusion_entity_stability(entity, perimeter_region,
prev_layer_ext_perim_lines, params);
prev_layer_ext_perim_lines,boundary, params);
for (const ExtrusionLine &perim : perims) {
if (perim.support_point_generated) {
reckon_new_support_point(create_support_point_position(perim.b), -EPSILON, Vec2f::Zero());
@ -818,13 +830,13 @@ SupportPoints check_stability(const PrintObject *po, const Params &params)
float unchecked_dist = params.min_distance_between_support_points + 1.0f;
for (const ExtrusionLine &line : current_slice_ext_perims_lines) {
if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.malformation < 0.3f) || line.len == 0) {
if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.curled_up_height < 0.3f) || line.len == 0) {
unchecked_dist += line.len;
} else {
unchecked_dist = line.len;
Vec2f pivot_site_search_point = Vec2f(line.b + (line.b - line.a).normalized() * 300.0f);
auto [dist, nidx,
nearest_point] = current_slice_lines_distancer.signed_distance_from_lines_extra(pivot_site_search_point);
nearest_point] = current_slice_lines_distancer.distance_from_lines_extra<false>(pivot_site_search_point);
Vec3f support_point = create_support_point_position(nearest_point);
auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, bottom_z, params);
if (force > 0) { reckon_new_support_point(support_point, force, (line.b - line.a).normalized()); }
@ -909,25 +921,25 @@ struct LayerCurlingEstimator
malformation_acc.add_angle(std::max(0.0f, curr_angle));
if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); }
auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b);
auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.distance_from_lines_extra<true>(current_line.b);
if (fabs(dist_from_prev_layer) < 2.0f * flow_width) {
const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx);
current_line.malformation += 0.9 * nearest_line.malformation;
current_line.curled_up_height += 0.9 * nearest_line.curled_up_height;
}
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
float factor = 0.5f + 0.5f * std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) /
(max_malformation_dist - min_malformation_dist);
malformation_acc.add_distance(current_line.len);
current_line.malformation += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI));
current_line.malformation = std::min(current_line.malformation, float(l->height * params.max_malformation_factor));
current_line.curled_up_height += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI));
current_line.curled_up_height = std::min(current_line.curled_up_height, float(l->height * params.max_malformation_factor));
} else {
malformation_acc.reset();
}
}
for (const ExtrusionLine &line : extrusion_lines) {
if (line.malformation > 0.3f) { l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); }
if (line.curled_up_height > 0.3f) { l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); }
}
prev_layer_lines = LD(extrusion_lines);
}
@ -955,7 +967,7 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float supports_fl
for (int point_idx = 0; point_idx < int(pl.points.size() - 1); ++point_idx) {
Vec2f start = unscaled(pl.points[point_idx]).cast<float>();
Vec2f next = unscaled(pl.points[point_idx + 1]).cast<float>();
ExtrusionLine line{start, next, extrusion};
ExtrusionLine line{start, next, (start - next).norm(), extrusion};
extrusion_lines.push_back(line);
}
}

View file

@ -27,7 +27,7 @@ struct Params {
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
const float bridge_distance = 12.0f; //mm
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
const float bridge_distance_decrease_by_curvature_factor = 10.0f; // allowed bridge distance = bridge_distance / (1 + this factor * curvature )
const std::pair<float,float> malformation_overlap_factor = std::pair<float, float> { 0.50, -0.1 };
const float max_malformation_factor = 10.0f;