Added support for ignoring of tiny extrusion drops which are usually not worth the supports.
However, it is disabled, as it can currently result in unsupported large columns
This commit is contained in:
parent
15d0c55d54
commit
f17e3f2c8b
@ -41,7 +41,7 @@ public:
|
|||||||
|
|
||||||
bool is_external_perimeter() const {
|
bool is_external_perimeter() const {
|
||||||
assert(origin_entity != nullptr);
|
assert(origin_entity != nullptr);
|
||||||
return origin_entity->role() == erExternalPerimeter;
|
return origin_entity->role() == erExternalPerimeter || origin_entity->role() == erOverhangPerimeter;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2f a;
|
Vec2f a;
|
||||||
@ -364,8 +364,10 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
|||||||
return Vec3f(point.x(), point.y(), layer_z);
|
return Vec3f(point.x(), point.y(), layer_z);
|
||||||
};
|
};
|
||||||
float overhang_dist = tan(params.overhang_angle_deg * PI / 180.0f) * layer_region->layer()->height;
|
float overhang_dist = tan(params.overhang_angle_deg * PI / 180.0f) * layer_region->layer()->height;
|
||||||
float min_malformation_dist = tan(params.malformation_angle_span_deg.first * PI / 180.0f)*layer_region->layer()->height;
|
float min_malformation_dist = tan(params.malformation_angle_span_deg.first * PI / 180.0f)
|
||||||
float max_malformation_dist = tan(params.malformation_angle_span_deg.second * PI / 180.0f)*layer_region->layer()->height;
|
* layer_region->layer()->height;
|
||||||
|
float max_malformation_dist = tan(params.malformation_angle_span_deg.second * PI / 180.0f)
|
||||||
|
* layer_region->layer()->height;
|
||||||
|
|
||||||
Points points { };
|
Points points { };
|
||||||
entity->collect_points(points);
|
entity->collect_points(points);
|
||||||
@ -387,9 +389,14 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity->total_volume() < params.supportable_volume_threshold) {
|
||||||
|
checked_lines_out.insert(checked_lines_out.end(), lines.begin(), lines.end());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ExtrusionPropertiesAccumulator bridging_acc { };
|
ExtrusionPropertiesAccumulator bridging_acc { };
|
||||||
ExtrusionPropertiesAccumulator malformation_acc { };
|
ExtrusionPropertiesAccumulator malformation_acc { };
|
||||||
bridging_acc.add_distance(params.bridge_distance);
|
bridging_acc.add_distance(params.bridge_distance + 1.0f);
|
||||||
const float flow_width = get_flow_width(layer_region, entity->role());
|
const float flow_width = get_flow_width(layer_region, entity->role());
|
||||||
|
|
||||||
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) {
|
||||||
@ -433,8 +440,11 @@ void check_extrusion_entity_stability(const ExtrusionEntity *entity,
|
|||||||
}
|
}
|
||||||
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
|
if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) {
|
||||||
malformation_acc.add_distance(current_line.len);
|
malformation_acc.add_distance(current_line.len);
|
||||||
current_line.malformation += layer_region->layer()->height * (0.5f +
|
current_line.malformation += layer_region->layer()->height
|
||||||
1.5f * (malformation_acc.max_curvature / PI) * gauss(malformation_acc.distance, 5.0f, 1.0f, 0.2f));
|
* (0.5f
|
||||||
|
+
|
||||||
|
1.5f * (malformation_acc.max_curvature / PI)
|
||||||
|
* gauss(malformation_acc.distance, 5.0f, 1.0f, 0.2f));
|
||||||
} else {
|
} else {
|
||||||
malformation_acc.reset();
|
malformation_acc.reset();
|
||||||
}
|
}
|
||||||
@ -464,12 +474,13 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LinesDistancer> islands; // these search trees will be used to determine to which island does the extrusion begin
|
std::vector<LinesDistancer> islands; // these search trees will be used to determine to which island does the extrusion belong.
|
||||||
std::vector<std::vector<size_t>> island_extrusions; //final assigment of each extrusion to an island
|
std::vector<std::vector<size_t>> island_extrusions; //final assigment of each extrusion to an island.
|
||||||
// initliaze the search from external perimeters - at the beginning, there is island candidate for each external perimeter.
|
// initliaze the search from external perimeters - at the beginning, there is island candidate for each external perimeter.
|
||||||
// some of them will disappear (e.g. holes)
|
// some of them will disappear (e.g. holes)
|
||||||
for (size_t e = 0; e < extrusions.size(); ++e) {
|
for (size_t e = 0; e < extrusions.size(); ++e) {
|
||||||
if (layer_lines[extrusions[e].first].is_external_perimeter()) {
|
if (layer_lines[extrusions[e].first].origin_entity->is_loop() &&
|
||||||
|
layer_lines[extrusions[e].first].is_external_perimeter()) {
|
||||||
std::vector<ExtrusionLine> copy(extrusions[e].second - extrusions[e].first);
|
std::vector<ExtrusionLine> copy(extrusions[e].second - extrusions[e].first);
|
||||||
for (size_t ex_line_idx = extrusions[e].first; ex_line_idx < extrusions[e].second; ++ex_line_idx) {
|
for (size_t ex_line_idx = extrusions[e].first; ex_line_idx < extrusions[e].second; ++ex_line_idx) {
|
||||||
copy[ex_line_idx - extrusions[e].first] = layer_lines[ex_line_idx];
|
copy[ex_line_idx - extrusions[e].first] = layer_lines[ex_line_idx];
|
||||||
@ -478,8 +489,8 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
|||||||
island_extrusions.push_back( { e });
|
island_extrusions.push_back( { e });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// backup code if islands not found - this can currently happen, as external perimeters may be also pure overhang perimeters, and there is no
|
|
||||||
// way to distinguish external extrusions with total certainty.
|
// backup code if islands not found
|
||||||
// If that happens, just make the first extrusion into island - it may be wrong, but it won't crash.
|
// If that happens, just make the first extrusion into island - it may be wrong, but it won't crash.
|
||||||
if (islands.empty() && !extrusions.empty()) {
|
if (islands.empty() && !extrusions.empty()) {
|
||||||
std::vector<ExtrusionLine> copy(extrusions[0].second - extrusions[0].first);
|
std::vector<ExtrusionLine> copy(extrusions[0].second - extrusions[0].first);
|
||||||
@ -492,9 +503,13 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
|||||||
|
|
||||||
// assign non external extrusions to islands
|
// assign non external extrusions to islands
|
||||||
for (size_t e = 0; e < extrusions.size(); ++e) {
|
for (size_t e = 0; e < extrusions.size(); ++e) {
|
||||||
if (!layer_lines[extrusions[e].first].is_external_perimeter()) {
|
if (!layer_lines[extrusions[e].first].origin_entity->is_loop() ||
|
||||||
|
!layer_lines[extrusions[e].first].is_external_perimeter()) {
|
||||||
bool island_assigned = false;
|
bool island_assigned = false;
|
||||||
for (size_t i = 0; i < islands.size(); ++i) {
|
for (size_t i = 0; i < islands.size(); ++i) {
|
||||||
|
if (island_extrusions[i].empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
size_t _idx = 0;
|
size_t _idx = 0;
|
||||||
Vec2f _pt = Vec2f::Zero();
|
Vec2f _pt = Vec2f::Zero();
|
||||||
if (islands[i].signed_distance_from_lines(layer_lines[extrusions[e].first].a, _idx, _pt) < 0) {
|
if (islands[i].signed_distance_from_lines(layer_lines[extrusions[e].first].a, _idx, _pt) < 0) {
|
||||||
@ -509,24 +524,6 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// merge islands which are embedded within each other (mainly holes)
|
|
||||||
for (size_t i = 0; i < islands.size(); ++i) {
|
|
||||||
if (islands[i].get_lines().empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (size_t j = 0; j < islands.size(); ++j) {
|
|
||||||
if (islands[j].get_lines().empty() || i == j) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
size_t _idx;
|
|
||||||
Vec2f _pt;
|
|
||||||
if (islands[i].signed_distance_from_lines(islands[j].get_line(0).a, _idx, _pt) < 0) {
|
|
||||||
island_extrusions[i].insert(island_extrusions[i].end(), island_extrusions[j].begin(),
|
|
||||||
island_extrusions[j].end());
|
|
||||||
island_extrusions[j].clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float flow_width = get_flow_width(layer->regions()[0], erExternalPerimeter);
|
float flow_width = get_flow_width(layer->regions()[0], erExternalPerimeter);
|
||||||
// after filtering the layer lines into islands, build the result LayerIslands structure.
|
// after filtering the layer lines into islands, build the result LayerIslands structure.
|
||||||
@ -559,7 +556,8 @@ std::tuple<LayerIslands, PixelGrid> reckon_islands(
|
|||||||
// Bottom infill lines can be quite long, and algined, so the middle approximaton used above does not work
|
// Bottom infill lines can be quite long, and algined, so the middle approximaton used above does not work
|
||||||
Vec2f dir = (line.b - line.a).normalized();
|
Vec2f dir = (line.b - line.a).normalized();
|
||||||
float segment_length = flow_width; // segments of size flow_width
|
float segment_length = flow_width; // segments of size flow_width
|
||||||
for (float segment_middle_dist = std::min(line.len, segment_length * 0.5f); segment_middle_dist < line.len;
|
for (float segment_middle_dist = std::min(line.len, segment_length * 0.5f);
|
||||||
|
segment_middle_dist < line.len;
|
||||||
segment_middle_dist += segment_length) {
|
segment_middle_dist += segment_length) {
|
||||||
Vec2f segment_middle = line.a + segment_middle_dist * dir;
|
Vec2f segment_middle = line.a + segment_middle_dist * dir;
|
||||||
island.sticking_second_moment_of_area_accumulator += segment_length * flow_width
|
island.sticking_second_moment_of_area_accumulator += segment_length * flow_width
|
||||||
@ -723,7 +721,8 @@ public:
|
|||||||
}
|
}
|
||||||
Vec3f centroid = centroid_accumulator / area;
|
Vec3f centroid = centroid_accumulator / area;
|
||||||
float extreme_fiber_dist = line_alg::distance_to(
|
float extreme_fiber_dist = line_alg::distance_to(
|
||||||
Linef(centroid.head<2>().cast<double>(), (centroid.head<2>() + Vec2f(line_dir.y(), -line_dir.x())).cast<double>()),
|
Linef(centroid.head<2>().cast<double>(),
|
||||||
|
(centroid.head<2>() + Vec2f(line_dir.y(), -line_dir.x())).cast<double>()),
|
||||||
extreme_point.head<2>().cast<double>());
|
extreme_point.head<2>().cast<double>());
|
||||||
float elastic_section_modulus = area * directional_xy_variance / extreme_fiber_dist;
|
float elastic_section_modulus = area * directional_xy_variance / extreme_fiber_dist;
|
||||||
|
|
||||||
@ -771,7 +770,8 @@ public:
|
|||||||
|
|
||||||
Vec2f bed_weight_arm = (mass_centroid.head<2>() - bed_centroid.head<2>());
|
Vec2f bed_weight_arm = (mass_centroid.head<2>() - bed_centroid.head<2>());
|
||||||
float bed_weight_arm_len = bed_weight_arm.norm();
|
float bed_weight_arm_len = bed_weight_arm.norm();
|
||||||
float bed_weight_dir_xy_variance = compute_directional_xy_variance(bed_weight_arm, this->sticking_centroid_accumulator,
|
float bed_weight_dir_xy_variance = compute_directional_xy_variance(bed_weight_arm,
|
||||||
|
this->sticking_centroid_accumulator,
|
||||||
this->sticking_second_moment_of_area_accumulator,
|
this->sticking_second_moment_of_area_accumulator,
|
||||||
this->sticking_second_moment_of_area_covariance_accumulator,
|
this->sticking_second_moment_of_area_covariance_accumulator,
|
||||||
this->sticking_area);
|
this->sticking_area);
|
||||||
@ -1019,6 +1019,13 @@ Issues check_global_stability(SupportGridFilter supports_presence_grid,
|
|||||||
for (size_t island_idx = 0; island_idx < islands_graph[layer_idx].islands.size(); ++island_idx) {
|
for (size_t island_idx = 0; island_idx < islands_graph[layer_idx].islands.size(); ++island_idx) {
|
||||||
const Island &island = islands_graph[layer_idx].islands[island_idx];
|
const Island &island = islands_graph[layer_idx].islands[island_idx];
|
||||||
ObjectPart &part = active_object_parts.access(prev_island_to_object_part_mapping[island_idx]);
|
ObjectPart &part = active_object_parts.access(prev_island_to_object_part_mapping[island_idx]);
|
||||||
|
|
||||||
|
//skip small drops of material - if they grow in size, they will be supported in next layers;
|
||||||
|
// if they dont grow, they are not worthy
|
||||||
|
if (part.get_volume() < params.supportable_volume_threshold) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
IslandConnection &weakest_conn = prev_island_weakest_connection[island_idx];
|
IslandConnection &weakest_conn = prev_island_weakest_connection[island_idx];
|
||||||
#ifdef DETAILED_DEBUG_LOGS
|
#ifdef DETAILED_DEBUG_LOGS
|
||||||
weakest_conn.print_info("weakest connection info: ");
|
weakest_conn.print_info("weakest connection info: ");
|
||||||
@ -1132,7 +1139,7 @@ std::tuple<Issues, std::vector<LayerIslands>> check_extrusions_and_build_graph(c
|
|||||||
}
|
}
|
||||||
for (const auto &line : layer_lines) {
|
for (const auto &line : layer_lines) {
|
||||||
if (line.malformation > 0.0f) {
|
if (line.malformation > 0.0f) {
|
||||||
Vec3f color = value_to_rgbf(0, 1.0f, line.malformation);
|
Vec3f color = value_to_rgbf(-EPSILON, 1.0f, line.malformation);
|
||||||
fprintf(malform_f, "v %f %f %f %f %f %f\n", line.b[0],
|
fprintf(malform_f, "v %f %f %f %f %f %f\n", line.b[0],
|
||||||
line.b[1], layer->slice_z, color[0], color[1], color[2]);
|
line.b[1], layer->slice_z, color[0], color[1], color[2]);
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,17 @@ 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 = 15.0f; //mm
|
const float bridge_distance = 12.0f; //mm
|
||||||
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (this factor * (curvature / PI) )
|
const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) )
|
||||||
const float overhang_angle_deg = 80.0f;
|
const float overhang_angle_deg = 80.0f;
|
||||||
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
|
const std::pair<float,float> malformation_angle_span_deg = std::pair<float, float> { 45.0f, 80.0f };
|
||||||
|
|
||||||
const float min_distance_between_support_points = 3.0f; //mm
|
const float min_distance_between_support_points = 3.0f; //mm
|
||||||
const float support_points_interface_radius = 1.5f; // mm
|
const float support_points_interface_radius = 1.5f; // mm
|
||||||
|
|
||||||
|
// NOTE: Currently disabled, does not work correctly due to inability of the algorithm to correctly detect islands at each layer
|
||||||
|
const float supportable_volume_threshold = 0.0f; // mm^3
|
||||||
|
|
||||||
std::string filament_type;
|
std::string filament_type;
|
||||||
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position.
|
||||||
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
const float max_acceleration = 9 * 1000.0f; // mm/s^2 ; max acceleration of object (bed) in XY (NOTE: The max hit is received by the object in the jerk phase, so the usual machine limits are too low)
|
||||||
|
Loading…
Reference in New Issue
Block a user