Initial implementation, requieres both dynamic speed and avoid curled overhangs options to be enabled
Also implements new, probably far better estimation of curled height of filament
This commit is contained in:
parent
69b69cb9a2
commit
b04e3bc25e
@ -246,6 +246,8 @@ class ExtrusionQualityEstimator
|
|||||||
{
|
{
|
||||||
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_layer_boundaries;
|
||||||
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_layer_boundaries;
|
||||||
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> prev_curled_extrusions;
|
||||||
|
std::unordered_map<const PrintObject *, AABBTreeLines::LinesDistancer<Linef>> next_curled_extrusions;
|
||||||
const PrintObject *current_object;
|
const PrintObject *current_object;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -253,18 +255,27 @@ public:
|
|||||||
|
|
||||||
void prepare_for_new_layer(const Layer *layer)
|
void prepare_for_new_layer(const Layer *layer)
|
||||||
{
|
{
|
||||||
if (layer == nullptr) return;
|
if (layer == nullptr)
|
||||||
const PrintObject *object = layer->object();
|
return;
|
||||||
prev_layer_boundaries[object] = next_layer_boundaries[object];
|
const PrintObject *object = layer->object();
|
||||||
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
|
prev_layer_boundaries[object] = next_layer_boundaries[object];
|
||||||
|
next_layer_boundaries[object] = AABBTreeLines::LinesDistancer<Linef>{to_unscaled_linesf(layer->lslices)};
|
||||||
|
prev_curled_extrusions[object] = next_curled_extrusions[object];
|
||||||
|
Linesf curled_lines;
|
||||||
|
curled_lines.reserve(layer->malformed_lines.size());
|
||||||
|
for (const Line &l : layer->malformed_lines) {
|
||||||
|
curled_lines.push_back(Linef(unscaled(l.a), unscaled(l.b)));
|
||||||
|
}
|
||||||
|
next_curled_extrusions[object] = AABBTreeLines::LinesDistancer<Linef>{curled_lines};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ProcessedPoint> estimate_extrusion_quality(const ExtrusionPath &path,
|
std::vector<ProcessedPoint> estimate_speed_from_extrusion_quality(
|
||||||
const std::vector<std::pair<int, ConfigOptionFloatOrPercent>> overhangs_w_speeds,
|
const ExtrusionPath &path,
|
||||||
const std::vector<std::pair<int, ConfigOptionInts>> overhangs_w_fan_speeds,
|
const std::vector<std::pair<int, ConfigOptionFloatOrPercent>> overhangs_w_speeds,
|
||||||
size_t extruder_id,
|
const std::vector<std::pair<int, ConfigOptionInts>> overhangs_w_fan_speeds,
|
||||||
float ext_perimeter_speed,
|
size_t extruder_id,
|
||||||
float original_speed)
|
float ext_perimeter_speed,
|
||||||
|
float original_speed)
|
||||||
{
|
{
|
||||||
float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed;
|
float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed;
|
||||||
std::map<float, float> speed_sections;
|
std::map<float, float> speed_sections;
|
||||||
@ -286,6 +297,15 @@ public:
|
|||||||
std::vector<ExtendedPoint> extended_points =
|
std::vector<ExtendedPoint> extended_points =
|
||||||
estimate_points_properties<true, true, true, true>(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);
|
||||||
|
|
||||||
|
for (ExtendedPoint& ep : extended_points) {
|
||||||
|
// We are going to enforce slowdown by increasing the point distance. The overhang speed is based on signed distance from
|
||||||
|
// the prev layer, where 0 means fully overlapping extrusions and thus no slowdown, while extrusion_width and more means full overhang, thus full slowdown.
|
||||||
|
// However, for curling, we take unsinged distance from the curled lines and artifically modifiy the distance
|
||||||
|
float distance_from_curled = prev_curled_extrusions[current_object].distance_from_lines<false>(ep.position);
|
||||||
|
ep.distance = std::max(ep.distance, path.width - distance_from_curled);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<ProcessedPoint> processed_points;
|
std::vector<ProcessedPoint> processed_points;
|
||||||
processed_points.reserve(extended_points.size());
|
processed_points.reserve(extended_points.size());
|
||||||
for (size_t i = 0; i < extended_points.size(); i++) {
|
for (size_t i = 0; i < extended_points.size(); i++) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <math.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@ -38,7 +39,7 @@
|
|||||||
#include "Geometry/ConvexHull.hpp"
|
#include "Geometry/ConvexHull.hpp"
|
||||||
|
|
||||||
// #define DETAILED_DEBUG_LOGS
|
// #define DETAILED_DEBUG_LOGS
|
||||||
// #define DEBUG_FILES
|
#define DEBUG_FILES
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
@ -208,16 +209,44 @@ std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length
|
|||||||
float estimate_curled_up_height(
|
float estimate_curled_up_height(
|
||||||
const ExtendedPoint &point, float layer_height, float flow_width, float prev_line_curled_height, Params params)
|
const ExtendedPoint &point, float layer_height, float flow_width, float prev_line_curled_height, Params params)
|
||||||
{
|
{
|
||||||
float curled_up_height = 0.0f;
|
float curled_up_height = 0;
|
||||||
if (fabs(point.distance) < 1.5 * flow_width) {
|
if (fabs(point.distance) < 1.5 * flow_width) {
|
||||||
curled_up_height = 0.85 * prev_line_curled_height;
|
curled_up_height = 0.9 * prev_line_curled_height;
|
||||||
}
|
}
|
||||||
if (point.distance > params.malformation_distance_factors.first * flow_width &&
|
|
||||||
point.distance < params.malformation_distance_factors.second * flow_width && point.curvature > -0.1f) {
|
|
||||||
float dist_factor = std::max(point.distance - params.malformation_distance_factors.first * flow_width, 0.01f) /
|
|
||||||
((params.malformation_distance_factors.second - params.malformation_distance_factors.first) * flow_width);
|
|
||||||
|
|
||||||
curled_up_height = layer_height * sqrt(sqrt(dist_factor)) * std::clamp(3.0f * point.curvature, 1.0f, 3.0f);
|
if (point.distance > params.malformation_distance_factors.first * flow_width &&
|
||||||
|
point.distance < params.malformation_distance_factors.second * flow_width) {
|
||||||
|
// imagine the extrusion profile. The part that has been glued (melted) with the previous layer will be called anchored section
|
||||||
|
// and the rest will be called curling section
|
||||||
|
float anchored_section = flow_width - point.distance;
|
||||||
|
float curling_section = point.distance;
|
||||||
|
|
||||||
|
// after extruding, the curling (floating) part of the extrusion starts to shrink back to the rounded shape of the nozzle
|
||||||
|
// The anchored part not, because the melted material holds to the previous layer well.
|
||||||
|
// We can assume for simplicity perfect equalization of layer height and raising part width, from which:
|
||||||
|
float swelling_radius = (layer_height + curling_section) / 2.0f;
|
||||||
|
curled_up_height += std::max(0.f, (swelling_radius - layer_height) / 2.0f);
|
||||||
|
|
||||||
|
// There is one more effect. On convex turns, there is larger tension on the floating edge of the extrusion then on the middle section.
|
||||||
|
// The tension is caused by the shrinking tendency of the filament, and on outer edge of convex trun, the expansion is greater and thus shrinking force is greater.
|
||||||
|
// This tension will cause the curling section to curle up (Why not down? maybe the previous layer works as a heat block, releasing the heat
|
||||||
|
// faster or slower than thin air, thus the extrusion always curles up)
|
||||||
|
|
||||||
|
if (point.curvature > 0.01){
|
||||||
|
float radius = 1.0 / point.curvature;
|
||||||
|
// compute radius at the point where the extrusion stops touch previous layer and starts curling
|
||||||
|
float radius_anchored_section_end = radius - flow_width / 2.0 + anchored_section;
|
||||||
|
// target radius represents the radius of the extrusion curling end, after curling
|
||||||
|
// the layer_height term aproximates that the extrusion curling part, when raising to vertical position, will stop before reaching
|
||||||
|
// perpendicular position, due to various forces.
|
||||||
|
float target_radius = std::max(radius, radius_anchored_section_end) + layer_height;
|
||||||
|
|
||||||
|
float b = target_radius - radius_anchored_section_end;
|
||||||
|
float a = (curling_section + swelling_radius) / 2.0;
|
||||||
|
float c = sqrt(a*a - b*b);
|
||||||
|
|
||||||
|
curled_up_height += c;
|
||||||
|
}
|
||||||
curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height);
|
curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ struct Params
|
|||||||
BrimType brim_type;
|
BrimType brim_type;
|
||||||
const float brim_width;
|
const float brim_width;
|
||||||
|
|
||||||
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.5, 1.1 };
|
const std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.3, 0.9 };
|
||||||
const float max_curled_height_factor = 10.0f;
|
const float max_curled_height_factor = 10.0f;
|
||||||
const float curling_tolerance_limit = 0.1f;
|
const float curling_tolerance_limit = 0.1f;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user