Introduce wrapper class around boost::polygon::voronoi_diagram.

This commit is contained in:
Lukáš Hejl 2024-01-31 17:40:57 +01:00
parent 4b6a6379fc
commit fb84f3113a
8 changed files with 142 additions and 80 deletions

View File

@ -89,7 +89,7 @@ static void export_graph_to_svg(const std::string
}
#endif
SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_type& vd_node, Point p)
SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(VD::vertex_type& vd_node, Point p)
{
auto he_node_it = vd_node_to_he_node.find(&vd_node);
if (he_node_it == vd_node_to_he_node.end())
@ -105,7 +105,7 @@ SkeletalTrapezoidation::node_t& SkeletalTrapezoidation::makeNode(vd_t::vertex_ty
}
}
void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments)
void SkeletalTrapezoidation::transferEdge(Point from, Point to, VD::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments)
{
auto he_edge_it = vd_edge_to_he_edge.find(vd_edge.twin());
if (he_edge_it != vd_edge_to_he_edge.end())
@ -216,14 +216,14 @@ void SkeletalTrapezoidation::transferEdge(Point from, Point to, vd_t::edge_type&
}
}
Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const std::vector<Segment>& segments)
Points SkeletalTrapezoidation::discretize(const VD::edge_type& vd_edge, const std::vector<Segment>& segments)
{
/*Terminology in this function assumes that the edge moves horizontally from
left to right. This is not necessarily the case; the edge can go in any
direction, but it helps to picture it in a certain direction in your head.*/
const vd_t::cell_type* left_cell = vd_edge.cell();
const vd_t::cell_type* right_cell = vd_edge.twin()->cell();
const VD::cell_type* left_cell = vd_edge.cell();
const VD::cell_type* right_cell = vd_edge.twin()->cell();
assert(VoronoiUtils::p(vd_edge.vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
assert(VoronoiUtils::p(vd_edge.vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge.vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
@ -331,7 +331,7 @@ Points SkeletalTrapezoidation::discretize(const vd_t::edge_type& vd_edge, const
}
}
bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
bool SkeletalTrapezoidation::computePointCellRange(VD::cell_type& cell, Point& start_source_point, Point& end_source_point, VD::edge_type*& starting_vd_edge, VD::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
{
if (cell.incident_edge()->is_infinite())
return false; //Infinite edges only occur outside of the polygon. Don't copy any part of this cell.
@ -340,7 +340,7 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
// Copy whole cell into graph or not at all
// If the cell.incident_edge()->vertex0() is far away so much that it doesn't even fit into Vec2i64, then there is no way that it will be inside the input polygon.
if (const vd_t::vertex_type &vert = *cell.incident_edge()->vertex0();
if (const VD::vertex_type &vert = *cell.incident_edge()->vertex0();
vert.x() >= double(std::numeric_limits<int64_t>::max()) || vert.x() <= double(std::numeric_limits<int64_t>::lowest()) ||
vert.y() >= double(std::numeric_limits<int64_t>::max()) || vert.y() <= double(std::numeric_limits<int64_t>::lowest()))
return false; // Don't copy any part of this cell
@ -358,7 +358,7 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
if (!LinearAlg2D::isInsideCorner(source_point_index.prev().p(), source_point_index.p(), source_point_index.next().p(), some_point))
return false; // Don't copy any part of this cell
vd_t::edge_type* vd_edge = cell.incident_edge();
VD::edge_type* vd_edge = cell.incident_edge();
do {
assert(vd_edge->is_finite());
if (Vec2i64 p1 = VoronoiUtils::p(vd_edge->vertex1()); p1 == source_point.cast<int64_t>()) {
@ -376,7 +376,7 @@ bool SkeletalTrapezoidation::computePointCellRange(vd_t::cell_type& cell, Point&
return true;
}
void SkeletalTrapezoidation::computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
void SkeletalTrapezoidation::computeSegmentCellRange(VD::cell_type& cell, Point& start_source_point, Point& end_source_point, VD::edge_type*& starting_vd_edge, VD::edge_type*& ending_vd_edge, const std::vector<Segment>& segments)
{
const Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments);
const Point from = source_segment.from();
@ -387,7 +387,7 @@ void SkeletalTrapezoidation::computeSegmentCellRange(vd_t::cell_type& cell, Poin
bool seen_possible_start = false;
bool after_start = false;
bool ending_edge_is_set_before_start = false;
vd_t::edge_type* edge = cell.incident_edge();
VD::edge_type* edge = cell.incident_edge();
do {
if (edge->is_infinite())
continue;
@ -431,7 +431,7 @@ SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const Bead
constructFromPolygons(polys);
}
static bool has_finite_edge_with_non_finite_vertex(const Geometry::VoronoiDiagram &voronoi_diagram)
static bool has_finite_edge_with_non_finite_vertex(const VD &voronoi_diagram)
{
for (const VoronoiUtils::vd_t::edge_type &edge : voronoi_diagram.edges()) {
if (edge.is_finite()) {
@ -444,11 +444,11 @@ static bool has_finite_edge_with_non_finite_vertex(const Geometry::VoronoiDiagra
return false;
}
static bool detect_missing_voronoi_vertex(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<SkeletalTrapezoidation::Segment> &segments) {
static bool detect_missing_voronoi_vertex(const VD &voronoi_diagram, const std::vector<SkeletalTrapezoidation::Segment> &segments) {
if (has_finite_edge_with_non_finite_vertex(voronoi_diagram))
return true;
for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) {
for (VD::cell_type cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // There is no spoon
@ -517,9 +517,9 @@ inline static void rotate_back_skeletal_trapezoidation_graph_after_fix(SkeletalT
}
}
bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments)
bool detect_voronoi_edge_intersecting_input_segment(const VD &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments)
{
for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) {
for (VD::cell_type cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // Degenerated cell, there is no spoon
@ -530,14 +530,14 @@ bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagr
const Vec2d source_segment_from = source_segment.from().cast<double>();
const Vec2d source_segment_vec = source_segment.to().cast<double>() - source_segment_from;
Point start_source_point, end_source_point;
VoronoiUtils::vd_t::edge_type *begin_voronoi_edge = nullptr, *end_voronoi_edge = nullptr;
Point start_source_point, end_source_point;
VD::edge_type *begin_voronoi_edge = nullptr, *end_voronoi_edge = nullptr;
SkeletalTrapezoidation::computeSegmentCellRange(cell, start_source_point, end_source_point, begin_voronoi_edge, end_voronoi_edge, segments);
// All Voronoi vertices must be on left side of the source segment, otherwise Voronoi diagram is invalid.
// FIXME Lukas H.: Be aware that begin_voronoi_edge and end_voronoi_edge could be nullptr in some specific cases.
// It mostly happens when there is some missing Voronoi, for example, in GH issue #8846 (IssuesWithMysteriousPerimeters.3mf).
if (begin_voronoi_edge != nullptr && end_voronoi_edge != nullptr)
for (VoronoiUtils::vd_t::edge_type *edge = begin_voronoi_edge; edge != end_voronoi_edge; edge = edge->next())
for (VD::edge_type *edge = begin_voronoi_edge; edge != end_voronoi_edge; edge = edge->next())
if (const Vec2d edge_v1(edge->vertex1()->x(), edge->vertex1()->y()); Slic3r::cross2(source_segment_vec, edge_v1 - source_segment_from) < 0)
return true;
}
@ -555,7 +555,7 @@ enum class VoronoiDiagramStatus {
// Try to detect cases when some Voronoi vertex is missing, when the Voronoi diagram
// is not planar or some Voronoi edge is intersecting input segment.
VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::VoronoiDiagram &voronoi_diagram,
VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const VD &voronoi_diagram,
const std::vector<SkeletalTrapezoidation::Segment> &segments)
{
if (const bool has_missing_voronoi_vertex = detect_missing_voronoi_vertex(voronoi_diagram, segments); has_missing_voronoi_vertex) {
@ -571,7 +571,7 @@ VoronoiDiagramStatus detect_voronoi_diagram_known_issues(const Geometry::Voronoi
}
inline static std::pair<PointMap, double> try_to_fix_degenerated_voronoi_diagram_by_rotation(
Geometry::VoronoiDiagram &voronoi_diagram,
VD &voronoi_diagram,
const Polygons &polys,
Polygons &polys_rotated,
std::vector<SkeletalTrapezoidation::Segment> &segments,
@ -602,7 +602,7 @@ inline static std::pair<PointMap, double> try_to_fix_degenerated_voronoi_diagram
segments.emplace_back(&polys_rotated, poly_idx, point_idx);
voronoi_diagram.clear();
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
voronoi_diagram.construct_voronoi(segments.cbegin(), segments.cend());
#ifdef ARACHNE_DEBUG_VORONOI
{
@ -651,8 +651,8 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
}
#endif
Geometry::VoronoiDiagram voronoi_diagram;
construct_voronoi(segments.begin(), segments.end(), &voronoi_diagram);
VD voronoi_diagram;
voronoi_diagram.construct_voronoi(segments.begin(), segments.end());
#ifdef ARACHNE_DEBUG_VORONOI
{
@ -692,14 +692,14 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
process_voronoi_diagram:
assert(this->graph.edges.empty() && this->graph.nodes.empty() && this->vd_edge_to_he_edge.empty() && this->vd_node_to_he_node.empty());
for (vd_t::cell_type cell : voronoi_diagram.cells()) {
for (VD::cell_type cell : voronoi_diagram.cells()) {
if (!cell.incident_edge())
continue; // There is no spoon
Point start_source_point;
Point end_source_point;
vd_t::edge_type* starting_voronoi_edge = nullptr;
vd_t::edge_type* ending_voronoi_edge = nullptr;
VD::edge_type* starting_voronoi_edge = nullptr;
VD::edge_type* ending_voronoi_edge = nullptr;
// Compute and store result in above variables
if (cell.contains_point()) {
@ -726,7 +726,7 @@ process_voronoi_diagram:
constexpr bool is_next_to_start_or_end = true;
graph.makeRib(prev_edge, start_source_point, end_source_point, is_next_to_start_or_end);
for (vd_t::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) {
for (VD::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) {
assert(vd_edge->is_finite());
assert(VoronoiUtils::p(vd_edge->vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(vd_edge->vertex0()).x() >= std::numeric_limits<coord_t>::lowest());

View File

@ -26,8 +26,9 @@
//#define ARACHNE_DEBUG
//#define ARACHNE_DEBUG_VORONOI
namespace Slic3r::Arachne
{
namespace Slic3r::Arachne {
using VD = Slic3r::Geometry::VoronoiDiagram;
/*!
* Main class of the dynamic beading strategies.
@ -50,8 +51,6 @@ deposition modeling" by Kuipers et al.
*/
class SkeletalTrapezoidation
{
using pos_t = double;
using vd_t = boost::polygon::voronoi_diagram<pos_t>;
using graph_t = SkeletalTrapezoidationGraph;
using edge_t = STHalfEdge;
using node_t = STHalfEdgeNode;
@ -168,9 +167,9 @@ protected:
* mapping each voronoi VD edge to the corresponding halfedge HE edge
* In case the result segment is discretized, we map the VD edge to the *last* HE edge
*/
ankerl::unordered_dense::map<vd_t::edge_type*, edge_t*> vd_edge_to_he_edge;
ankerl::unordered_dense::map<vd_t::vertex_type*, node_t*> vd_node_to_he_node;
node_t& makeNode(vd_t::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
ankerl::unordered_dense::map<VD::edge_type*, edge_t*> vd_edge_to_he_edge;
ankerl::unordered_dense::map<VD::vertex_type*, node_t*> vd_node_to_he_node;
node_t& makeNode(VD::vertex_type& vd_node, Point p); //!< Get the node which the VD node maps to, or create a new mapping if there wasn't any yet.
/*!
* (Eventual) returned 'polylines per index' result (from generateToolpaths):
@ -181,7 +180,7 @@ protected:
* Transfer an edge from the VD to the HE and perform discretization of parabolic edges (and vertex-vertex edges)
* \p prev_edge serves as input and output. May be null as input.
*/
void transferEdge(Point from, Point to, vd_t::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments);
void transferEdge(Point from, Point to, VD::edge_type& vd_edge, edge_t*& prev_edge, Point& start_source_point, Point& end_source_point, const std::vector<Segment>& segments);
/*!
* Discretize a Voronoi edge that represents the medial axis of a vertex-
@ -208,7 +207,7 @@ protected:
* \return A number of coordinates along the edge where the edge is broken
* up into discrete pieces.
*/
Points discretize(const vd_t::edge_type& segment, const std::vector<Segment>& segments);
Points discretize(const VD::edge_type& segment, const std::vector<Segment>& segments);
/*!
* Compute the range of line segments that surround a cell of the skeletal
@ -234,7 +233,7 @@ protected:
* /return Whether the cell is inside of the polygon. If it's outside of the
* polygon we should skip processing it altogether.
*/
static bool computePointCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
static bool computePointCellRange(VD::cell_type& cell, Point& start_source_point, Point& end_source_point, VD::edge_type*& starting_vd_edge, VD::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
/*!
* Compute the range of line segments that surround a cell of the skeletal
@ -260,7 +259,7 @@ protected:
* /return Whether the cell is inside of the polygon. If it's outside of the
* polygon we should skip processing it altogether.
*/
static void computeSegmentCellRange(vd_t::cell_type& cell, Point& start_source_point, Point& end_source_point, vd_t::edge_type*& starting_vd_edge, vd_t::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
static void computeSegmentCellRange(VD::cell_type& cell, Point& start_source_point, Point& end_source_point, VD::edge_type*& starting_vd_edge, VD::edge_type*& ending_vd_edge, const std::vector<Segment>& segments);
/*!
* For VD cells associated with an input polygon vertex, we need to separate the node at the end and start of the cell into two
@ -603,7 +602,7 @@ protected:
*/
void generateLocalMaximaSingleBeads();
friend bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments);
friend bool detect_voronoi_edge_intersecting_input_segment(const VD &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments);
};
} // namespace Slic3r::Arachne

View File

@ -156,8 +156,6 @@ struct PathsPointIndexLocator
}
};
using PolygonsPointIndexLocator = PathsPointIndexLocator<Polygons>;
}//namespace Slic3r::Arachne
namespace std

View File

@ -467,7 +467,7 @@ void MedialAxis::build(ThickPolylines* polylines)
test(l.b.y());
}
#endif // NDEBUG
construct_voronoi(m_lines.begin(), m_lines.end(), &m_vd);
m_vd.construct_voronoi(m_lines.begin(), m_lines.end());
Slic3r::Voronoi::annotate_inside_outside(m_vd, m_lines);
// static constexpr double threshold_alpha = M_PI / 12.; // 30 degrees
// std::vector<Vec2d> skeleton_edges = Slic3r::Voronoi::skeleton_edges_rough(vd, lines, threshold_alpha);

View File

@ -8,10 +8,8 @@
#include "../Line.hpp"
#include "../Polyline.hpp"
#define BOOST_VORONOI_USE_GMP 1
#ifdef _MSC_VER
// Suppress warning C4146 in OpenVDB: unary minus operator applied to unsigned type, result still unsigned
// Suppress warning C4146 in OpenVDB: unary minus operator applied to unsigned type, result still unsigned
#pragma warning(push)
#pragma warning(disable : 4146)
#endif // _MSC_VER
@ -20,18 +18,85 @@
#pragma warning(pop)
#endif // _MSC_VER
namespace Slic3r {
namespace Slic3r::Geometry {
namespace Geometry {
class VoronoiDiagram : public boost::polygon::voronoi_diagram<double> {
class VoronoiDiagram
{
public:
typedef double coord_type;
typedef boost::polygon::point_data<coordinate_type> point_type;
typedef boost::polygon::segment_data<coordinate_type> segment_type;
typedef boost::polygon::rectangle_data<coordinate_type> rect_type;
using coord_type = double;
using voronoi_diagram_type = boost::polygon::voronoi_diagram<coord_type>;
using point_type = boost::polygon::point_data<voronoi_diagram_type::coordinate_type>;
using segment_type = boost::polygon::segment_data<voronoi_diagram_type::coordinate_type>;
using rect_type = boost::polygon::rectangle_data<voronoi_diagram_type::coordinate_type>;
using coordinate_type = voronoi_diagram_type::coordinate_type;
using vertex_type = voronoi_diagram_type::vertex_type;
using edge_type = voronoi_diagram_type::edge_type;
using cell_type = voronoi_diagram_type::cell_type;
using const_vertex_iterator = voronoi_diagram_type::const_vertex_iterator;
using const_edge_iterator = voronoi_diagram_type::const_edge_iterator;
using const_cell_iterator = voronoi_diagram_type::const_cell_iterator;
using vertex_container_type = voronoi_diagram_type::vertex_container_type;
using edge_container_type = voronoi_diagram_type::edge_container_type;
using cell_container_type = voronoi_diagram_type::cell_container_type;
VoronoiDiagram() = default;
virtual ~VoronoiDiagram() = default;
void clear() { m_voronoi_diagram.clear(); }
const cell_container_type &cells() const { return m_voronoi_diagram.cells(); }
const vertex_container_type &vertices() const { return m_voronoi_diagram.vertices(); }
const edge_container_type &edges() const { return m_voronoi_diagram.edges(); }
std::size_t num_cells() const { return m_voronoi_diagram.num_cells(); }
std::size_t num_edges() const { return m_voronoi_diagram.num_edges(); }
std::size_t num_vertices() const { return m_voronoi_diagram.num_vertices(); }
template<typename SegmentIterator>
typename boost::polygon::enable_if<
typename boost::polygon::gtl_if<typename boost::polygon::is_segment_concept<
typename boost::polygon::geometry_concept<typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type,
void>::type
construct_voronoi(const SegmentIterator first, const SegmentIterator last)
{
boost::polygon::construct_voronoi(first, last, &m_voronoi_diagram);
}
template<typename PointIterator>
typename boost::polygon::enable_if<
typename boost::polygon::gtl_if<typename boost::polygon::is_point_concept<
typename boost::polygon::geometry_concept<typename std::iterator_traits<PointIterator>::value_type>::type>::type>::type,
void>::type
construct_voronoi(const PointIterator first, const PointIterator last)
{
boost::polygon::construct_voronoi(first, last, &m_voronoi_diagram);
}
template<typename PointIterator, typename SegmentIterator>
typename boost::polygon::enable_if<
typename boost::polygon::gtl_and<
typename boost::polygon::gtl_if<typename boost::polygon::is_point_concept<
typename boost::polygon::geometry_concept<typename std::iterator_traits<PointIterator>::value_type>::type>::type>::type,
typename boost::polygon::gtl_if<typename boost::polygon::is_segment_concept<typename boost::polygon::geometry_concept<
typename std::iterator_traits<SegmentIterator>::value_type>::type>::type>::type>::type,
void>::type
construct_voronoi(const PointIterator p_first, const PointIterator p_last, const SegmentIterator s_first, const SegmentIterator s_last)
{
boost::polygon::construct_voronoi(p_first, p_last, s_first, s_last, &m_voronoi_diagram);
}
private:
voronoi_diagram_type m_voronoi_diagram;
};
} } // namespace Slicer::Geometry
} // namespace Slic3r::Geometry
#endif // slic3r_Geometry_Voronoi_hpp_

View File

@ -254,7 +254,7 @@ static bool check_if_three_edges_are_ccw(const VD::edge_type &first, const VD::e
}
}
bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments)
bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VD &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments)
{
for (const VD::vertex_type &vertex : voronoi_diagram.vertices()) {
std::vector<const VD::edge_type *> edges;
@ -271,9 +271,9 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &vor
// Checking for CCW make sense for three and more edges.
if (edges.size() > 2) {
for (auto edge_it = edges.begin() ; edge_it != edges.end(); ++edge_it) {
const Geometry::VoronoiDiagram::edge_type *prev_edge = edge_it == edges.begin() ? edges.back() : *std::prev(edge_it);
const Geometry::VoronoiDiagram::edge_type *curr_edge = *edge_it;
const Geometry::VoronoiDiagram::edge_type *next_edge = std::next(edge_it) == edges.end() ? edges.front() : *std::next(edge_it);
const VD::edge_type *prev_edge = edge_it == edges.begin() ? edges.back() : *std::prev(edge_it);
const VD::edge_type *curr_edge = *edge_it;
const VD::edge_type *next_edge = std::next(edge_it) == edges.end() ? edges.front() : *std::next(edge_it);
if (!check_if_three_edges_are_ccw(*prev_edge, *curr_edge, *next_edge, segments))
return false;

View File

@ -702,7 +702,7 @@ struct MMU_Graph
// All Voronoi vertices are post-processes to merge very close vertices to single. Witch eliminates issues with intersection edges.
// Also, Voronoi vertices outside of the bounding of input polygons are throw away by marking them.
void append_voronoi_vertices(const Geometry::VoronoiDiagram &vd, const Polygons &color_poly_tmp, BoundingBox bbox) {
void append_voronoi_vertices(const Voronoi::VD &vd, const Polygons &color_poly_tmp, BoundingBox bbox) {
bbox.offset(SCALED_EPSILON);
struct CPoint
@ -884,7 +884,7 @@ static inline Line clip_finite_voronoi_edge(const Voronoi::VD::edge_type &edge,
static MMU_Graph build_graph(size_t layer_idx, const std::vector<std::vector<ColoredLine>> &color_poly)
{
Geometry::VoronoiDiagram vd;
Voronoi::VD vd;
std::vector<ColoredLine> lines_colored = to_lines(color_poly);
const Polygons color_poly_tmp = colored_points_to_polygon(color_poly);
const Points points = to_points(color_poly_tmp);
@ -908,7 +908,7 @@ static MMU_Graph build_graph(size_t layer_idx, const std::vector<std::vector<Col
force_edge_adding[&c_poly - &color_poly.front()] = force_edge;
}
boost::polygon::construct_voronoi(lines_colored.begin(), lines_colored.end(), &vd);
vd.construct_voronoi(lines_colored.begin(), lines_colored.end());
MMU_Graph graph;
graph.nodes.reserve(points.size() + vd.vertices().size());
for (const Point &point : points)

View File

@ -62,7 +62,7 @@ TEST_CASE("Voronoi missing edges - points 12067", "[Voronoi]")
// Construction of the Voronoi Diagram.
VD vd;
construct_voronoi(pts.begin(), pts.end(), &vd);
vd.construct_voronoi(pts.begin(), pts.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-pts.svg").c_str(),
@ -190,7 +190,7 @@ TEST_CASE("Voronoi missing edges - Alessandro gapfill 12707", "[Voronoi]")
Lines lines = to_lines(poly);
VD vd;
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-lines.svg").c_str(),
@ -298,7 +298,7 @@ TEST_CASE("Voronoi weirdness", "[Voronoi]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-weirdness.svg").c_str(),
@ -322,7 +322,7 @@ TEST_CASE("Voronoi division by zero 12903", "[Voronoi]")
}
VD vd;
construct_voronoi(pts.begin(), pts.end(), &vd);
vd.construct_voronoi(pts.begin(), pts.end());
#ifdef VORONOI_DEBUG_OUT
// Scale the voronoi vertices and input points, so that the dump_voronoi_to_svg will display them correctly.
@ -1319,7 +1319,7 @@ TEST_CASE("Voronoi NaN coordinates 12139", "[Voronoi][!hide][!mayfail]")
#endif
VD vd;
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const auto& edge : vd.edges())
if (edge.is_finite()) {
@ -1360,7 +1360,7 @@ TEST_CASE("Voronoi offset", "[VoronoiOffset]")
VD vd;
Lines lines = to_lines(poly_with_hole);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 1, 1 },
@ -1426,7 +1426,7 @@ TEST_CASE("Voronoi offset 2", "[VoronoiOffset]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
@ -1496,7 +1496,7 @@ TEST_CASE("Voronoi offset 3", "[VoronoiOffset]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
@ -1747,7 +1747,7 @@ TEST_CASE("Voronoi offset with edge collapse", "[VoronoiOffset4]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
@ -1858,7 +1858,7 @@ TEST_CASE("Voronoi offset 5", "[VoronoiOffset5]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(2.8), 1, 1 },
@ -1916,7 +1916,7 @@ TEST_CASE("Voronoi skeleton", "[VoronoiSkeleton]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
Slic3r::Voronoi::annotate_inside_outside(vd, lines);
static constexpr double threshold_alpha = M_PI / 12.; // 30 degrees
std::vector<Vec2d> skeleton_edges = Slic3r::Voronoi::skeleton_edges_rough(vd, lines, threshold_alpha);
@ -1966,7 +1966,7 @@ TEST_CASE("Voronoi missing vertex 1", "[VoronoiMissingVertex1]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex1-out.svg").c_str(), vd, Points(), lines);
#endif
@ -2006,7 +2006,7 @@ TEST_CASE("Voronoi missing vertex 2", "[VoronoiMissingVertex2]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex2-out.svg").c_str(), vd, Points(), lines);
#endif
@ -2047,7 +2047,7 @@ TEST_CASE("Voronoi missing vertex 3", "[VoronoiMissingVertex3]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex3-out.svg").c_str(), vd, Points(), lines);
#endif
@ -2091,8 +2091,8 @@ TEST_CASE("Voronoi missing vertex 4", "[VoronoiMissingVertex4]")
Geometry::VoronoiDiagram vd_2;
Lines lines_1 = to_lines(polygon_1);
Lines lines_2 = to_lines(polygon_2);
construct_voronoi(lines_1.begin(), lines_1.end(), &vd_1);
construct_voronoi(lines_2.begin(), lines_2.end(), &vd_2);
vd_1.construct_voronoi(lines_1.begin(), lines_1.end());
vd_2.construct_voronoi(lines_2.begin(), lines_2.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-1-out.svg").c_str(), vd_1, Points(), lines_1);
dump_voronoi_to_svg(debug_out_path("voronoi-missing-vertex4-2-out.svg").c_str(), vd_2, Points(), lines_2);
@ -2124,7 +2124,7 @@ TEST_CASE("Duplicate Voronoi vertices", "[Voronoi]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-duplicate-vertices-out.svg").c_str(), vd, Points(), lines);
#endif
@ -2164,7 +2164,7 @@ TEST_CASE("Intersecting Voronoi edges", "[Voronoi]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-intersecting-edges-out.svg").c_str(), vd, Points(), lines);
#endif
@ -2226,7 +2226,7 @@ TEST_CASE("Non-planar voronoi diagram", "[VoronoiNonPlanar]")
VD vd;
Lines lines = to_lines(poly);
construct_voronoi(lines.begin(), lines.end(), &vd);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-non-planar-out.svg").c_str(), vd, Points(), lines);
#endif