From 5d2b3cfc1ec8efe96ca3547760c89ed43a9bcc33 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Tue, 11 May 2021 20:19:05 +0200 Subject: [PATCH] =?UTF-8?q?=EF=BB=BFAdd=20outline=20angle=20rule=20to=20de?= =?UTF-8?q?cide=20when=20support=20centre=20line?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SLA/SupportIslands/LineUtils.cpp | 10 + .../SLA/SupportIslands/LineUtils.hpp | 11 +- .../SLA/SupportIslands/SampleConfig.hpp | 5 + .../SLA/SupportIslands/SampleIslandUtils.cpp | 200 +++++++++++++----- .../SLA/SupportIslands/SampleIslandUtils.hpp | 18 ++ .../SLA/SupportIslands/SupportIslandPoint.cpp | 3 + .../SLA/SupportIslands/SupportIslandPoint.hpp | 3 + .../SLA/SupportIslands/VoronoiGraphUtils.cpp | 132 +++++++----- .../SLA/SupportIslands/VoronoiGraphUtils.hpp | 9 + tests/sla_print/sla_supptgen_tests.cpp | 6 +- 10 files changed, 282 insertions(+), 115 deletions(-) diff --git a/src/libslic3r/SLA/SupportIslands/LineUtils.cpp b/src/libslic3r/SLA/SupportIslands/LineUtils.cpp index 8da1f48036..a9bc659382 100644 --- a/src/libslic3r/SLA/SupportIslands/LineUtils.cpp +++ b/src/libslic3r/SLA/SupportIslands/LineUtils.cpp @@ -306,6 +306,16 @@ bool LineUtils::belongs(const Line &line, const Point &point, double benevolence return false; } +Slic3r::Point LineUtils::direction(const Line &line) +{ + return line.b - line.a; +} + +Slic3r::Point LineUtils::middle(const Line &line) { + // division before adding to prevent data type overflow + return line.a / 2 + line.b / 2; +} + double LineUtils::foot(const Line &line, const Point &point) { Vec2d a = line.a.cast(); diff --git a/src/libslic3r/SLA/SupportIslands/LineUtils.hpp b/src/libslic3r/SLA/SupportIslands/LineUtils.hpp index 23e1cbe79e..d48d988d9c 100644 --- a/src/libslic3r/SLA/SupportIslands/LineUtils.hpp +++ b/src/libslic3r/SLA/SupportIslands/LineUtils.hpp @@ -127,8 +127,15 @@ public: /// Direction vector is represented as point /// /// input line - /// line direction - static Point direction(const Line &line) { return line.b - line.a; } + /// line direction | b - a + static Point direction(const Line &line); + + /// + /// middle point, center of line + /// + /// + /// ceneter of line | a+b / 2 + static Point middle(const Line &line); /// /// Calculate foot point in maner of Geometry::foot_pt diff --git a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp index 6d4546bc89..edb09cdf8f 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp +++ b/src/libslic3r/SLA/SupportIslands/SampleConfig.hpp @@ -29,6 +29,11 @@ struct SampleConfig // Must be bigger than minimal_distance_from_outline coord_t maximal_distance_from_outline = 1.;// [nano meter] + // When angle on outline is smaller than max_interesting_angle + // than create unmovable support point. + // Should be in range from Pi/2 to Pi + double max_interesting_angle = 2. / 3. * M_PI; // [radians] + // Distinguish when to add support point on VD outline point(center line sample) // MUST be bigger than minimal_distance_from_outline coord_t minimal_support_distance = 0; diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp index db32683fcd..6bf7bf07d0 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp +++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.cpp @@ -23,6 +23,7 @@ //#define SLA_SAMPLE_ISLAND_UTILS_STORE_VORONOI_GRAPH_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG +//#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNE_VD_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG //#define SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNED_TO_SVG @@ -404,7 +405,15 @@ void SampleIslandUtils::align_samples(SupportIslandPoints &samples, const ExPolygon & island, const SampleConfig & config) { - assert(samples.size() > 2); + bool exist_moveable = false; + for (const auto &sample : samples) { + if (sample->can_move()) { + exist_moveable = true; + break; + } + } + if (!exist_moveable) return; + size_t count_iteration = config.count_iteration; // copy coord_t max_move = 0; while (--count_iteration > 1) { @@ -440,7 +449,6 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples, const ExPolygon & island, const SampleConfig & config) { - assert(samples.size() > 2); using VD = Slic3r::Geometry::VoronoiDiagram; VD vd; Slic3r::Points points = SampleIslandUtils::to_points(samples); @@ -463,6 +471,28 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples, // create voronoi diagram with points construct_voronoi(points.begin(), points.end(), &vd); +#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNE_VD_TO_SVG + static int vd_counter = 0; + BoundingBox bbox(island); + std::string name = "align_VD_" + std::to_string(vd_counter++) + ".svg"; + SVG svg(name.c_str(), bbox); + svg.draw(island); + for (const Point &point : points) { + size_t index = &point - &points.front(); + svg.draw(point, "black", config.head_radius); + svg.draw_text(point + Point(config.head_radius,0), std::to_string(index).c_str(), "black"); + } + Lines island_lines = to_lines(island); + svg.draw(island_lines, "blue"); + for (const auto &edge: vd.edges()) { + std::optional line = + VoronoiGraphUtils::to_line(edge, points, config.max_distance); + if (!line.has_value()) continue; + svg.draw(*line, "green", 1e6); + } + svg.Close(); +#endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNE_VD_TO_SVG + size_t max_move_index = -1; for (const VD::cell_type &cell : vd.cells()) { SupportIslandPointPtr &sample = samples[cell.source_index()]; @@ -482,12 +512,9 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples, break; } } - assert(island_cell != nullptr); - - - Point center = island_cell->centroid(); - /* - { + assert(island_cell != nullptr); + Point center = island_cell->centroid(); + /*{ SVG cell_svg("island_cell.svg", island_cell->points); cell_svg.draw(cell_polygon, "lightgray"); cell_svg.draw(points, "darkgray", config.head_radius); @@ -504,7 +531,10 @@ coord_t SampleIslandUtils::align_once(SupportIslandPoints &samples, svg.draw(center, color_wanted_point, config.head_radius); // wanted position #endif // SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG coord_t act_move = sample->move(center); - if (max_move < act_move) max_move = act_move; + if (max_move < act_move) { + max_move = act_move; + max_move_index = cell.source_index(); + } #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGN_ONCE_TO_SVG svg.draw(sample->point, color_new_point, config.head_radius); svg.draw_text(sample->point+Point(config.head_radius,0), SupportIslandPoint::to_string(sample->type).c_str(), color_new_point.c_str()); @@ -930,6 +960,7 @@ SupportIslandPoints SampleIslandUtils::sample_expath( if (position.has_value()) { points.push_back(create_no_move_point( *position, SupportIslandPoint::Type::center_line_start)); + // move nodes to done set VoronoiGraph::Nodes start_path; for (const auto &node : path.nodes) { if (node == position->neighbor->node) break; @@ -978,16 +1009,11 @@ void SampleIslandUtils::sample_field(VoronoiGraph::Position &field_start, // Erode island to not sampled island around border, // minimal value must be -config.minimal_distance_from_outline - Polygons polygons = offset(field.border, -2.f * config.minimal_distance_from_outline, + Polygons polygons = offset(field.border, + -2.f * config.minimal_distance_from_outline, ClipperLib::jtSquare); if (polygons.empty()) return; - - auto inner = std::make_shared(polygons.front()); - for (size_t i = 1; i < polygons.size(); ++i) { - Polygon &hole = polygons[i]; - inner->holes.push_back(hole); - } - + auto inner = std::make_shared(field.inner); Points inner_points = sample_expolygon(*inner, config.max_distance); std::transform(inner_points.begin(), inner_points.end(), std::back_inserter(points), [&](const Point &point) { @@ -1008,6 +1034,7 @@ std::optional SampleIslandUtils::sample_center( coord_t support_in; bool use_new_start = true; bool is_continous = false; + while (use_new_start || neighbor->max_width() <= config.max_width_for_center_support_line) { // !! do not check max width for new start, it could be wide to tiny change if (use_new_start) { @@ -1033,7 +1060,7 @@ std::optional SampleIslandUtils::sample_center( double ratio = support_in / neighbor->length(); VoronoiGraph::Position position(neighbor, ratio); results.push_back(std::make_unique( - position, &config, SupportIslandPoint::Type::center_line)); + position, &config, SupportIslandPoint::Type::center_line1)); support_in += config.max_distance; is_continous = true; } @@ -1051,24 +1078,24 @@ std::optional SampleIslandUtils::sample_center( next_neighbor = &node_neighbor; continue; } - coord_t next_support_in = (support_in >= config.half_distance) ? - support_in : (config.max_distance - support_in); - new_starts.emplace_back(&node_neighbor, next_support_in, path); // search in side branch + new_starts.emplace_back(&node_neighbor, support_in, path); // search in side branch } + if (next_neighbor == nullptr) { - // no neighbor to continue - VoronoiGraph::Nodes path_reverse = path; // copy - std::reverse(path_reverse.begin(), path_reverse.end()); - coord_t width = 2 * config.minimal_distance_from_outline; - coord_t distance = config.maximal_distance_from_outline; - auto position_opt = create_position_on_path(path_reverse, lines, width, distance); - if (position_opt.has_value()) { - if (is_continous && config.max_distance < (support_in+distance) ) { - // one support point should be enough - // when max_distance > maximal_distance_from_outline - results.pop_back(); // remove support point + if (neighbor->min_width() != 0) { + std::reverse(path.begin(), path.end()); + auto position_opt = create_position_on_path(path, support_in / 2); + if (position_opt.has_value()) { + results.push_back( + std::make_unique( + *position_opt, &config, + SupportIslandPoint::Type::center_line3)); } - create_sample_center_end(*position_opt, results, new_starts, config); + } else { + // no neighbor to continue + create_sample_center_end(*neighbor, is_continous, path, + support_in, lines, results, + new_starts, config); } use_new_start = true; } else { @@ -1087,12 +1114,47 @@ std::optional SampleIslandUtils::sample_center( double ratio = support_in / edge_length; VoronoiGraph::Position position(neighbor, ratio); results.push_back(std::make_unique( - position, &config,SupportIslandPoint::Type::center_line)); + position, &config, SupportIslandPoint::Type::center_line2)); support_in += config.max_distance; } return result; } +void SampleIslandUtils::create_sample_center_end( + const VoronoiGraph::Node::Neighbor &neighbor, + bool is_continous, + const VoronoiGraph::Nodes & path, + coord_t support_in, + const Lines & lines, + SupportIslandPoints & results, + CenterStarts & new_starts, + const SampleConfig & config) +{ + // last neighbor? + if (neighbor.min_width() != 0) return; + + // sharp corner? + double angle = VoronoiGraphUtils::outline_angle(neighbor, lines); + if (angle > config.max_interesting_angle) return; + + // exist place for support? + VoronoiGraph::Nodes path_reverse = path; // copy + std::reverse(path_reverse.begin(), path_reverse.end()); + coord_t width = 2 * config.minimal_distance_from_outline; + coord_t distance = config.maximal_distance_from_outline; + auto position_opt = create_position_on_path(path_reverse, lines, width, distance); + if (!position_opt.has_value()) return; + + // check if exist popable result + if (is_continous && config.max_distance < (support_in + distance)) { + // one support point should be enough + // when max_distance > maximal_distance_from_outline + results.pop_back(); // remove support point + } + + create_sample_center_end(*position_opt, results, new_starts, config); +} + void SampleIslandUtils::create_sample_center_end( const VoronoiGraph::Position &position, SupportIslandPoints & results, @@ -1110,8 +1172,8 @@ void SampleIslandUtils::create_sample_center_end( Point diff = point - res->point; if (abs(diff.x()) > minimal_support_distance) continue; if (abs(diff.y()) > minimal_support_distance) continue; - near_no_move.push_back( - &*res); // create raw pointer, used only in function scope + // create raw pointer, used only in function scope + near_no_move.push_back(&*res); } std::map distances; @@ -1412,6 +1474,8 @@ SampleIslandUtils::Field SampleIslandUtils::create_field( } field.source_indexe_for_change = source_indexe_for_change; field.source_indexes = std::move(source_indexes); + std::tie(field.inner, field.field_2_inner) = + outline_offset(field.border, config.minimal_distance_from_outline); #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG { @@ -1446,6 +1510,8 @@ SampleIslandUtils::outline_offset(const Slic3r::ExPolygon &island, // TODO: Connect indexes for convert during creation of offset // !! this implementation was fast for develop BUT NOT for running !! + const double angle_tolerace = 1e-4; + const double distance_tolerance = 20.; Lines island_lines = to_lines(island); Lines offset_lines = to_lines(offseted); // Convert index map from island index to offseted index @@ -1459,15 +1525,23 @@ SampleIslandUtils::outline_offset(const Slic3r::ExPolygon &island, Vec2d dir2 = LineUtils::direction(offset_line).cast(); dir2.normalize(); double angle = acos(dir1.dot(dir2)); - if (fabs(angle) < 1e-4) { // in similar direction - Point middle = offset_line.a / 2 + offset_line.b / 2; - double distance = island_line.perp_distance_to(middle); - if (fabs(distance - offset_distance) < 20) { - // found offseted line - converter[island_line_index] = offset_line_index; - break; - } - } + // not similar direction + + if (fabs(angle) > angle_tolerace) continue; + + Point offset_middle = LineUtils::middle(offset_line); + Point island_middle = LineUtils::middle(island_line); + Point diff_middle = offset_middle - island_middle; + if (fabs(diff_middle.x()) > 2 * offset_distance || + fabs(diff_middle.y()) > 2 * offset_distance) continue; + + double distance = island_line.perp_distance_to(offset_middle); + if (fabs(distance - offset_distance) > distance_tolerance) + continue; + + // found offseted line + converter[island_line_index] = offset_line_index; + break; } } @@ -1480,10 +1554,6 @@ SupportIslandPoints SampleIslandUtils::sample_outline( const ExPolygon &border = field.border; const Polygon &contour = border.contour; assert(field.source_indexes.size() >= contour.size()); - // convert map from field index to inner(line index) - std::map field_2_inner; - ExPolygon inner; - std::tie(inner, field_2_inner) = outline_offset(border, config.minimal_distance_from_outline); coord_t max_align_distance = config.max_align_distance; coord_t sample_distance = config.outline_sample_distance; SupportIslandPoints result; @@ -1574,6 +1644,9 @@ SupportIslandPoints SampleIslandUtils::sample_outline( } }; + + // convert map from field index to inner(line index) + const std::map& field_2_inner = field.field_2_inner; const size_t& change_index = field.source_indexe_for_change; auto sample_polygon = [&](const Polygon &polygon, const Polygon &inner_polygon, @@ -1630,11 +1703,11 @@ SupportIslandPoints SampleIslandUtils::sample_outline( }; size_t index_offset = 0; - sample_polygon(contour, inner.contour, index_offset); + sample_polygon(contour, field.inner.contour, index_offset); index_offset = contour.size(); for (size_t hole_index = 0; hole_index < border.holes.size(); ++hole_index) { const Polygon &hole = border.holes[hole_index]; - sample_polygon(hole, inner.holes[hole_index], index_offset); + sample_polygon(hole, field.inner.holes[hole_index], index_offset); index_offset += hole.size(); } return result; @@ -1646,7 +1719,8 @@ void SampleIslandUtils::draw(SVG & svg, bool draw_field_source_indexes) { const char *field_color = "red"; - const char *border_line_color = "blue"; + const char *border_line_color = "blue"; + const char *inner_line_color = "green"; const char *source_index_text_color = "blue"; svg.draw(field.border, field_color); Lines border_lines = to_lines(field.border); @@ -1657,10 +1731,27 @@ void SampleIslandUtils::draw(SVG & svg, size_t index = &line - &border_lines.front(); // start of holes if (index >= field.source_indexes.size()) break; - Point middle_point = (line.a + line.b) / 2; + Point middle_point = LineUtils::middle(line); std::string text = std::to_string(field.source_indexes[index]); + auto item = field.field_2_inner.find(index); + if (item != field.field_2_inner.end()) { + text += " inner " + std::to_string(item->second); + } svg.draw_text(middle_point, text.c_str(), source_index_text_color); } + + // draw inner + Lines inner_lines = to_lines(field.inner); + LineUtils::draw(svg, inner_lines, inner_line_color, 0., + draw_border_line_indexes); + if (draw_field_source_indexes) + for (auto &line : inner_lines) { + size_t index = &line - &inner_lines.front(); + Point middle_point = LineUtils::middle(line); + std::string text = std::to_string(index); + svg.draw_text(middle_point, text.c_str(), inner_line_color); + } + } void SampleIslandUtils::draw(SVG & svg, @@ -1690,6 +1781,9 @@ bool SampleIslandUtils::is_visualization_disabled() #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_INITIAL_SAMPLE_POSITION_TO_SVG return false; #endif +#ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_ALIGNE_VD_TO_SVG + return false; +#endif #ifdef SLA_SAMPLE_ISLAND_UTILS_STORE_FIELD_TO_SVG return false; #endif diff --git a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp index 1b35aa77db..5e4bc5bcaf 100644 --- a/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp +++ b/src/libslic3r/SLA/SupportIslands/SampleIslandUtils.hpp @@ -281,6 +281,19 @@ public: const SampleConfig & config); private: + /// + /// + /// + static void create_sample_center_end( + const VoronoiGraph::Node::Neighbor &neighbor, + bool is_continous, + const VoronoiGraph::Nodes & path, + coord_t support_in, + const Lines & lines, + SupportIslandPoints & results, + CenterStarts & new_starts, + const SampleConfig & config); + /// /// Check near supports if no exists there add to results /// @@ -313,6 +326,11 @@ public : std::vector source_indexes; // value for source index of change from wide to tiny part of island size_t source_indexe_for_change; + + // inner part of field + ExPolygon inner; + // map to convert field index to inner index + std::map field_2_inner; }; /// diff --git a/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp b/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp index 692572b7aa..20f58e6502 100644 --- a/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp +++ b/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.cpp @@ -50,6 +50,9 @@ std::string SupportIslandPoint::to_string(const Type &type) {{Type::one_center_point, "one_center_point"}, {Type::two_points,"two_points"}, {Type::center_line, "center_line"}, + {Type::center_line1, "center_line1"}, + {Type::center_line2, "center_line2"}, + {Type::center_line3, "center_line3"}, {Type::center_line_end, "center_line_end"}, {Type::center_line_end2, "center_line_end2"}, {Type::center_line_end3, "center_line_end3"}, diff --git a/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.hpp b/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.hpp index b0b0e8f9fd..bad9b628f3 100644 --- a/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.hpp +++ b/src/libslic3r/SLA/SupportIslands/SupportIslandPoint.hpp @@ -19,6 +19,9 @@ public: one_center_point, two_points, center_line, + center_line1, // sample line in center + center_line2, // rest of neighbor edge before position of Field start + center_line3, // end of loop, next neighbors are already sampled center_line_end, // end of branch center_line_end2, // start of main path(only one per VD) center_line_end3, // end in continous sampling diff --git a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp index a71d01b7c5..5994a34efd 100644 --- a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp +++ b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.cpp @@ -226,13 +226,15 @@ Slic3r::Polygon VoronoiGraphUtils::to_polygon(const Lines &lines, points.push_back(p2); } Polygon polygon(points); - //if (!polygon.contains(center)) draw(polygon, lines, center); + if (!polygon.contains(center)) { + draw(polygon, lines, center); + } assert(polygon.is_valid()); assert(polygon.contains(center)); assert(PolygonUtils::is_not_self_intersect(polygon, center)); return polygon; } - + Slic3r::Polygon VoronoiGraphUtils::to_polygon(const VD::cell_type & cell, const Slic3r::Points &points, double maximal_distance) @@ -1162,6 +1164,77 @@ coord_t VoronoiGraphUtils::get_max_width(const VoronoiGraph::Node *node) return max; } +bool VoronoiGraphUtils::is_last_neighbor( + const VoronoiGraph::Node::Neighbor *neighbor) +{ + return (neighbor->node->neighbors.size() == 1); +} + +void VoronoiGraphUtils::for_neighbor_at_distance( + const VoronoiGraph::Position &position, + coord_t max_distance, + std::function fnc) +{ + coord_t act_distance = position.calc_distance(); + const VoronoiGraph::Node *act_node = position.neighbor->node; + const VoronoiGraph::Node *twin_node = get_twin_node(*position.neighbor); + std::set done; + done.insert(twin_node); + done.insert(act_node); + std::queue> process; + coord_t distance = position.calc_rest_distance(); + if (distance < max_distance) process.push({twin_node, distance}); + + while (true) { + const VoronoiGraph::Node *next_node = nullptr; + coord_t next_distance = 0; + for (const auto &neighbor : act_node->neighbors) { + if (done.find(neighbor.node) != done.end()) + continue; // already checked + done.insert(neighbor.node); + + fnc(neighbor, act_distance); + + coord_t length = static_cast(neighbor.length()); + coord_t distance = act_distance + length; + if (distance >= max_distance) continue; + if (next_node == nullptr) { + next_node = neighbor.node; + next_distance = distance; + } else { + process.push({neighbor.node, distance}); + } + } + if (next_node != nullptr) { // exist next node + act_node = next_node; + act_distance = next_distance; + } else if (!process.empty()) { // exist next process + act_node = process.front().first; + act_distance = process.front().second; + process.pop(); + } else { // no next node neither process + break; + } + } +} + +double VoronoiGraphUtils::outline_angle(const VoronoiGraph::Node::Neighbor &neighbor, const Lines& lines) +{ + assert(neighbor.edge->is_linear()); + assert(neighbor.min_width() == 0); + const VD::cell_type *c1 = neighbor.edge->cell(); + const VD::cell_type *c2 = neighbor.edge->twin()->cell(); + + const Line &l1 = lines[c1->source_index()]; + const Line &l2 = lines[c2->source_index()]; + + Vec2d d1 = LineUtils::direction(l1).cast(); + Vec2d d2 = LineUtils::direction(l2).cast(); + + double dot = d1.dot(-d2); + return std::acos(dot/d1.norm() / d2.norm()); +} + void VoronoiGraphUtils::draw(SVG & svg, const VoronoiGraph &graph, const Lines & lines, @@ -1200,56 +1273,6 @@ void VoronoiGraphUtils::draw(SVG & svg, } } -void VoronoiGraphUtils::for_neighbor_at_distance( - const VoronoiGraph::Position & position, - coord_t max_distance, - std::function fnc) -{ - coord_t act_distance = position.calc_distance(); - const VoronoiGraph::Node *act_node = position.neighbor->node; - const VoronoiGraph::Node *twin_node = get_twin_node(*position.neighbor); - std::set done; - done.insert(twin_node); - done.insert(act_node); - std::queue> process; - coord_t distance = position.calc_rest_distance(); - if (distance < max_distance) - process.push({twin_node, distance}); - - while (true) { - const VoronoiGraph::Node *next_node = nullptr; - coord_t next_distance = 0; - for (const auto &neighbor : act_node->neighbors) { - if (done.find(neighbor.node) != done.end()) - continue; // already checked - done.insert(neighbor.node); - - fnc(neighbor, act_distance); - - coord_t length = static_cast(neighbor.length()); - coord_t distance = act_distance + length; - if (distance >= max_distance) continue; - if (next_node == nullptr) { - next_node = neighbor.node; - next_distance = distance; - } else { - process.push({neighbor.node, distance}); - } - } - if (next_node != nullptr) { // exist next node - act_node = next_node; - act_distance = next_distance; - } else if (!process.empty()) { // exist next process - act_node = process.front().first; - act_distance = process.front().second; - process.pop(); - } else { // no next node neither process - break; - } - } - -} - void VoronoiGraphUtils::draw(SVG & svg, const VD::edge_type &edge, const Lines & lines, @@ -1330,11 +1353,6 @@ void VoronoiGraphUtils::draw(SVG & svg, draw(svg, path.nodes, width, mainPathColor); } -bool VoronoiGraphUtils::is_last_neighbor(const VoronoiGraph::Node::Neighbor *neighbor) -{ - return (neighbor->node->neighbors.size() == 1); -} - void VoronoiGraphUtils::draw(const Polygon &polygon, const Lines & lines, const Point & center) diff --git a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp index 4d2ad5f2f9..c86bc906f4 100644 --- a/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp +++ b/src/libslic3r/SLA/SupportIslands/VoronoiGraphUtils.hpp @@ -454,6 +454,15 @@ public: /// True when neighbor node has only one neighbor static bool is_last_neighbor(const VoronoiGraph::Node::Neighbor *neighbor); + /// + /// only line created VG + /// only last neighbor + /// Calculate angle of outline(source lines) at end of voronoi diagram + /// + /// Neighbor to calculate angle + /// Angle of source lines in radians + static double outline_angle(const VoronoiGraph::Node::Neighbor &neighbor, const Lines& lines); + /// /// Loop over neighbor in max distance from position /// diff --git a/tests/sla_print/sla_supptgen_tests.cpp b/tests/sla_print/sla_supptgen_tests.cpp index c0670e7833..72ae2ef96e 100644 --- a/tests/sla_print/sla_supptgen_tests.cpp +++ b/tests/sla_print/sla_supptgen_tests.cpp @@ -328,6 +328,7 @@ ExPolygons createTestIslands(double size) ExPolygon(create_V_shape(size*4, size / 3)), ExPolygon(create_cross_roads(size, size / 3)), create_disc(3*size, size / 4, 30), + create_disc(2*size, size, 12), // 3 points create_square_with_4holes(5 * size, 5 * size / 2 - size / 3), // Tiny and wide part together with holes @@ -473,8 +474,8 @@ SampleConfig create_sample_config(double size) { cfg.min_width_for_outline_support = cfg.max_width_for_center_support_line; cfg.outline_sample_distance = cfg.max_distance; - cfg.minimal_move = std::max(10000., size/40); - cfg.count_iteration = 50; + cfg.minimal_move = static_cast(size/30); + cfg.count_iteration = 100; cfg.max_align_distance = 0; return cfg; } @@ -590,7 +591,6 @@ TEST_CASE("Small islands should be supported in center", "[SupGen], [VoronoiSkel double size = 3e7; SampleConfig cfg = create_sample_config(size); ExPolygons islands = createTestIslands(size); - islands = { create_disc(3 * size, 2*size , 20)}; for (ExPolygon &island : islands) { // information for debug which island cause problem [[maybe_unused]] size_t debug_index = &island - &islands.front();