#ifndef slic3r_VoronoiUtils_hpp_ #define slic3r_VoronoiUtils_hpp_ #include "libslic3r/Geometry/Voronoi.hpp" #include "libslic3r/Arachne/utils/PolygonsSegmentIndex.hpp" using VD = Slic3r::Geometry::VoronoiDiagram; namespace Slic3r::Geometry { // Represent trapezoid Voronoi cell around segment. template struct SegmentCellRange { const PT segment_start_point; // The start point of the source segment of this cell. const PT segment_end_point; // The end point of the source segment of this cell. const VD::edge_type *edge_begin = nullptr; // The edge of the Voronoi diagram where the loop around the cell starts. const VD::edge_type *edge_end = nullptr; // The edge of the Voronoi diagram where the loop around the cell ends. SegmentCellRange() = delete; explicit SegmentCellRange(const PT &segment_start_point, const PT &segment_end_point) : segment_start_point(segment_start_point), segment_end_point(segment_end_point) {} bool is_valid() const { return edge_begin && edge_end && edge_begin != edge_end; } }; class VoronoiUtils { public: static Vec2i64 to_point(const VD::vertex_type *vertex); static Vec2i64 to_point(const VD::vertex_type &vertex); static bool is_finite(const VD::vertex_type &vertex); static VD::vertex_type make_rotated_vertex(VD::vertex_type &vertex, double angle); template static typename boost::polygon::enable_if< typename boost::polygon::gtl_if::value_type>::type>::type>::type, typename std::iterator_traits::reference>::type get_source_segment(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); template static typename boost::polygon::enable_if< typename boost::polygon::gtl_if::value_type>::type>::type>::type, typename boost::polygon::segment_point_type::value_type>::type>::type get_source_point(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); template static typename boost::polygon::enable_if< typename boost::polygon::gtl_if::value_type>::type>::type>::type, Arachne::PolygonsPointIndex>::type get_source_point_index(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); /** * Discretize a parabola based on (approximate) step size. * * Adapted from CuraEngine VoronoiUtils::discretizeParabola by Tim Kuipers @BagelOrb and @Ghostkeeper. * * @param approximate_step_size is measured parallel to the source_segment, not along the parabola. */ template static typename boost::polygon::enable_if::type>::type>::type, Points>::type discretize_parabola(const Point &source_point, const Segment &source_segment, const Point &start, const Point &end, coord_t approximate_step_size, float transitioning_angle); /** * Compute the range of line segments that surround a cell of the skeletal * graph that belongs to a line segment of the medial axis. * * This should only be used on cells that belong to a central line segment * of the skeletal graph, e.g. trapezoid cells, not triangular cells. * * The resulting line segments is just the first and the last segment. They * are linked to the neighboring segments, so you can iterate over the * segments until you reach the last segment. * * Adapted from CuraEngine VoronoiUtils::computePointCellRange by Tim Kuipers @BagelOrb, * Jaime van Kessel @nallath, Remco Burema @rburema and @Ghostkeeper. * * @param cell The cell to compute the range of line segments for. * @param segment_begin Begin iterator for all edges of the input Polygons. * @param segment_end End iterator for all edges of the input Polygons. * @return Range of line segments that surround the cell. */ template static typename boost::polygon::enable_if< typename boost::polygon::gtl_if::value_type>::type>::type>::type, Geometry::SegmentCellRange< typename boost::polygon::segment_point_type::value_type>::type>>::type compute_segment_cell_range(const VD::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end); template static bool is_in_range(double value) { return double(std::numeric_limits::lowest()) <= value && value <= double(std::numeric_limits::max()); } template static bool is_in_range(const VD::vertex_type &vertex) { return VoronoiUtils::is_finite(vertex) && is_in_range(vertex.x()) && is_in_range(vertex.y()); } template static bool is_in_range(const VD::edge_type &edge) { if (edge.vertex0() == nullptr || edge.vertex1() == nullptr) return false; return is_in_range(*edge.vertex0()) && is_in_range(*edge.vertex1()); } }; } // namespace Slic3r::Geometry #endif // slic3r_VoronoiUtils_hpp_