diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 54fbb1fe64..ac3e054e77 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -196,6 +196,40 @@ public: //BBS: this function calculate the maximum void grid area of sparse infill of this layer. Just estimated value coordf_t get_sparse_infill_max_void_area(); + // FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold. + // Find the first item with Z value >= of an internal threshold of fn_higher_equal. + // If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size() + // If the initial idx is size_t(-1), then use binary search. + // Otherwise search linearly upwards. + template + static IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal) + { + auto size = int(end - begin); + if (size == 0) { + idx = 0; + } + else if (idx == IndexType(-1)) { + // First of the batch of layers per thread pool invocation. Use binary search. + int idx_low = 0; + int idx_high = std::max(0, size - 1); + while (idx_low + 1 < idx_high) { + int idx_mid = (idx_low + idx_high) / 2; + if (fn_higher_equal(begin[idx_mid])) + idx_high = idx_mid; + else + idx_low = idx_mid; + } + idx = fn_higher_equal(begin[idx_low]) ? idx_low : + (fn_higher_equal(begin[idx_high]) ? idx_high : size); + } + else { + // For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search. + while (int(idx) < size && !fn_higher_equal(begin[idx])) + ++idx; + } + return idx; + } + protected: friend class PrintObject; friend std::vector new_layers(PrintObject*, const std::vector&); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 351d124ac0..e8f6035d2e 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2834,41 +2834,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta return bottom_contacts; } -// FN_HIGHER_EQUAL: the provided object pointer has a Z value >= of an internal threshold. -// Find the first item with Z value >= of an internal threshold of fn_higher_equal. -// If no vec item with Z value >= of an internal threshold of fn_higher_equal is found, return vec.size() -// If the initial idx is size_t(-1), then use binary search. -// Otherwise search linearly upwards. -template -IndexType idx_higher_or_equal(IteratorType begin, IteratorType end, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal) -{ - auto size = int(end - begin); - if (size == 0) { - idx = 0; - } else if (idx == IndexType(-1)) { - // First of the batch of layers per thread pool invocation. Use binary search. - int idx_low = 0; - int idx_high = std::max(0, size - 1); - while (idx_low + 1 < idx_high) { - int idx_mid = (idx_low + idx_high) / 2; - if (fn_higher_equal(begin[idx_mid])) - idx_high = idx_mid; - else - idx_low = idx_mid; - } - idx = fn_higher_equal(begin[idx_low]) ? idx_low : - (fn_higher_equal(begin[idx_high]) ? idx_high : size); - } else { - // For the other layers of this batch of layers, search incrementally, which is cheaper than the binary search. - while (int(idx) < size && ! fn_higher_equal(begin[idx])) - ++ idx; - } - return idx; -} template IndexType idx_higher_or_equal(const std::vector& vec, IndexType idx, FN_HIGHER_EQUAL fn_higher_equal) { - return idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal); + return Layer::idx_higher_or_equal(vec.begin(), vec.end(), idx, fn_higher_equal); } // FN_LOWER_EQUAL: the provided object pointer has a Z value <= of an internal threshold. @@ -3353,7 +3322,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object( assert(! support_layer.polygons.empty() && support_layer.print_z >= m_slicing_params.raft_contact_top_z + EPSILON); // Find the overlapping object layers including the extra above / below gap. coordf_t z_threshold = support_layer.bottom_print_z() - gap_extra_below + EPSILON; - idx_object_layer_overlapping = idx_higher_or_equal( + idx_object_layer_overlapping = Layer::idx_higher_or_equal( object.layers().begin(), object.layers().end(), idx_object_layer_overlapping, [z_threshold](const Layer *layer){ return layer->print_z >= z_threshold; }); // Collect all the object layers intersecting with this layer. diff --git a/src/libslic3r/TreeSupport.cpp b/src/libslic3r/TreeSupport.cpp index 4dc4570774..c774bf1bec 100644 --- a/src/libslic3r/TreeSupport.cpp +++ b/src/libslic3r/TreeSupport.cpp @@ -1959,7 +1959,8 @@ coordf_t TreeSupport::calc_branch_radius(coordf_t base_radius, coordf_t mm_to_to return radius; } -ExPolygons avoid_object_remove_extra_small_parts(ExPolygons &expolys, const ExPolygons &avoid_region) { +template // RegionType could be ExPolygons or Polygons +ExPolygons avoid_object_remove_extra_small_parts(ExPolygons &expolys, const RegionType&avoid_region) { ExPolygons expolys_out; for (auto expoly : expolys) { auto expolys_avoid = diff_ex(expoly, avoid_region); @@ -1977,6 +1978,82 @@ ExPolygons avoid_object_remove_extra_small_parts(ExPolygons &expolys, const ExPo return expolys_out; } +Polygons TreeSupport::get_trim_support_regions( + const PrintObject& object, + SupportLayer* support_layer_ptr, + const coordf_t gap_extra_above, + const coordf_t gap_extra_below, + const coordf_t gap_xy) +{ + static const double sharp_tail_xy_gap = 0.2f; + static const double no_overlap_xy_gap = 0.2f; + double gap_xy_scaled = scale_(gap_xy); + SupportLayer& support_layer = *support_layer_ptr; + auto m_print_config = object.print()->config(); + + size_t idx_object_layer_overlapping = size_t(-1); + + auto is_layers_overlap = [](const SupportLayer& support_layer, const Layer& object_layer, coordf_t bridging_height = 0.f) -> bool { + if (std::abs(support_layer.print_z - object_layer.print_z) < EPSILON) + return true; + + coordf_t object_lh = bridging_height > EPSILON ? bridging_height : object_layer.height; + if (support_layer.print_z < object_layer.print_z && support_layer.print_z > object_layer.print_z - object_lh) + return true; + + if (support_layer.print_z > object_layer.print_z && support_layer.bottom_z() < object_layer.print_z - EPSILON) + return true; + + return false; + }; + + // Find the overlapping object layers including the extra above / below gap. + coordf_t z_threshold = support_layer.bottom_z() - gap_extra_below + EPSILON; + idx_object_layer_overlapping = Layer::idx_higher_or_equal( + object.layers().begin(), object.layers().end(), idx_object_layer_overlapping, + [z_threshold](const Layer* layer) { return layer->print_z >= z_threshold; }); + // Collect all the object layers intersecting with this layer. + Polygons polygons_trimming; + size_t i = idx_object_layer_overlapping; + for (; i < object.layers().size(); ++i) { + const Layer& object_layer = *object.layers()[i]; + if (object_layer.bottom_z() > support_layer.print_z + gap_extra_above - EPSILON) + break; + + bool is_overlap = is_layers_overlap(support_layer, object_layer); + for (const ExPolygon& expoly : object_layer.lslices) { + // BBS + bool is_sharptail = !intersection_ex({ expoly }, object_layer.sharp_tails).empty(); + coordf_t trimming_offset = is_sharptail ? scale_(sharp_tail_xy_gap) : + is_overlap ? gap_xy_scaled : + scale_(no_overlap_xy_gap); + polygons_append(polygons_trimming, offset({ expoly }, trimming_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS)); + } + } + if (!m_slicing_params.soluble_interface && m_object_config->thick_bridges) { + // Collect all bottom surfaces, which will be extruded with a bridging flow. + for (; i < object.layers().size(); ++i) { + const Layer& object_layer = *object.layers()[i]; + bool some_region_overlaps = false; + for (LayerRegion* region : object_layer.regions()) { + coordf_t bridging_height = region->region().bridging_height_avg(m_print_config); + if (object_layer.print_z - bridging_height > support_layer.print_z + gap_extra_above - EPSILON) + break; + some_region_overlaps = true; + + bool is_overlap = is_layers_overlap(support_layer, object_layer, bridging_height); + coordf_t trimming_offset = is_overlap ? gap_xy_scaled : scale_(no_overlap_xy_gap); + polygons_append(polygons_trimming, + offset(region->fill_surfaces.filter_by_type(stBottomBridge), trimming_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS)); + } + if (!some_region_overlaps) + break; + } + } + + return polygons_trimming; +} + void TreeSupport::draw_circles(const std::vector>& contact_nodes) { const PrintObjectConfig &config = m_object->config(); @@ -2171,7 +2248,8 @@ void TreeSupport::draw_circles(const std::vector>& contact_no roof_1st_layer = std::move(offset2_ex(roof_1st_layer, contact_dist_scaled, -contact_dist_scaled)); // avoid object - auto avoid_region_interface = m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr); + //ExPolygons avoid_region_interface = m_ts_data->get_collision(m_ts_data->m_xy_distance, layer_nr); + Polygons avoid_region_interface = get_trim_support_regions(*m_object, ts_layer, m_slicing_params.gap_object_support, m_slicing_params.gap_support_object, m_ts_data->m_xy_distance); if (has_circle_node) { roof_areas = avoid_object_remove_extra_small_parts(roof_areas, avoid_region_interface); roof_1st_layer = avoid_object_remove_extra_small_parts(roof_1st_layer, avoid_region_interface); @@ -2248,7 +2326,7 @@ void TreeSupport::draw_circles(const std::vector>& contact_no } }); -#if 1 + if (with_lightning_infill) { const bool global_lightning_infill = true; @@ -2320,7 +2398,7 @@ void TreeSupport::draw_circles(const std::vector>& contact_no else if (!with_infill) { // move the holes to contour so they can be well supported - // check if poly's contour intersects with expoly's contour + // check if poly's contour intersects with expoly's contour auto intersects_contour = [](Polygon poly, ExPolygon expoly, Point& pt_on_poly, Point& pt_on_expoly, Point& pt_far_on_poly, float dist_thresh = 0.01) { float min_dist = std::numeric_limits::max(); float max_dist = 0; @@ -2433,7 +2511,7 @@ void TreeSupport::draw_circles(const std::vector>& contact_no } } } -#endif + #ifdef SUPPORT_TREE_DEBUG_TO_SVG for (int layer_nr = m_object->layer_count() - 1; layer_nr >= 0; layer_nr--) { diff --git a/src/libslic3r/TreeSupport.hpp b/src/libslic3r/TreeSupport.hpp index 6119bc8906..1a706e433b 100644 --- a/src/libslic3r/TreeSupport.hpp +++ b/src/libslic3r/TreeSupport.hpp @@ -20,6 +20,7 @@ namespace Slic3r { class PrintObject; class TreeSupport; +class SupportLayer; struct LayerHeightData { @@ -494,6 +495,14 @@ private: Polygons contact_nodes_to_polygon(const std::vector& contact_nodes, Polygons layer_contours, int layer_nr, std::vector& radiis, std::vector& is_interface); coordf_t calc_branch_radius(coordf_t base_radius, size_t layers_to_top, size_t tip_layers, double diameter_angle_scale_factor); coordf_t calc_branch_radius(coordf_t base_radius, coordf_t mm_to_top, double diameter_angle_scale_factor); + + // similar to SupportMaterial::trim_support_layers_by_object + Polygons get_trim_support_regions( + const PrintObject& object, + SupportLayer* support_layer_ptr, + const coordf_t gap_extra_above, + const coordf_t gap_extra_below, + const coordf_t gap_xy); }; }