From 6521b722749775b9c7809d38a5b454428e75932f Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Wed, 15 Feb 2023 17:23:31 +0100 Subject: [PATCH] Fix problems with adaptive infills, but the anchoring itself is not used on them Fix briding angles for octagram and hilberts curve --- src/libslic3r/Fill/Fill.cpp | 8 ++++ src/libslic3r/PrintObject.cpp | 72 +++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 16 deletions(-) diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 082cf93cc..043a2e34a 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -442,6 +442,14 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ for (SurfaceFill &surface_fill : surface_fills) { + //skip patterns for which additional input is nullptr + switch (surface_fill.params.pattern) { + case ipLightning: if (lightning_generator == nullptr) continue; break; + case ipAdaptiveCubic: if (adaptive_fill_octree == nullptr) continue; break; + case ipSupportCubic: if (support_fill_octree == nullptr) continue; break; + default: break; + } + // Create the filler object. std::unique_ptr f = std::unique_ptr(Fill::new_from_type(surface_fill.params.pattern)); f->set_bounding_box(bbox); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 63ce832d8..f1f377deb 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1638,6 +1638,17 @@ void PrintObject::bridge_over_infill() continue; } + auto region_has_anchorable_sparse_infill = [](const LayerRegion* layer_region) { + switch (layer_region->region().config().fill_pattern.value) { + case ipAdaptiveCubic: return false; + case ipSupportCubic: return false; + case ipLightning: return false; + default: break; + } + + return layer_region->region().config().fill_density.value < 100; + }; + // Gather lower layers sparse infill areas, to depth defined by used bridge flow Polygons lower_layers_sparse_infill{}; double bottom_z = layer->print_z - max_bridge_flow_height[candidates.first] - EPSILON; @@ -1660,7 +1671,7 @@ void PrintObject::bridge_over_infill() for (size_t region_idx : regions_under_to_check) { const LayerRegion *region = po->get_layer(i)->get_region(region_idx); - if (region->region().config().fill_density.value < 100) { + if (region_has_anchorable_sparse_infill(region)) { for (const Surface *surface : region->fill_surfaces().filter_by_type(stInternal)) { Polygons p = to_polygons(surface->expolygon); lower_layers_sparse_infill.insert(lower_layers_sparse_infill.end(), p.begin(), p.end()); @@ -1703,7 +1714,7 @@ void PrintObject::bridge_over_infill() closing(max_area, flow.scaled_width()); Polylines anchors = intersection_pl(lower_layer_polylines, max_area); - anchors = diff_pl(anchors, shrink(bridged_area, flow.scaled_width())); + anchors = diff_pl(anchors, bridged_area); Lines anchors_and_walls = to_lines(anchors); Lines tmp = to_lines(max_area); @@ -1716,9 +1727,9 @@ void PrintObject::bridge_over_infill() double bridging_angle = 0; { - AABBTreeLines::LinesDistancer lines_tree{anchors_and_walls}; + AABBTreeLines::LinesDistancer lines_tree{anchors.empty() ? anchors_and_walls : to_lines(anchors)}; - std::vector> directions_with_distances; + std::map counted_directions; for (const Polygon &p : bridged_area) { for (int point_idx = 0; point_idx < int(p.points.size()) - 1; ++point_idx) { Vec2d start = p.points[point_idx].cast(); @@ -1736,23 +1747,52 @@ void PrintObject::bridge_over_infill() angle -= PI; } angle += PI * 0.5; - directions_with_distances.emplace_back(angle, distance); + counted_directions[angle]++; } } } - double max_dist = directions_with_distances[0].second; - for (const auto &dir : directions_with_distances) { - max_dist = std::max(max_dist, dir.second); + + std::pair best_dir{0, 0}; + // sliding window accumulation + for (const auto &dir : counted_directions) { + int score_acc = 0; + double dir_acc = 0; + double window_start_angle = dir.first - PI * 0.2; + double window_end_angle = dir.first + PI * 0.2; + for (auto dirs_window = counted_directions.lower_bound(window_start_angle); + dirs_window != counted_directions.upper_bound(window_end_angle); dirs_window++) { + dir_acc += dirs_window->first * dirs_window->second; + score_acc += dirs_window->second; + } + // current span of directions is 0.5 PI to 1.5 PI (due to the aproach.). Edge values should also account for the + // opposite direction. + if (window_start_angle < 0.5 * PI) { + for (auto dirs_window = counted_directions.lower_bound(1.5 * PI - (0.5 * PI - window_start_angle)); + dirs_window != counted_directions.end(); dirs_window++) { + dir_acc += dirs_window->first * dirs_window->second; + score_acc += dirs_window->second; + } + } + if (window_start_angle > 1.5 * PI) { + for (auto dirs_window = counted_directions.begin(); + dirs_window != counted_directions.upper_bound(window_start_angle - 1.5 * PI); dirs_window++) { + dir_acc += dirs_window->first * dirs_window->second; + score_acc += dirs_window->second; + } + } + + if (score_acc > best_dir.second) { + best_dir = {dir_acc / score_acc, score_acc}; + } } - double acc = 0; - for (const auto &dir : directions_with_distances) { - bridging_angle += dir.first * (max_dist - dir.second); - acc += (max_dist - dir.second); - } - if (acc <= EPSILON || bridging_angle == 0) { + bridging_angle = best_dir.first; + if (bridging_angle == 0) { bridging_angle = 0.001; - } else { - bridging_angle /= acc; + } + switch (surface_to_region[candidate]->region().config().fill_pattern.value) { + case ipHilbertCurve: bridging_angle += 0.25 * PI; break; + case ipOctagramSpiral: bridging_angle += (1.0 / 16.0) * PI; break; + default: break; } }