#ifndef slic3r_SLA_SuppotstIslands_VoronoiGraphUtils_hpp_ #define slic3r_SLA_SuppotstIslands_VoronoiGraphUtils_hpp_ #include #include #include #include #include #include #include "VoronoiGraph.hpp" #include "Parabola.hpp" #include "SampleConfig.hpp" #include "SupportIslandPoint.hpp" namespace Slic3r::sla { /// /// Class which contain collection of static function /// for work with Voronoi Graph. /// class VoronoiGraphUtils { using VD = Slic3r::Geometry::VoronoiDiagram; public: VoronoiGraphUtils() = delete; /// /// Convert coordinate type between voronoi and slicer format /// /// Coordinate /// When it is possible than cast it otherwise empty optional static coord_t to_coord(const VD::coordinate_type &coord); /// /// Convert Point type to slicer point /// /// Input point pointer /// When it is possible to convert than convert otherwise empty optional static Slic3r::Point to_point(const VD::vertex_type *vertex); /// /// check if coord is in limits for coord_t /// /// input value /// VD source point coordinate /// Maximal distance from source /// True when coord is in +- max_distance from source otherwise FALSE. static bool is_coord_in_limits(const VD::coordinate_type &coord, const coord_t & source, double max_distance); /// /// Check x and y values of vertex /// /// input vertex /// VD source point /// Maximal distance from source /// True when both coord are in limits given by source and max distance otherwise FALSE static bool is_point_in_limits(const VD::vertex_type *vertex, const Point & source, double max_distance); /// /// Private function to help convert edge without vertex to line /// /// VD source point /// VD source point /// Maximal distance from source point /// Line segment between lines static Slic3r::Line create_line_between_source_points( const Point &point1, const Point &point2, double maximal_distance); /// /// Convert edge to line /// only for line edge /// crop infinite edge by maximal distance from source point /// inspiration in VoronoiVisualUtils::clip_infinite_edge /// /// /// Source point for voronoi diagram /// Maximal distance from source point /// Croped line, when all line segment is out of max distance return empty optional static std::optional to_line(const VD::edge_type &edge, const Points & points, double maximal_distance); /// /// close polygon defined by lines /// close points will convert to their center /// Mainly for convert to polygon /// /// Border of polygon, sorted lines CCW /// Center point of polygon /// Radius around center point /// Merge points closer than minimal_distance /// Count checking points, create help points for result polygon /// CCW polygon with center inside of polygon static Slic3r::Polygon to_polygon(const Lines &lines, const Point ¢er, double maximal_distance, double minimal_distance, size_t count_points); /// /// Convert cell to polygon /// Source for VD must be only point to create VD with only line segments /// infinite cell are croped by maximal distance from source point /// /// cell from VD created only by points /// source points for VD /// maximal distance from source point - only for infinite edges(cells) /// polygon created by cell static Slic3r::Polygon to_polygon(const VD::cell_type & cell, const Slic3r::Points &points, double maximal_distance); // return node from graph by vertex, when no exists create one static VoronoiGraph::Node *getNode(VoronoiGraph & graph, const VD::vertex_type *vertex, const VD::edge_type * edge, const Lines & lines); /// /// Extract point from lines, belongs to cell /// ! Source for VD must be only lines /// Main purpose parabola focus point from lines belongs to cell /// inspiration in VoronoiVisualUtils::retrieve_point /// /// Source of Voronoi diagram /// Cell inside of Voronoi diagram /// Point from source lines. static Point retrieve_point(const Lines &lines, const VD::cell_type &cell); /// /// Extract point from lines /// ! Source for VD must be only points /// inspiration in VoronoiVisualUtils::retrieve_point /// /// Source of Voronoi diagram /// Cell inside of Voronoi diagram /// Point from source points. static const Point& retrieve_point(const Points &points, const VD::cell_type &cell); static Slic3r::Point get_parabola_point(const VD::edge_type ¶bola, const Slic3r::Lines &lines); static Slic3r::Line get_parabola_line(const VD::edge_type ¶bola, const Lines &lines); static Parabola get_parabola(const VD::edge_type &edge, const Lines &lines); /// /// Calculate length /// /// curved edge /// edge length static double calculate_length_of_parabola( const VD::edge_type & edge, const Lines & lines); /// /// Calculate length of edge line segment or curve - parabola. /// /// Input edge to calcuate length /// Source for Voronoi diagram. It contains parabola parameters /// The length of edge static double calculate_length(const VD::edge_type &edge, const Lines & lines); /// /// Calculate maximal distance to outline and multiply by two(must be similar on both side) /// /// Input edge. /// Source for Voronoi diagram. It contains parabola parameters /// Maximal island width along edge static double calculate_max_width(const VD::edge_type &edge, const Lines & lines); /// /// calculate distances to border of island and length on skeleton /// /// Input anotated voronoi diagram /// (use function Slic3r::Voronoi::annotate_inside_outside) /// Source lines for voronoi diagram /// Extended voronoi graph by distances and length static VoronoiGraph getSkeleton(const VD &vd, const Lines &lines); /// /// For generating support point in distance from node /// /// Node lay on outline with only one neighbor /// Distance from outline /// static Slic3r::Point get_offseted_point(const VoronoiGraph::Node &node, double padding); /// /// find neighbor and return distance between nodes /// /// source of neighborse /// neighbor node /// When neighbor return distance between neighbor Nodes /// otherwise no value static const VoronoiGraph::Node::Neighbor *get_neighbor( const VoronoiGraph::Node *from, const VoronoiGraph::Node *to); /// /// use function get_neighbor /// when not neighbor assert /// /// source Node /// destination Node /// distance between Nodes or Assert when not neighbor static double get_neighbor_distance(const VoronoiGraph::Node *from, const VoronoiGraph::Node *to); /// /// Create longest node path over circle together with side branches /// /// Source circle, can't be connected with another /// circle Circle side branches from /// nodes of circle Path before circle - /// defince input point to circle Longest nodes path and /// its length static VoronoiGraph::Path find_longest_path_on_circle( const VoronoiGraph::Circle & circle, const VoronoiGraph::ExPath::SideBranchesMap &side_branches); /// /// Serach longest path from input_node throw Nodes in connected circles, /// when circle is alone call find_longest_path_on_circle. /// /// Node on circle /// index of circle with input /// node Hold Circles, connection of circles /// and Side branches Longest path from input /// node static VoronoiGraph::Path find_longest_path_on_circles( const VoronoiGraph::Node & input_node, size_t finished_circle_index, const VoronoiGraph::ExPath &ex_path); /// /// Function for detection circle in passed path. /// /// Already passed path in Graph /// Actual neighbor possible created circle /// Circle when exists static std::optional create_circle( const VoronoiGraph::Path & path, const VoronoiGraph::Node::Neighbor &neighbor); /// /// Move source connected circles into destination /// /// In/Out param /// Input possible modified, do not use it after this /// function Count of destination /// circles before merge Source circle are append afted destination, therfore /// all src indexes must be increased by destination circle count static void merge_connected_circle( VoronoiGraph::ExPath::ConnectedCircles &dst, VoronoiGraph::ExPath::ConnectedCircles &src, size_t dst_circle_count); /// /// move data from source to destination /// side_branches + circles + connected_circle /// /// destination extended path - append data from /// source source extended path - data will be /// moved to dst static void append_neighbor_branch(VoronoiGraph::ExPath &dst, VoronoiGraph::ExPath &src); /// /// Heal starting from random point. /// Compare length of all starting path with side branches /// when side branch is longer than swap with start path /// /// IN/OUT path to be fixed after creating longest path /// from one point static void reshape_longest_path(VoronoiGraph::ExPath &path); /// /// Extract the longest path from voronoi graph /// by own function call stack(IStackFunction). /// Restructuralize path by branch created from random point. /// /// Random point from outline. static VoronoiGraph::ExPath create_longest_path( const VoronoiGraph::Node *start_node); /// /// Find source node of neighbor /// /// neighbor /// start node static const VoronoiGraph::Node *VoronoiGraphUtils::get_twin_node( const VoronoiGraph::Node::Neighbor *neighbor); /// /// Create point on edge defined by neighbor /// in distance defined by edge length ratio /// static Point get_edge_point(const VD::edge_type *edge, double ratio); static const VoronoiGraph::Node *getFirstContourNode( const VoronoiGraph &graph); /// /// Get max width from edge in voronoi graph /// /// Input point to voronoi graph /// Maximal widht in graph static double get_max_width(const VoronoiGraph::ExPath &longest_path); static double get_max_width(const VoronoiGraph::Nodes &path); static double get_max_width(const VoronoiGraph::Node *node); public: // draw function for debug static void draw(SVG &svg, const VoronoiGraph &graph, coord_t width); static void draw(SVG & svg, const VoronoiGraph::Nodes &path, coord_t width, const char * color, bool finish = false); static void draw(SVG & svg, const VoronoiGraph::ExPath &path, coord_t width); }; } // namespace Slic3r::sla #endif // slic3r_SLA_SuppotstIslands_VoronoiGraphUtils_hpp_