refactored and unified code for curled up filament estimation
This commit is contained in:
parent
72a25e7ad0
commit
ec4cc2e694
@ -68,23 +68,32 @@ public:
|
|||||||
class CurvatureEstimator
|
class CurvatureEstimator
|
||||||
{
|
{
|
||||||
static const size_t sliders_count = 2;
|
static const size_t sliders_count = 2;
|
||||||
SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{4.0}, {12.0}};
|
SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{4.0}, {10.0}};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add_point(float distance, float angle)
|
void add_point(float distance, float angle)
|
||||||
{
|
{
|
||||||
if (distance < EPSILON) return;
|
if (distance < EPSILON)
|
||||||
for (SlidingWindowCurvatureAccumulator &slider : sliders) { slider.add_point(distance, angle); }
|
return;
|
||||||
|
for (SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||||
|
slider.add_point(distance, angle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
float get_curvature()
|
float get_curvature()
|
||||||
{
|
{
|
||||||
float max_curvature = std::numeric_limits<float>::min();
|
float max_curvature = 0.0f;
|
||||||
for (const SlidingWindowCurvatureAccumulator &slider : sliders) { max_curvature = std::max(max_curvature, slider.get_curvature()); }
|
for (const SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||||
|
if (abs(slider.get_curvature()) > abs(max_curvature)) {
|
||||||
|
max_curvature = slider.get_curvature();
|
||||||
|
}
|
||||||
|
}
|
||||||
return max_curvature;
|
return max_curvature;
|
||||||
}
|
}
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
for (SlidingWindowCurvatureAccumulator &slider : sliders) { slider.reset(); }
|
for (SlidingWindowCurvatureAccumulator &slider : sliders) {
|
||||||
|
slider.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,7 +120,6 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
|
|||||||
return {};
|
return {};
|
||||||
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
|
float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f;
|
||||||
CurvatureEstimator cestim;
|
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>(); };
|
auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast<double>(); };
|
||||||
|
|
||||||
std::vector<P> extrusion_points;
|
std::vector<P> extrusion_points;
|
||||||
@ -218,7 +226,6 @@ std::vector<ExtendedPoint> estimate_points_properties(const std::vector<P>
|
|||||||
cestim.add_point(distance, alfa);
|
cestim.add_point(distance, alfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.distance < min_malformation_dist) { cestim.reset(); }
|
|
||||||
a.curvature = cestim.get_curvature();
|
a.curvature = cestim.get_curvature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,31 +181,6 @@ float get_flow_width(const LayerRegion *region, ExtrusionRole role)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulator of current extrusion path properties
|
|
||||||
// It remembers unsuported distance and maximum accumulated curvature over that distance.
|
|
||||||
// Used to determine local stability issues (too long bridges, extrusion curves into air)
|
|
||||||
struct ExtrusionPropertiesAccumulator
|
|
||||||
{
|
|
||||||
float distance = 0; // accumulated distance
|
|
||||||
float curvature = 0; // accumulated signed ccw angles
|
|
||||||
float max_curvature = 0; // max absolute accumulated value
|
|
||||||
|
|
||||||
void add_distance(float dist) { distance += dist; }
|
|
||||||
|
|
||||||
void add_angle(float ccw_angle)
|
|
||||||
{
|
|
||||||
curvature += ccw_angle;
|
|
||||||
max_curvature = std::max(max_curvature, std::abs(curvature));
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
distance = 0;
|
|
||||||
curvature = 0;
|
|
||||||
max_curvature = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit)
|
std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length_limit)
|
||||||
{
|
{
|
||||||
assert(!e->is_collection());
|
assert(!e->is_collection());
|
||||||
@ -229,6 +204,24 @@ std::vector<ExtrusionLine> to_short_lines(const ExtrusionEntity *e, float length
|
|||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float estimate_curled_up_height(
|
||||||
|
const ExtendedPoint &point, float layer_height, float flow_width, float prev_line_curled_height, Params params)
|
||||||
|
{
|
||||||
|
float curled_up_height = 0.0f;
|
||||||
|
if (fabs(point.distance) < 1.5 * flow_width) {
|
||||||
|
curled_up_height = 0.85 * 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 = (point.distance - params.malformation_distance_factors.first * flow_width) /
|
||||||
|
((params.malformation_distance_factors.second - params.malformation_distance_factors.first) * flow_width);
|
||||||
|
|
||||||
|
curled_up_height = layer_height * 2.0f * sqrt(sqrt(dist_factor)) * std::clamp(6.0f * point.curvature, 1.0f, 6.0f);
|
||||||
|
curled_up_height = std::min(curled_up_height, params.max_malformation_factor * layer_height);
|
||||||
|
}
|
||||||
|
return curled_up_height;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
||||||
const LayerRegion *layer_region,
|
const LayerRegion *layer_region,
|
||||||
const LD &prev_layer_lines,
|
const LD &prev_layer_lines,
|
||||||
@ -244,7 +237,9 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
|
|||||||
}
|
}
|
||||||
return checked_lines_out;
|
return checked_lines_out;
|
||||||
} else { // single extrusion path, with possible varying parameters
|
} else { // single extrusion path, with possible varying parameters
|
||||||
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { return {}; }
|
if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const float flow_width = get_flow_width(layer_region, entity->role());
|
const float flow_width = get_flow_width(layer_region, entity->role());
|
||||||
|
|
||||||
@ -262,11 +257,11 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
|
|||||||
ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast<float>() : curr_point.position.cast<float>(),
|
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};
|
curr_point.position.cast<float>(), line_len, entity};
|
||||||
|
|
||||||
ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
|
const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
|
||||||
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
|
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
|
||||||
ExtrusionLine{};
|
ExtrusionLine{};
|
||||||
|
|
||||||
float sign = prev_layer_boundary.distance_from_lines<true>(curr_point.position) - 0.5f * flow_width < 0.0f ? -1.0f : 1.0f;
|
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;
|
curr_point.distance *= sign;
|
||||||
|
|
||||||
if (curr_point.distance > 0.9f * flow_width) {
|
if (curr_point.distance > 0.9f * flow_width) {
|
||||||
@ -282,8 +277,7 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
|
|||||||
}
|
}
|
||||||
} else if (curr_point.distance > flow_width * (0.8 + std::clamp(curr_point.curvature, -0.2f, 0.2f))) {
|
} else if (curr_point.distance > flow_width * (0.8 + std::clamp(curr_point.curvature, -0.2f, 0.2f))) {
|
||||||
bridged_distance += line_len;
|
bridged_distance += line_len;
|
||||||
line_out.form_quality = nearest_prev_layer_line.form_quality -
|
line_out.form_quality = nearest_prev_layer_line.form_quality - std::abs(curr_point.curvature);
|
||||||
std::abs(curr_point.curvature);
|
|
||||||
if (line_out.form_quality < 0) {
|
if (line_out.form_quality < 0) {
|
||||||
line_out.support_point_generated = true;
|
line_out.support_point_generated = true;
|
||||||
line_out.form_quality = 0.7f;
|
line_out.form_quality = 0.7f;
|
||||||
@ -292,10 +286,8 @@ std::vector<ExtrusionLine> check_extrusion_entity_stability(const ExtrusionEntit
|
|||||||
bridged_distance = 0.0f;
|
bridged_distance = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
line_out.curled_up_height = 0.8 * nearest_prev_layer_line.curled_up_height;
|
line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width,
|
||||||
if (curr_point.distance > 0.6 * flow_width && curr_point.distance < 0.9 * flow_width && curr_point.curvature > 0.0) {
|
nearest_prev_layer_line.curled_up_height, params);
|
||||||
line_out.curled_up_height = layer_region->layer()->height * (0.6f + std::min(1.0f, curr_point.curvature));
|
|
||||||
}
|
|
||||||
|
|
||||||
lines_out.push_back(line_out);
|
lines_out.push_back(line_out);
|
||||||
}
|
}
|
||||||
@ -765,7 +757,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms)
|
|||||||
auto ls = to_unscaled_linesf({layer->lower_layer->lslices[link.slice_idx]});
|
auto ls = to_unscaled_linesf({layer->lower_layer->lslices[link.slice_idx]});
|
||||||
boundary_lines.insert(boundary_lines.end(), ls.begin(), ls.end());
|
boundary_lines.insert(boundary_lines.end(), ls.begin(), ls.end());
|
||||||
}
|
}
|
||||||
AABBTreeLines::LinesDistancer<Linef> boundary{std::move(boundary_lines)};
|
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
||||||
|
|
||||||
|
|
||||||
std::vector<ExtrusionLine> current_slice_ext_perims_lines{};
|
std::vector<ExtrusionLine> current_slice_ext_perims_lines{};
|
||||||
@ -803,7 +795,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms)
|
|||||||
const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx];
|
const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx];
|
||||||
if (entity->role() == erBridgeInfill) {
|
if (entity->role() == erBridgeInfill) {
|
||||||
for (const ExtrusionLine &bridge :
|
for (const ExtrusionLine &bridge :
|
||||||
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,boundary, params)) {
|
check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,prev_layer_boundary, params)) {
|
||||||
if (bridge.support_point_generated) {
|
if (bridge.support_point_generated) {
|
||||||
reckon_new_support_point(create_support_point_position(bridge.b), -EPSILON, Vec2f::Zero());
|
reckon_new_support_point(create_support_point_position(bridge.b), -EPSILON, Vec2f::Zero());
|
||||||
}
|
}
|
||||||
@ -816,7 +808,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms)
|
|||||||
for (const auto &perimeter_idx : island.perimeters) {
|
for (const auto &perimeter_idx : island.perimeters) {
|
||||||
const ExtrusionEntity *entity = perimeter_region->perimeters().entities[perimeter_idx];
|
const ExtrusionEntity *entity = perimeter_region->perimeters().entities[perimeter_idx];
|
||||||
std::vector<ExtrusionLine> perims = check_extrusion_entity_stability(entity, perimeter_region,
|
std::vector<ExtrusionLine> perims = check_extrusion_entity_stability(entity, perimeter_region,
|
||||||
prev_layer_ext_perim_lines,boundary, params);
|
prev_layer_ext_perim_lines,prev_layer_boundary, params);
|
||||||
for (const ExtrusionLine &perim : perims) {
|
for (const ExtrusionLine &perim : perims) {
|
||||||
if (perim.support_point_generated) {
|
if (perim.support_point_generated) {
|
||||||
reckon_new_support_point(create_support_point_position(perim.b), -EPSILON, Vec2f::Zero());
|
reckon_new_support_point(create_support_point_position(perim.b), -EPSILON, Vec2f::Zero());
|
||||||
@ -851,7 +843,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
void debug_export(Issues issues, std::string file_name)
|
void debug_export(SupportPoints support_points, std::string file_name)
|
||||||
{
|
{
|
||||||
Slic3r::CNumericLocalesSetter locales_setter;
|
Slic3r::CNumericLocalesSetter locales_setter;
|
||||||
{
|
{
|
||||||
@ -861,13 +853,13 @@ void debug_export(Issues issues, std::string file_name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < issues.support_points.size(); ++i) {
|
for (size_t i = 0; i < support_points.size(); ++i) {
|
||||||
if (issues.support_points[i].force <= 0) {
|
if (support_points[i].force <= 0) {
|
||||||
fprintf(fp, "v %f %f %f %f %f %f\n", issues.support_points[i].position(0), issues.support_points[i].position(1),
|
fprintf(fp, "v %f %f %f %f %f %f\n", support_points[i].position(0), support_points[i].position(1),
|
||||||
issues.support_points[i].position(2), 0.0, 1.0, 0.0);
|
support_points[i].position(2), 0.0, 1.0, 0.0);
|
||||||
} else {
|
} else {
|
||||||
fprintf(fp, "v %f %f %f %f %f %f\n", issues.support_points[i].position(0), issues.support_points[i].position(1),
|
fprintf(fp, "v %f %f %f %f %f %f\n", support_points[i].position(0), support_points[i].position(1),
|
||||||
issues.support_points[i].position(2), 1.0, 0.0, 0.0);
|
support_points[i].position(2), 1.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,105 +875,70 @@ SupportPoints full_search(const PrintObject *po, const Params ¶ms)
|
|||||||
{
|
{
|
||||||
SupportPoints supp_points = check_stability(po, params);
|
SupportPoints supp_points = check_stability(po, params);
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
debug_export(issues, "issues");
|
debug_export(supp_points, "issues");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return supp_points;
|
return supp_points;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, const Params ¶ms)
|
||||||
struct LayerCurlingEstimator
|
|
||||||
{
|
|
||||||
LD prev_layer_lines;
|
|
||||||
Params params;
|
|
||||||
std::function<float(const ExtrusionLine &)> flow_width_getter;
|
|
||||||
|
|
||||||
LayerCurlingEstimator(std::function<float(const ExtrusionLine &)> flow_width_getter, const Params ¶ms)
|
|
||||||
: flow_width_getter(flow_width_getter), params(params)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void estimate_curling(std::vector<ExtrusionLine> &extrusion_lines, Layer *l)
|
|
||||||
{
|
|
||||||
ExtrusionPropertiesAccumulator malformation_acc{};
|
|
||||||
for (size_t line_idx = 0; line_idx < extrusion_lines.size(); ++line_idx) {
|
|
||||||
ExtrusionLine ¤t_line = extrusion_lines[line_idx];
|
|
||||||
|
|
||||||
float flow_width = flow_width_getter(current_line);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
float curr_angle = 0;
|
|
||||||
if (line_idx + 1 < extrusion_lines.size()) {
|
|
||||||
const Vec2f v1 = current_line.b - current_line.a;
|
|
||||||
const Vec2f v2 = extrusion_lines[line_idx + 1].b - extrusion_lines[line_idx + 1].a;
|
|
||||||
curr_angle = angle(v1, v2);
|
|
||||||
}
|
|
||||||
// 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(); }
|
|
||||||
|
|
||||||
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.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.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.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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void estimate_supports_malformations(SupportLayerPtrs &layers, float supports_flow_width, const Params ¶ms)
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
FILE *debug_file = boost::nowide::fopen(debug_out_path("supports_malformations.obj").c_str(), "w");
|
FILE *debug_file = boost::nowide::fopen(debug_out_path("supports_malformations.obj").c_str(), "w");
|
||||||
#endif
|
#endif
|
||||||
auto flow_width_getter = [=](const ExtrusionLine& l) {
|
|
||||||
return supports_flow_width;
|
|
||||||
};
|
|
||||||
|
|
||||||
LayerCurlingEstimator lce{flow_width_getter, params};
|
AABBTreeLines::LinesDistancer<ExtrusionLine> prev_layer_lines{};
|
||||||
|
|
||||||
for (SupportLayer *l : layers) {
|
for (SupportLayer *l : layers) {
|
||||||
std::vector<ExtrusionLine> extrusion_lines;
|
std::vector<ExtrusionLine> current_layer_lines;
|
||||||
|
|
||||||
for (const ExtrusionEntity *extrusion : l->support_fills.flatten().entities) {
|
for (const ExtrusionEntity *extrusion : l->support_fills.flatten().entities) {
|
||||||
Polyline pl = extrusion->as_polyline();
|
Polyline pl = extrusion->as_polyline();
|
||||||
Polygon pol(pl.points);
|
Polygon pol(pl.points);
|
||||||
pol.make_counter_clockwise();
|
pol.make_counter_clockwise();
|
||||||
pl = pol.split_at_first_point();
|
|
||||||
for (int point_idx = 0; point_idx < int(pl.points.size() - 1); ++point_idx) {
|
auto annotated_points = estimate_points_properties<true, true, false, false>(pol.points, prev_layer_lines, flow_width);
|
||||||
Vec2f start = unscaled(pl.points[point_idx]).cast<float>();
|
|
||||||
Vec2f next = unscaled(pl.points[point_idx + 1]).cast<float>();
|
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
||||||
ExtrusionLine line{start, next, (start - next).norm(), extrusion};
|
ExtendedPoint &curr_point = annotated_points[i];
|
||||||
extrusion_lines.push_back(line);
|
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, extrusion};
|
||||||
|
|
||||||
|
const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ?
|
||||||
|
prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) :
|
||||||
|
ExtrusionLine{};
|
||||||
|
|
||||||
|
Vec2f v1 = (nearest_prev_layer_line.b - nearest_prev_layer_line.a);
|
||||||
|
Vec2f v2 = (curr_point.position.cast<float>() - nearest_prev_layer_line.a);
|
||||||
|
auto d = (v1.x() * v2.y()) - (v1.y() * v2.x());
|
||||||
|
if (d > 0) {
|
||||||
|
curr_point.distance *= -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_out.curled_up_height = estimate_curled_up_height(curr_point, l->height, flow_width,
|
||||||
|
nearest_prev_layer_line.curled_up_height, params);
|
||||||
|
|
||||||
|
current_layer_lines.push_back(line_out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lce.estimate_curling(extrusion_lines, l);
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
|
if (line.curled_up_height > 0.3f) {
|
||||||
|
l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
for (const ExtrusionLine &line : extrusion_lines) {
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
if (line.malformation > 0.3f) {
|
if (line.curled_up_height > 0.3f) {
|
||||||
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.malformation);
|
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.curled_up_height);
|
||||||
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
prev_layer_lines = LD{current_layer_lines};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
@ -994,44 +951,58 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
|||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
FILE *debug_file = boost::nowide::fopen(debug_out_path("object_malformations.obj").c_str(), "w");
|
FILE *debug_file = boost::nowide::fopen(debug_out_path("object_malformations.obj").c_str(), "w");
|
||||||
#endif
|
#endif
|
||||||
auto flow_width_getter = [](const ExtrusionLine &l) { return 0.0; };
|
|
||||||
LayerCurlingEstimator lce{flow_width_getter, params};
|
LD prev_layer_lines{};
|
||||||
|
|
||||||
for (Layer *l : layers) {
|
for (Layer *l : layers) {
|
||||||
if (l->regions().empty()) {
|
std::vector<Linef> boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector<Linef>();
|
||||||
continue;
|
AABBTreeLines::LinesDistancer<Linef> prev_layer_boundary{std::move(boundary_lines)};
|
||||||
}
|
std::vector<ExtrusionLine> current_layer_lines;
|
||||||
struct Visitor {
|
for (const LayerRegion *layer_region : l->regions()) {
|
||||||
Visitor(const Params ¶ms) : params(params) {}
|
for (const ExtrusionEntity *extrusion : layer_region->perimeters().flatten().entities) {
|
||||||
void recursive_do(const ExtrusionEntityCollection &collection, const LayerRegion *region) {
|
Points extrusion_pts;
|
||||||
for (const ExtrusionEntity* entity : collection.entities)
|
extrusion->collect_points(extrusion_pts);
|
||||||
if (entity->is_collection())
|
float flow_width = get_flow_width(layer_region, extrusion->role());
|
||||||
this->recursive_do(*static_cast<const ExtrusionEntityCollection*>(entity), region);
|
auto annotated_points = estimate_points_properties<true, false, false, false>(extrusion_pts, prev_layer_lines, flow_width,
|
||||||
else {
|
params.bridge_distance);
|
||||||
append(extrusion_lines, to_short_lines(entity, params.bridge_distance));
|
for (size_t i = 0; i < annotated_points.size(); ++i) {
|
||||||
extrusions_widths.emplace(entity, get_flow_width(region, entity->role()));
|
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, extrusion};
|
||||||
|
|
||||||
|
const 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;
|
||||||
|
|
||||||
|
line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width,
|
||||||
|
nearest_prev_layer_line.curled_up_height, params);
|
||||||
|
|
||||||
|
current_layer_lines.push_back(line_out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const Params ¶ms;
|
|
||||||
std::unordered_map<const ExtrusionEntity*, float> extrusions_widths;
|
|
||||||
std::vector<ExtrusionLine> extrusion_lines;
|
|
||||||
} visitor(params);
|
|
||||||
|
|
||||||
for (const LayerRegion *region : l->regions())
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
visitor.recursive_do(region->perimeters(), region);
|
if (line.curled_up_height > 0.3f) {
|
||||||
|
l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)});
|
||||||
lce.flow_width_getter = [&](const ExtrusionLine &l) { return visitor.extrusions_widths[l.origin_entity]; };
|
}
|
||||||
|
}
|
||||||
lce.estimate_curling(visitor.extrusion_lines, l);
|
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
for (const ExtrusionLine &line : extrusion_lines) {
|
for (const ExtrusionLine &line : current_layer_lines) {
|
||||||
if (line.malformation > 0.3f) {
|
if (line.curled_up_height > 0.3f) {
|
||||||
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.malformation);
|
Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.curled_up_height);
|
||||||
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
prev_layer_lines = LD{current_layer_lines};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FILES
|
#ifdef DEBUG_FILES
|
||||||
@ -1039,6 +1010,5 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} //SupportableIssues End
|
} // namespace SupportSpotsGenerator
|
||||||
}
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ struct Params {
|
|||||||
// the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2]
|
// 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 = 12.0f; //mm
|
||||||
const float bridge_distance_decrease_by_curvature_factor = 10.0f; // allowed bridge distance = bridge_distance / (1 + this factor * curvature )
|
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 std::pair<float,float> malformation_distance_factors = std::pair<float, float> { 0.4, 1.2 };
|
||||||
const float max_malformation_factor = 10.0f;
|
const float max_malformation_factor = 10.0f;
|
||||||
|
|
||||||
const float min_distance_between_support_points = 3.0f; //mm
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
|
Loading…
Reference in New Issue
Block a user