diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 7eb7ab56a4..39f828b558 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -1,35 +1,11 @@ #ifndef SRC_LIBSLIC3R_AABBTREELINES_HPP_ #define SRC_LIBSLIC3R_AABBTREELINES_HPP_ -#include "libslic3r/Point.hpp" -#include "libslic3r/EdgeGrid.hpp" #include "libslic3r/AABBTreeIndirect.hpp" #include "libslic3r/Line.hpp" namespace Slic3r { - -struct EdgeGridWrapper { - EdgeGridWrapper(coord_t edge_width, std::vector lines) : - lines(lines), edge_width(edge_width) { - - grid.create(this->lines, edge_width, true); - grid.calculate_sdf(); - } - - bool signed_distance(const Point &point, coordf_t point_width, coordf_t &dist_out) const { - coordf_t tmp_dist_out; - bool found = grid.signed_distance(point, edge_width, tmp_dist_out); - dist_out = tmp_dist_out - edge_width / 2 - point_width / 2; - return found; - } - - EdgeGrid::Grid grid; - std::vector lines; - coord_t edge_width; -}; - - namespace AABBTreeLines { namespace detail { diff --git a/src/libslic3r/SupportableIssuesSearch.cpp b/src/libslic3r/SupportableIssuesSearch.cpp index d8ff5b7172..55d883f0a9 100644 --- a/src/libslic3r/SupportableIssuesSearch.cpp +++ b/src/libslic3r/SupportableIssuesSearch.cpp @@ -557,11 +557,17 @@ private: // essentially doing nothing. int final_height_coords = local_coords.z(); while (final_height_coords > 0 - && this->access_cell(this->to_global_cell_coords(Vec3i(local_coords.x(), local_coords.y(), final_height_coords))).volume > 0) { + && this->access_cell( + this->to_global_cell_coords(Vec3i(local_coords.x(), local_coords.y(), final_height_coords))).volume + > 0) { final_height_coords--; } - Vec3f support_point = unscale(this->get_cell_center(this->to_global_cell_coords(Vec3i(local_coords.x(), local_coords.y(), final_height_coords)))).cast< - float>(); + Vec3f support_point = + unscale( + this->get_cell_center( + this->to_global_cell_coords( + Vec3i(local_coords.x(), local_coords.y(), final_height_coords)))).cast< + float>(); std::cout << " new support point: " << support_point.x() << " | " << support_point.y() << " | " << support_point.z() << std::endl; @@ -683,51 +689,76 @@ void debug_export(Issues issues, std::string file_name) { } #endif -EdgeGridWrapper compute_layer_edge_grid(const Layer *layer) { - float min_region_flow_width { 1.0f }; - for (const auto *region : layer->regions()) { - min_region_flow_width = std::min(min_region_flow_width, - region->flow(FlowRole::frExternalPerimeter).width()); - } - std::vector lines; - for (const LayerRegion *layer_region : layer->regions()) { - for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { - lines.push_back(Points { }); - ex_entity->collect_points(lines.back()); - } // ex_entity +struct LayerLinesDistancer { + std::vector lines; + AABBTreeIndirect::Tree<2, double> tree; + float line_width; - for (const ExtrusionEntity *ex_entity : layer_region->fills.entities) { - lines.push_back(Points { }); - ex_entity->collect_points(lines.back()); - } // ex_entity + LayerLinesDistancer(const Layer *layer) { + float min_region_flow_width { 1.0f }; + for (const auto *region : layer->regions()) { + min_region_flow_width = std::min(min_region_flow_width, + region->flow(FlowRole::frExternalPerimeter).width()); + } + for (const LayerRegion *layer_region : layer->regions()) { + for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { + Points points { }; + ex_entity->collect_points(points); + Vec2d prev = points.size() > 0 ? unscaled(points.front()) : Vec2d::Zero(); + for (size_t idx = 1; idx < points.size(); ++idx) { + lines.emplace_back(prev, unscaled(points[idx])); + } + } // ex_entity + + for (const ExtrusionEntity *ex_entity : layer_region->fills.entities) { + Points points { }; + ex_entity->collect_points(points); + Vec2d prev = points.size() > 0 ? unscaled(points.front()) : Vec2d::Zero(); + for (size_t idx = 1; idx < points.size(); ++idx) { + lines.emplace_back(prev, unscaled(points[idx])); + } + } // ex_entity + } + tree = AABBTreeLines::build_aabb_tree_over_indexed_lines(lines); + line_width = min_region_flow_width; } - return EdgeGridWrapper(scale_(min_region_flow_width), lines); -} + float distance_from_lines(const Point &point, float point_width) const { + Vec2d p = unscaled(point); + size_t hit_idx_out; + Vec2d hit_point_out; + auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, hit_idx_out, hit_point_out); + if (distance < 0) + return distance; + + distance = sqrt(distance); + return std::max(float(distance - point_width / 2 - line_width / 20), 0.0f); + } +}; //TODO needs revision -coordf_t get_flow_width(const LayerRegion *region, ExtrusionRole role) { +float get_flow_width(const LayerRegion *region, ExtrusionRole role) { switch (role) { case ExtrusionRole::erBridgeInfill: - return region->flow(FlowRole::frExternalPerimeter).scaled_width(); + return region->flow(FlowRole::frExternalPerimeter).width(); case ExtrusionRole::erExternalPerimeter: - return region->flow(FlowRole::frExternalPerimeter).scaled_width(); + return region->flow(FlowRole::frExternalPerimeter).width(); case ExtrusionRole::erGapFill: - return region->flow(FlowRole::frInfill).scaled_width(); + return region->flow(FlowRole::frInfill).width(); case ExtrusionRole::erPerimeter: - return region->flow(FlowRole::frPerimeter).scaled_width(); + return region->flow(FlowRole::frPerimeter).width(); case ExtrusionRole::erSolidInfill: - return region->flow(FlowRole::frSolidInfill).scaled_width(); + return region->flow(FlowRole::frSolidInfill).width(); case ExtrusionRole::erInternalInfill: - return region->flow(FlowRole::frInfill).scaled_width(); + return region->flow(FlowRole::frInfill).width(); case ExtrusionRole::erTopSolidInfill: - return region->flow(FlowRole::frTopSolidInfill).scaled_width(); + return region->flow(FlowRole::frTopSolidInfill).width(); default: - return region->flow(FlowRole::frPerimeter).scaled_width(); + return region->flow(FlowRole::frPerimeter).width(); } } -coordf_t get_max_allowed_distance(ExtrusionRole role, coordf_t flow_width, bool external_perimeters_first, +float get_max_allowed_distance(ExtrusionRole role, float flow_width, bool external_perimeters_first, const Params ¶ms) { // <= distance / flow_width (can be larger for perimeter, if not external perimeter first) if ((role == ExtrusionRole::erExternalPerimeter || role == ExtrusionRole::erOverhangPerimeter) && (external_perimeters_first)) { @@ -761,13 +792,13 @@ struct SegmentAccumulator { Issues check_extrusion_entity_stability(const ExtrusionEntity *entity, float print_z, const LayerRegion *layer_region, - const EdgeGridWrapper &supported_grid, const Params ¶ms) { + const LayerLinesDistancer &support_layer, const Params ¶ms) { Issues issues { }; if (entity->is_collection()) { for (const auto *e : static_cast(entity)->entities) { issues.add( - check_extrusion_entity_stability(e, print_z, layer_region, supported_grid, params)); + check_extrusion_entity_stability(e, print_z, layer_region, support_layer, params)); } } else { //single extrusion path, with possible varying parameters //prepare stack of points on the extrusion path. If there are long segments, additional points might be pushed onto the stack during the algorithm. @@ -788,9 +819,9 @@ Issues check_extrusion_entity_stability(const ExtrusionEntity *entity, float pri Point prev_point = points.top(); // prev point of the path. Initialize with first point. Vec3f prev_fpoint = to_vec3f(prev_point); - coordf_t flow_width = get_flow_width(layer_region, entity->role()); + float flow_width = get_flow_width(layer_region, entity->role()); bool external_perimters_first = layer_region->region().config().external_perimeters_first; - const coordf_t max_allowed_dist_from_prev_layer = get_max_allowed_distance(entity->role(), flow_width, + const float max_allowed_dist_from_prev_layer = get_max_allowed_distance(entity->role(), flow_width, external_perimters_first, params); while (!points.empty()) { @@ -799,8 +830,8 @@ Issues check_extrusion_entity_stability(const ExtrusionEntity *entity, float pri Vec3f fpoint = to_vec3f(point); float edge_len = (fpoint - prev_fpoint).norm(); - coordf_t dist_from_prev_layer { 0 }; - if (!supported_grid.signed_distance(point, flow_width, dist_from_prev_layer)) { // dist from prev layer not found, assume empty layer + float dist_from_prev_layer = support_layer.distance_from_lines(point, flow_width); + if (dist_from_prev_layer < 0) { // dist from prev layer not found, assume empty layer issues.supports_nedded.push_back(SupportPoint(fpoint, 1.0f)); supports_acc.reset(); } @@ -867,7 +898,7 @@ void distribute_layer_volume(const PrintObject *po, size_t layer_idx, for (const ExtrusionEntity *entity : static_cast(collections)->entities) { for (const Line &line : entity->as_polyline().lines()) { balance_grid.distribute_edge(line.a, line.b, layer->print_z, - unscale(get_flow_width(region, entity->role())), layer->height); + get_flow_width(region, entity->role()), layer->height); } } } @@ -875,7 +906,7 @@ void distribute_layer_volume(const PrintObject *po, size_t layer_idx, for (const ExtrusionEntity *entity : static_cast(collections)->entities) { for (const Line &line : entity->as_polyline().lines()) { balance_grid.distribute_edge(line.a, line.b, layer->print_z, - unscale(get_flow_width(region, entity->role())), layer->height); + get_flow_width(region, entity->role()), layer->height); } } } @@ -886,7 +917,7 @@ Issues check_layer_stability(const PrintObject *po, size_t layer_idx, bool full_ const Params ¶ms) { const Layer *layer = po->get_layer(layer_idx); //Prepare edge grid of previous layer, will be used to check if the extrusion path is supported - EdgeGridWrapper supported_grid = compute_layer_edge_grid(layer->lower_layer); + LayerLinesDistancer support_layer(layer->lower_layer); Issues issues { }; if (full_check) { // If full check; check stability of perimeters, gap fills, and bridges. @@ -895,7 +926,7 @@ Issues check_layer_stability(const PrintObject *po, size_t layer_idx, bool full_ for (const ExtrusionEntity *perimeter : static_cast(ex_entity)->entities) { issues.add( check_extrusion_entity_stability(perimeter, layer->print_z, layer_region, - supported_grid, params)); + support_layer, params)); } // perimeter } // ex_entity for (const ExtrusionEntity *ex_entity : layer_region->fills.entities) { @@ -904,7 +935,7 @@ Issues check_layer_stability(const PrintObject *po, size_t layer_idx, bool full_ || fill->role() == ExtrusionRole::erBridgeInfill) { issues.add( check_extrusion_entity_stability(fill, layer->print_z, layer_region, - supported_grid, + support_layer, params)); } } // fill @@ -919,7 +950,7 @@ Issues check_layer_stability(const PrintObject *po, size_t layer_idx, bool full_ || perimeter->role() == ExtrusionRole::erOverhangPerimeter) { issues.add( check_extrusion_entity_stability(perimeter, layer->print_z, layer_region, - supported_grid, params)); + support_layer, params)); }; // ex_perimeter } // perimeter } // ex_entity