From 88a1ddeb914909f42b8036a054281abec8d02623 Mon Sep 17 00:00:00 2001 From: Filip Sykala - NTB T15p Date: Wed, 18 Sep 2024 16:41:23 +0200 Subject: [PATCH] Remove points out of extended part. Allow multiple sample of the same 2d part of object in multiple heights --- src/libslic3r/SLA/SupportPointGenerator.cpp | 98 +++++++++++++++++---- 1 file changed, 83 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/SLA/SupportPointGenerator.cpp b/src/libslic3r/SLA/SupportPointGenerator.cpp index b8bb569e60..254a87cd8e 100644 --- a/src/libslic3r/SLA/SupportPointGenerator.cpp +++ b/src/libslic3r/SLA/SupportPointGenerator.cpp @@ -18,6 +18,10 @@ namespace { /// class NearPoints { + /// + /// Structure made for KDTree as function to + /// acess support point coordinate by index into global support point storage + /// struct PointAccessor { // multiple trees points into same data storage of all support points LayerSupportPoints *m_supports_ptr; @@ -39,21 +43,50 @@ public: explicit NearPoints(LayerSupportPoints* supports_ptr) : m_points(supports_ptr), m_tree(m_points) {} + /// + /// Remove support points from KD-Tree which lay out of expolygons + /// + /// Define area where could be support points + void remove_out_of(const ExPolygons &shapes) { + std::vector indices = get_indices(); + auto it = std::remove_if(indices.begin(), indices.end(), + [&pts = *m_points.m_supports_ptr, &shapes](size_t point_index) { + const Point& p = pts.at(point_index).position_on_layer; + return !std::any_of(shapes.begin(), shapes.end(), + [&p](const ExPolygon &shape) { + return shape.contains(p); + }); + }); + indices.erase(it, indices.end()); + m_tree.clear(); + m_tree.build(indices); // consume indices + } + + /// + /// Add point new support point into global storage of support points + /// and pointer into tree structure of nearest points + /// + /// New added point void add(LayerSupportPoint &&point) { + // IMPROVE: only add to existing tree, do not reconstruct tree + std::vector indices = get_indices(); LayerSupportPoints &pts = *m_points.m_supports_ptr; size_t index = pts.size(); pts.emplace_back(std::move(point)); - // IMPROVE: only add to existing tree, do not reconstruct tree - std::vector indices = m_tree.get_nodes(); // copy - auto it = std::remove_if(indices.begin(), indices.end(), - [index](size_t i) { return i >= index; }); - indices.erase(it, indices.end()); indices.push_back(index); m_tree.clear(); m_tree.build(indices); // consume indices } using CheckFnc = std::function; + /// + /// Iterate over support points in 2d radius and search any of fnc with True. + /// Made for check wheather surrounding supports support current point p. + /// + /// Center of search circle + /// Search circle radius + /// Function to check supports point + /// True wheny any of check function return true, otherwise False bool exist_true_in_radius(const Point &pos, coord_t radius, const CheckFnc &fnc) const { std::vector point_indices = find_nearby_points(m_tree, pos, radius); return std::any_of(point_indices.begin(), point_indices.end(), @@ -62,25 +95,41 @@ public: }); } + /// + /// Merge another tree structure into current one. + /// Made for connection of two mesh parts. + /// + /// Another near points void merge(NearPoints &&near_point) { // need to have same global storage of support points assert(m_points.m_supports_ptr == near_point.m_points.m_supports_ptr); // IMPROVE: merge trees instead of rebuild - std::vector indices = m_tree.get_nodes(); // copy - const std::vector& indices2 = near_point.m_tree.get_nodes(); - indices.insert(indices.end(), indices2.begin(), indices2.end()); - auto it = std::remove_if(indices.begin(), indices.end(), - [size = indices.size()](size_t i) { return i >= size; }); - indices.erase(it, indices.end()); - // remove duplicit indices + std::vector indices = get_indices(); + std::vector indices2 = near_point.get_indices(); + // merge + indices.insert(indices.end(), + std::move_iterator(indices2.begin()), + std::move_iterator(indices2.end())); + // remove duplicit indices - Diamond case std::sort(indices.begin(), indices.end()); - it = std::unique(indices.begin(), indices.end()); + auto it = std::unique(indices.begin(), indices.end()); indices.erase(it, indices.end()); // rebuild tree m_tree.clear(); m_tree.build(indices); // consume indices } + +private: + std::vector get_indices() const { + std::vector indices = m_tree.get_nodes(); // copy + // nodes in tree contain "max values for size_t" on unused leaf of tree, + // when count of indices is not exactly power of 2 + auto it = std::remove_if(indices.begin(), indices.end(), + [max_index = m_points.m_supports_ptr->size()](size_t i) { return i >= max_index; }); + indices.erase(it, indices.end()); + return indices; + } }; /// @@ -416,6 +465,23 @@ void prepare_supports_for_layer(LayerSupportPoints &supports, float layer_z, support.current_radius = static_cast(scale_(a.x() + t * (b.x() - a.x()))); } } + +/// +/// Near points do not have to contain support points out of part. +/// Due to be able support in same area again(overhang above another overhang) +/// Wanted Side effect, it supports thiny part of overhangs +/// +/// +/// +void remove_supports_out_of_part(NearPoints& part_grid, const LayerPart &part) { + + // Must be greater than surface texture and lower than self supporting area + // May be use maximal island distance + float delta = scale_(5.); + ExPolygons extend_shape = offset_ex(*part.shape, delta, ClipperLib::jtSquare); + part_grid.remove_out_of(extend_shape); +} + } // namespace #include "libslic3r/Execution/ExecutionSeq.hpp" @@ -581,8 +647,10 @@ LayerSupportPoints Slic3r::sla::generate_support_points( // first layer should have empty prev_part assert(layer_id != 0); const LayerParts &prev_layer_parts = layers[layer_id - 1].parts; - grids.push_back(create_part_grid(prev_layer_parts, part, prev_grids)); - support_part_overhangs(part, config, grids.back(), layer.print_z, maximal_radius); + NearPoints part_grid = create_part_grid(prev_layer_parts, part, prev_grids); + remove_supports_out_of_part(part_grid, part); + support_part_overhangs(part, config, part_grid, layer.print_z, maximal_radius); + grids.push_back(std::move(part_grid)); } } prev_grids = std::move(grids);