#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 Vodonoi diagram vertex type to Slicer Point /// decrease precission by rounding /// /// Input point pointer(double precission) /// Converted point(int preccission) static Point to_point(const VD::vertex_type *vertex); /// /// Convert Slic3r point to Vodonoi point type /// extend precission /// /// Input point(int preccission) /// Converted vertex(double precission) static VD::point_type to_point(const Point &point); /// /// Convert point type between voronoi and slicer format /// /// Input vertex /// created vector static Vec2d to_point_d(const VD::vertex_type* vertex); /// /// Convert Slic3r Line to Voronoi segment type /// /// input line(int preccission) /// output segment(double precission) static VD::segment_type to_segment(const Line &line); /// /// create direction from Voronoi edge /// /// input /// direction --> (vertex1 - vertex0) static Point to_direction(const VD::edge_type *edge); /// /// create direction from Voronoi edge /// /// input /// direction --> (vertex1 - vertex0) static Vec2d to_direction_d(const VD::edge_type *edge); /// /// 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: /// /// 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 Line create_line_between_source_points( const Point &point1, const Point &point2, double maximal_distance); public: /// /// Convert edge to line /// only for line edge /// crop infinite edge by maximal distance from source point /// inspiration in VoronoiVisualUtils::clip_infinite_edge /// /// VD 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 /// Valid CCW polygon with center inside of polygon static 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 Polygon to_polygon(const VD::cell_type &cell, const 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); private: /// /// PRIVATE: function to get parabola focus point /// /// curved edge /// source lines /// Parabola focus point static Point get_parabola_point(const VD::edge_type ¶bola, const Lines &lines); /// /// PRIVATE: function to get parabola diretrix /// /// curved edge /// source lines /// Parabola diretrix static Line get_parabola_line(const VD::edge_type ¶bola, const Lines &lines); public: /// /// Construct parabola from curved edge /// /// curved edge /// Voronoi diagram source lines /// Parabola represented shape of edge static Parabola get_parabola(const VD::edge_type &edge, const Lines &lines); /// /// Calculate length of curved edge /// /// curved edge /// Voronoi diagram source lines /// 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) /// ! not used /// /// 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 width limit(min, max) and round value to coord_t /// /// Input edge /// Source for Voronoi diagram. It contains parabola parameters /// Width range for edge. /// First is minimal width on edge. /// Second is maximal width on edge. static std::pair calculate_width(const VD::edge_type &edge, const Lines &lines); private: static std::pair calculate_width_for_line( const VD::edge_type &line_edge, const Lines &lines); static std::pair calculate_width_for_parabola( const VD::edge_type ¶bola_edge, const Lines &lines); static std::pair min_max_width(const VD::edge_type &edge, const Point &point); public: /// /// 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 create_skeleton(const VD &vd, const Lines &lines); /// /// 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 twin neighbor /// /// neighbor /// Twin neighbor static const VoronoiGraph::Node::Neighbor *get_twin(const VoronoiGraph::Node::Neighbor& neighbor); /// /// Find source node of neighbor /// /// neighbor /// start node static const VoronoiGraph::Node *get_twin_node(const VoronoiGraph::Node::Neighbor& neighbor); /// /// Check if neighbor is in opposit direction to line direction /// /// edge has direction from vertex0 to vertex1 /// line has direction from point a to point b /// True when oposit direction otherwise FALSE static bool is_opposit_direction(const VD::edge_type *edge, const Line &line); /// /// Create point on edge defined by neighbor /// in distance defined by edge length ratio /// /// Containe neighbor and position ratio on neighbor /// Point laying on neighbor edge static Point create_edge_point(const VoronoiGraph::Position& position); static Point create_edge_point(const VD::edge_type *edge, double ratio); /// /// Find position on VD edge with width /// /// Edge for searching position /// Specify place on edge /// Source lines for voronoi diagram /// Position on given edge static VoronoiGraph::Position get_position_with_width( const VoronoiGraph::Node::Neighbor *neighbor, coord_t width, const Lines & lines); /// /// Calculate both point on source lines correspond to edge postion /// Faster way to get both point_on_line /// /// Position on edge /// Source lines of VD /// pair of point lay on outline lines correspond to position on edge /// first -> source line of edge cell /// second -> source line of edge twin cell static std::pair point_on_lines( const VoronoiGraph::Position &position, const Lines & lines); /// /// align "position" close to point "to" /// /// input position on VD /// point to align /// maximal distance on VD for search point /// Position on VD static VoronoiGraph::Position align(const VoronoiGraph::Position &position, const Point & to, double max_distance); /// /// Calc position by ratio to closest point laying on edge /// /// edge to align /// point to align /// output: ratio between vertex0 and vertex1 closest to point, /// when less than zero vertex0 is closest point on edge /// when grater than one vertex1 is closest point on edge /// distance edge to "to" point /// only when result ratio is in range from 0 to 1 static double get_distance(const VD::edge_type &edge, const Point & point, double & edge_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 coord_t get_max_width(const VoronoiGraph::ExPath &longest_path); static coord_t get_max_width(const VoronoiGraph::Nodes &path); static coord_t get_max_width(const VoronoiGraph::Node *node); /// /// Check wheather VG ends in smaller distance than given one /// /// Position in direction to checked end /// distance to explore /// True when there is only smaller VD path to edge static bool ends_in_distanace(const VoronoiGraph::Position &position, coord_t max_distance); /// /// 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 /// /// Start of loop /// Termination of loop /// function to process neighbor with actual distance static void for_neighbor_at_distance( const VoronoiGraph::Position &position, coord_t max_distance, std::function fnc); public: // draw function for debug static void draw(SVG & svg, const VoronoiGraph &graph, const Lines & lines, const SampleConfig &config, bool pointer_caption = false); static void draw(SVG & svg, const VD::edge_type &edge, const Lines & lines, const char * color, coord_t width); static void draw(SVG & svg, const VoronoiGraph::Nodes &path, coord_t width, const char * color, bool finish = false, bool caption = false); static void draw(SVG & svg, const VoronoiGraph::ExPath &path, coord_t width); // draw polygon when convert from cell static void draw(const Slic3r::Polygon &polygon, const Slic3r::Lines & lines, const Slic3r::Point & center); }; } // namespace Slic3r::sla #endif // slic3r_SLA_SuppotstIslands_VoronoiGraphUtils_hpp_