OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Geometry::VoronoiDiagram Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Geometry/Voronoi.hpp>

Classes

struct  Segment

Public Types

enum class  IssueType {
  NO_ISSUE_DETECTED , FINITE_EDGE_WITH_NON_FINITE_VERTEX , MISSING_VORONOI_VERTEX , NON_PLANAR_VORONOI_DIAGRAM ,
  VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT , PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT , UNKNOWN
}
enum class  State { REPAIR_NOT_NEEDED , REPAIR_SUCCESSFUL , REPAIR_UNSUCCESSFUL , UNKNOWN }
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
using SegmentIt = std::vector<Slic3r::Geometry::VoronoiDiagram::Segment>::iterator

Public Member Functions

 VoronoiDiagram ()=default
virtual ~VoronoiDiagram ()=default
IssueType get_issue_type () const
State get_state () const
bool is_valid () const
void clear ()
const vertex_container_type & vertices () const
const edge_container_type & edges () const
const cell_container_type & cells () const
std::size_t num_vertices () const
std::size_t num_edges () const
std::size_t num_cells () const
template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, void >::type construct_voronoi (SegmentIterator segment_begin, SegmentIterator segment_end, bool try_to_repair_if_needed=true)
template<typename PointIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_point_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< PointIterator >::value_type >::type >::type >::type, void >::type construct_voronoi (const PointIterator first, const PointIterator last)
template<typename PointIterator, typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_and< typenameboost::polygon::gtl_if< typenameboost::polygon::is_point_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< PointIterator >::value_type >::type >::type >::type, typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::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)
template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type try_to_repair_degenerated_voronoi_diagram_by_rotation (SegmentIterator segment_begin, SegmentIterator segment_end, double fix_angle)
template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type try_to_repair_degenerated_voronoi_diagram (SegmentIterator segment_begin, SegmentIterator segment_end)

Static Public Member Functions

template<typename SegmentIterator>
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, IssueType >::type detect_known_issues (const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)

Private Member Functions

void copy_to_local (voronoi_diagram_type &voronoi_diagram)

Static Private Member Functions

template<typename SegmentIterator>
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, IssueType >::type detect_known_voronoi_cell_issues (const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)
static IssueType detect_known_voronoi_edge_issues (const VoronoiDiagram &voronoi_diagram)

Private Attributes

voronoi_diagram_type m_voronoi_diagram
vertex_container_type m_vertices
edge_container_type m_edges
cell_container_type m_cells
bool m_is_modified = false
State m_state = State::UNKNOWN
IssueType m_issue_type = IssueType::UNKNOWN

Friends

struct boost::polygon::segment_traits< Slic3r::Geometry::VoronoiDiagram::Segment >

Detailed Description

Member Typedef Documentation

◆ cell_container_type

using Slic3r::Geometry::VoronoiDiagram::cell_container_type = voronoi_diagram_type::cell_container_type

◆ cell_type

using Slic3r::Geometry::VoronoiDiagram::cell_type = voronoi_diagram_type::cell_type

◆ const_cell_iterator

using Slic3r::Geometry::VoronoiDiagram::const_cell_iterator = voronoi_diagram_type::const_cell_iterator

◆ const_edge_iterator

using Slic3r::Geometry::VoronoiDiagram::const_edge_iterator = voronoi_diagram_type::const_edge_iterator

◆ const_vertex_iterator

using Slic3r::Geometry::VoronoiDiagram::const_vertex_iterator = voronoi_diagram_type::const_vertex_iterator

◆ coord_type

◆ coordinate_type

using Slic3r::Geometry::VoronoiDiagram::coordinate_type = voronoi_diagram_type::coordinate_type

◆ edge_container_type

using Slic3r::Geometry::VoronoiDiagram::edge_container_type = voronoi_diagram_type::edge_container_type

◆ edge_type

using Slic3r::Geometry::VoronoiDiagram::edge_type = voronoi_diagram_type::edge_type

◆ point_type

using Slic3r::Geometry::VoronoiDiagram::point_type = boost::polygon::point_data<voronoi_diagram_type::coordinate_type>

◆ rect_type

using Slic3r::Geometry::VoronoiDiagram::rect_type = boost::polygon::rectangle_data<voronoi_diagram_type::coordinate_type>

◆ segment_type

using Slic3r::Geometry::VoronoiDiagram::segment_type = boost::polygon::segment_data<voronoi_diagram_type::coordinate_type>

◆ SegmentIt

◆ vertex_container_type

using Slic3r::Geometry::VoronoiDiagram::vertex_container_type = voronoi_diagram_type::vertex_container_type

◆ vertex_type

using Slic3r::Geometry::VoronoiDiagram::vertex_type = voronoi_diagram_type::vertex_type

◆ voronoi_diagram_type

using Slic3r::Geometry::VoronoiDiagram::voronoi_diagram_type = boost::polygon::voronoi_diagram<coord_type>

Member Enumeration Documentation

◆ IssueType

Enumerator
NO_ISSUE_DETECTED 
FINITE_EDGE_WITH_NON_FINITE_VERTEX 
MISSING_VORONOI_VERTEX 
NON_PLANAR_VORONOI_DIAGRAM 
VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT 
PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT 
UNKNOWN 
52 {
53 NO_ISSUE_DETECTED,
54 FINITE_EDGE_WITH_NON_FINITE_VERTEX,
55 MISSING_VORONOI_VERTEX,
56 NON_PLANAR_VORONOI_DIAGRAM,
57 VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT,
58 PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT,
59 UNKNOWN // Repairs are disabled in the constructor.
60 };
@ UNKNOWN
Definition AMSDryControl.hpp:45

◆ State

Enumerator
REPAIR_NOT_NEEDED 
REPAIR_SUCCESSFUL 
REPAIR_UNSUCCESSFUL 
UNKNOWN 
62 {
63 REPAIR_NOT_NEEDED, // The original Voronoi diagram doesn't have any issue.
64 REPAIR_SUCCESSFUL, // The original Voronoi diagram has some issues, but it was repaired.
65 REPAIR_UNSUCCESSFUL, // The original Voronoi diagram has some issues, but it wasn't repaired.
66 UNKNOWN // Repairs are disabled in the constructor.
67 };

Constructor & Destructor Documentation

◆ VoronoiDiagram()

Slic3r::Geometry::VoronoiDiagram::VoronoiDiagram ( )
default

Referenced by detect_known_issues(), detect_known_voronoi_cell_issues(), and detect_known_voronoi_edge_issues().

Here is the caller graph for this function:

◆ ~VoronoiDiagram()

virtual Slic3r::Geometry::VoronoiDiagram::~VoronoiDiagram ( )
virtualdefault

Member Function Documentation

◆ cells()

const cell_container_type & Slic3r::Geometry::VoronoiDiagram::cells ( ) const
inline
85{ return m_is_modified ? m_cells : m_voronoi_diagram.cells(); }
bool m_is_modified
Definition Voronoi.hpp:182
voronoi_diagram_type m_voronoi_diagram
Definition Voronoi.hpp:178
cell_container_type m_cells
Definition Voronoi.hpp:181

References m_cells, m_is_modified, and m_voronoi_diagram.

Referenced by Slic3r::Arachne::SkeletalTrapezoidation::constructFromPolygons(), detect_known_voronoi_cell_issues(), Slic3r::Voronoi::reset_inside_outside_annotations(), and Slic3r::Voronoi::debug::verify_inside_outside_annotations().

Here is the caller graph for this function:

◆ clear()

void Slic3r::Geometry::VoronoiDiagram::clear ( )
82{
83 if (m_is_modified) {
84 m_vertices.clear();
85 m_edges.clear();
86 m_cells.clear();
87 m_is_modified = false;
88 } else {
89 m_voronoi_diagram.clear();
90 }
91
94}
State m_state
Definition Voronoi.hpp:183
vertex_container_type m_vertices
Definition Voronoi.hpp:179
@ UNKNOWN
Definition Voronoi.hpp:66
IssueType m_issue_type
Definition Voronoi.hpp:184
edge_container_type m_edges
Definition Voronoi.hpp:180

References m_cells, m_edges, m_is_modified, m_issue_type, m_state, m_vertices, m_voronoi_diagram, and UNKNOWN.

◆ construct_voronoi() [1/3]

template<typename PointIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_point_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< PointIterator >::value_type >::type >::type >::type, void >::type Slic3r::Geometry::VoronoiDiagram::construct_voronoi ( const PointIterator first,
const PointIterator last )
inline
106 {
107 boost::polygon::construct_voronoi(first, last, &m_voronoi_diagram);
110 }

References m_issue_type, m_state, m_voronoi_diagram, and UNKNOWN.

◆ construct_voronoi() [2/3]

template<typename PointIterator, typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_and< typenameboost::polygon::gtl_if< typenameboost::polygon::is_point_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< PointIterator >::value_type >::type >::type >::type, typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type >::type, void >::type Slic3r::Geometry::VoronoiDiagram::construct_voronoi ( const PointIterator p_first,
const PointIterator p_last,
const SegmentIterator s_first,
const SegmentIterator s_last )
inline
121 {
122 boost::polygon::construct_voronoi(p_first, p_last, s_first, s_last, &m_voronoi_diagram);
125 }

References m_issue_type, m_state, m_voronoi_diagram, and UNKNOWN.

◆ construct_voronoi() [3/3]

template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, void >::type Slic3r::Geometry::VoronoiDiagram::construct_voronoi ( SegmentIterator segment_begin,
SegmentIterator segment_end,
bool try_to_repair_if_needed = true )
34 {
35 boost::polygon::construct_voronoi(segment_begin, segment_end, &m_voronoi_diagram);
36 if (try_to_repair_if_needed) {
37 if (m_issue_type = detect_known_issues(*this, segment_begin, segment_end); m_issue_type != IssueType::NO_ISSUE_DETECTED) {
39 BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth.";
41 BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth.";
43 BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth.";
45 BOOST_LOG_TRIVIAL(warning) << "Detected finite Voronoi vertex with non finite vertex, input polygons will be rotated back and forth.";
47 BOOST_LOG_TRIVIAL(warning) << "Detected parabolic Voronoi edges without focus point, input polygons will be rotated back and forth.";
48 } else {
49 BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue, input polygons will be rotated back and forth.";
50 }
51
54 BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input.";
56 BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input.";
58 BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input.";
60 BOOST_LOG_TRIVIAL(error) << "Detected finite Voronoi vertex with non finite vertex even after the rotation of input.";
62 BOOST_LOG_TRIVIAL(error) << "Detected parabolic Voronoi edges without focus point even after the rotation of input.";
63 } else {
64 BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue even after the rotation of input.";
65 }
66
68 } else {
70 }
71 } else {
74 }
75 } else {
78 }
79}
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, IssueType >::type detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)
Definition Voronoi.cpp:172
@ FINITE_EDGE_WITH_NON_FINITE_VERTEX
Definition Voronoi.hpp:54
@ VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT
Definition Voronoi.hpp:57
@ NO_ISSUE_DETECTED
Definition Voronoi.hpp:53
@ NON_PLANAR_VORONOI_DIAGRAM
Definition Voronoi.hpp:56
@ MISSING_VORONOI_VERTEX
Definition Voronoi.hpp:55
@ PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT
Definition Voronoi.hpp:58
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type try_to_repair_degenerated_voronoi_diagram(SegmentIterator segment_begin, SegmentIterator segment_end)
Definition Voronoi.cpp:254
@ REPAIR_NOT_NEEDED
Definition Voronoi.hpp:63
@ REPAIR_UNSUCCESSFUL
Definition Voronoi.hpp:65
@ REPAIR_SUCCESSFUL
Definition Voronoi.hpp:64

References detect_known_issues(), FINITE_EDGE_WITH_NON_FINITE_VERTEX, m_issue_type, m_state, m_voronoi_diagram, MISSING_VORONOI_VERTEX, NO_ISSUE_DETECTED, NON_PLANAR_VORONOI_DIAGRAM, PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT, REPAIR_NOT_NEEDED, REPAIR_SUCCESSFUL, REPAIR_UNSUCCESSFUL, try_to_repair_degenerated_voronoi_diagram(), UNKNOWN, and VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT.

Referenced by Slic3r::build_graph(), and Slic3r::Arachne::SkeletalTrapezoidation::constructFromPolygons().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ copy_to_local()

void Slic3r::Geometry::VoronoiDiagram::copy_to_local ( voronoi_diagram_type & voronoi_diagram)
private
96 {
97 m_edges.clear();
98 m_cells.clear();
99 m_vertices.clear();
100
101 // Copy Voronoi edges.
102 m_edges.reserve(voronoi_diagram.num_edges());
103 for (const edge_type &edge : voronoi_diagram.edges()) {
104 m_edges.emplace_back(edge.is_linear(), edge.is_primary());
105 m_edges.back().color(edge.color());
106 }
107
108 // Copy Voronoi cells.
109 m_cells.reserve(voronoi_diagram.num_cells());
110 for (const cell_type &cell : voronoi_diagram.cells()) {
111 m_cells.emplace_back(cell.source_index(), cell.source_category());
112 m_cells.back().color(cell.color());
113
114 if (cell.incident_edge()) {
115 size_t incident_edge_idx = cell.incident_edge() - voronoi_diagram.edges().data();
116 m_cells.back().incident_edge(&m_edges[incident_edge_idx]);
117 }
118 }
119
120 // Copy Voronoi vertices.
121 m_vertices.reserve(voronoi_diagram.num_vertices());
122 for (const vertex_type &vertex : voronoi_diagram.vertices()) {
123 m_vertices.emplace_back(vertex.x(), vertex.y());
124 m_vertices.back().color(vertex.color());
125
126 if (vertex.incident_edge()) {
127 size_t incident_edge_idx = vertex.incident_edge() - voronoi_diagram.edges().data();
128 m_vertices.back().incident_edge(&m_edges[incident_edge_idx]);
129 }
130 }
131
132 // Assign all pointers for each Voronoi edge.
133 for (const edge_type &old_edge : voronoi_diagram.edges()) {
134 size_t edge_idx = &old_edge - voronoi_diagram.edges().data();
135 edge_type &new_edge = m_edges[edge_idx];
136
137 if (old_edge.cell()) {
138 size_t cell_idx = old_edge.cell() - voronoi_diagram.cells().data();
139 new_edge.cell(&m_cells[cell_idx]);
140 }
141
142 if (old_edge.vertex0()) {
143 size_t vertex0_idx = old_edge.vertex0() - voronoi_diagram.vertices().data();
144 new_edge.vertex0(&m_vertices[vertex0_idx]);
145 }
146
147 if (old_edge.twin()) {
148 size_t twin_edge_idx = old_edge.twin() - voronoi_diagram.edges().data();
149 new_edge.twin(&m_edges[twin_edge_idx]);
150 }
151
152 if (old_edge.next()) {
153 size_t next_edge_idx = old_edge.next() - voronoi_diagram.edges().data();
154 new_edge.next(&m_edges[next_edge_idx]);
155 }
156
157 if (old_edge.prev()) {
158 size_t prev_edge_idx = old_edge.prev() - voronoi_diagram.edges().data();
159 new_edge.prev(&m_edges[prev_edge_idx]);
160 }
161 }
162
163 m_voronoi_diagram.clear();
164 m_is_modified = true;
165}
voronoi_diagram_type::cell_type cell_type
Definition Voronoi.hpp:42
voronoi_diagram_type::vertex_type vertex_type
Definition Voronoi.hpp:40
voronoi_diagram_type::edge_type edge_type
Definition Voronoi.hpp:41

References m_cells, m_edges, m_is_modified, m_vertices, and m_voronoi_diagram.

Referenced by try_to_repair_degenerated_voronoi_diagram_by_rotation().

Here is the caller graph for this function:

◆ detect_known_issues()

template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type Slic3r::Geometry::VoronoiDiagram::detect_known_issues ( const VoronoiDiagram & voronoi_diagram,
SegmentIterator segment_begin,
SegmentIterator segment_end )
static
173{
174 if (const IssueType edge_issue_type = detect_known_voronoi_edge_issues(voronoi_diagram); edge_issue_type != IssueType::NO_ISSUE_DETECTED) {
175 return edge_issue_type;
176 } else if (const IssueType cell_issue_type = detect_known_voronoi_cell_issues(voronoi_diagram, segment_begin, segment_end); cell_issue_type != IssueType::NO_ISSUE_DETECTED) {
177 return cell_issue_type;
178 } else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) {
179 // Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446.
181 }
182
184}
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, IssueType >::type detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)
Definition Voronoi.cpp:191
static IssueType detect_known_voronoi_edge_issues(const VoronoiDiagram &voronoi_diagram)
Definition Voronoi.cpp:233
IssueType
Definition Voronoi.hpp:52
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, bool >::type is_voronoi_diagram_planar_angle(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)

References VoronoiDiagram(), detect_known_voronoi_cell_issues(), detect_known_voronoi_edge_issues(), Slic3r::Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(), NO_ISSUE_DETECTED, and NON_PLANAR_VORONOI_DIAGRAM.

Referenced by construct_voronoi(), and try_to_repair_degenerated_voronoi_diagram_by_rotation().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ detect_known_voronoi_cell_issues()

template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type Slic3r::Geometry::VoronoiDiagram::detect_known_voronoi_cell_issues ( const VoronoiDiagram & voronoi_diagram,
SegmentIterator segment_begin,
SegmentIterator segment_end )
staticprivate
194{
195 using Segment = typename std::iterator_traits<SegmentIterator>::value_type;
196 using Point = typename boost::polygon::segment_point_type<Segment>::type;
197 using SegmentCellRange = SegmentCellRange<Point>;
198
199 for (VD::cell_type cell : voronoi_diagram.cells()) {
200 if (cell.is_degenerate() || !cell.contains_segment())
201 continue; // Skip degenerated cell that has no spoon. Also, skip a cell that doesn't contain a segment.
202
203 if (const SegmentCellRange cell_range = VoronoiUtils::compute_segment_cell_range(cell, segment_begin, segment_end); cell_range.is_valid()) {
204 // Detection if Voronoi edge is intersecting input segment.
205 // It detects this type of issue at least in GH issues #8446, #8474 and #8514.
206
207 const Segment &source_segment = Geometry::VoronoiUtils::get_source_segment(cell, segment_begin, segment_end);
208 const Vec2d source_segment_from = boost::polygon::segment_traits<Segment>::get(source_segment, boost::polygon::LOW).template cast<double>();
209 const Vec2d source_segment_to = boost::polygon::segment_traits<Segment>::get(source_segment, boost::polygon::HIGH).template cast<double>();
210 const Vec2d source_segment_vec = source_segment_to - source_segment_from;
211
212 // All Voronoi vertices must be on the left side of the source segment, otherwise the Voronoi diagram is invalid.
213 for (const VD::edge_type *edge = cell_range.edge_begin; edge != cell_range.edge_end; edge = edge->next()) {
214 if (edge->is_infinite()) {
215 // When there is a missing Voronoi vertex, we may encounter an infinite Voronoi edge.
216 // This happens, for example, in GH issue #8846.
218 } else if (const Vec2d edge_v1(edge->vertex1()->x(), edge->vertex1()->y()); Slic3r::cross2(source_segment_vec, edge_v1 - source_segment_from) < 0) {
220 }
221 }
222 } else {
223 // When there is a missing Voronoi vertex (especially at one of the endpoints of the input segment),
224 // the returned cell_range is marked as invalid.
225 // It detects this type of issue at least in GH issue #8846.
227 }
228 }
229
231}
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, Geometry::SegmentCellRange< typenameboost::polygon::segment_point_type< typenamestd::iterator_traits< SegmentIterator >::value_type >::type > >::type compute_segment_cell_range(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end)
Definition VoronoiUtils.cpp:218
static boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, typenamestd::iterator_traits< SegmentIterator >::reference >::type get_source_segment(const VoronoiDiagram::cell_type &cell, SegmentIterator segment_begin, SegmentIterator segment_end)
Definition VoronoiUtils.cpp:53
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
int32_t cross2(const Eigen::MatrixBase< Eigen::Matrix< int32_t, 2, 1, Options > > &v1, const Eigen::MatrixBase< Eigen::Matrix< int32_t, 2, 1, Options > > &v2)=delete
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
auto cast(const BoundingBoxBase< Tin > &b)
Definition BoundingBox.hpp:299

References VoronoiDiagram(), Slic3r::cast(), cells(), Slic3r::Geometry::VoronoiUtils::compute_segment_cell_range(), Slic3r::cross2(), Slic3r::Geometry::VoronoiUtils::get_source_segment(), MISSING_VORONOI_VERTEX, NO_ISSUE_DETECTED, and VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT.

Referenced by detect_known_issues().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ detect_known_voronoi_edge_issues()

VoronoiDiagram::IssueType Slic3r::Geometry::VoronoiDiagram::detect_known_voronoi_edge_issues ( const VoronoiDiagram & voronoi_diagram)
staticprivate
234{
235 for (const voronoi_diagram_type::edge_type &edge : voronoi_diagram.edges()) {
236 if (edge.is_finite()) {
237 assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr);
238 if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || !VoronoiUtils::is_finite(*edge.vertex1()))
240
241 if (edge.is_curved() && !edge.cell()->contains_point() && !edge.twin()->cell()->contains_point())
243 }
244 }
245
247}
static bool is_finite(const VoronoiDiagram::vertex_type &vertex)
Definition VoronoiUtils.cpp:334

References VoronoiDiagram(), edges(), FINITE_EDGE_WITH_NON_FINITE_VERTEX, Slic3r::Geometry::VoronoiUtils::is_finite(), NO_ISSUE_DETECTED, and PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT.

Referenced by detect_known_issues().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ edges()

◆ get_issue_type()

IssueType Slic3r::Geometry::VoronoiDiagram::get_issue_type ( ) const
inline
73{ return m_issue_type; }

References m_issue_type.

◆ get_state()

State Slic3r::Geometry::VoronoiDiagram::get_state ( ) const
inline
75{ return m_state; }

References m_state.

◆ is_valid()

bool Slic3r::Geometry::VoronoiDiagram::is_valid ( ) const
inline

◆ num_cells()

std::size_t Slic3r::Geometry::VoronoiDiagram::num_cells ( ) const
inline
91{ return m_is_modified ? m_cells.size() : m_voronoi_diagram.num_cells(); }

References m_cells, m_is_modified, and m_voronoi_diagram.

◆ num_edges()

std::size_t Slic3r::Geometry::VoronoiDiagram::num_edges ( ) const
inline
89{ return m_is_modified ? m_edges.size() : m_voronoi_diagram.num_edges(); }

References m_edges, m_is_modified, and m_voronoi_diagram.

Referenced by Slic3r::Voronoi::edge_offset_contour_intersections(), Slic3r::Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(), Slic3r::Voronoi::offset(), Slic3r::Voronoi::skeleton_edges_rough(), and Slic3r::Voronoi::debug::verify_twin_halfedges_successive().

Here is the caller graph for this function:

◆ num_vertices()

std::size_t Slic3r::Geometry::VoronoiDiagram::num_vertices ( ) const
inline
87{ return m_is_modified ? m_vertices.size() : m_voronoi_diagram.num_vertices(); }

References m_is_modified, m_vertices, and m_voronoi_diagram.

◆ try_to_repair_degenerated_voronoi_diagram()

template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type Slic3r::Geometry::VoronoiDiagram::try_to_repair_degenerated_voronoi_diagram ( SegmentIterator segment_begin,
SegmentIterator segment_end )
255{
256 IssueType issue_type = m_issue_type;
257
258 const std::vector<double> fix_angles = {PI / 6, PI / 5, PI / 7, PI / 11};
259 for (const double fix_angle : fix_angles) {
260 issue_type = try_to_repair_degenerated_voronoi_diagram_by_rotation(segment_begin, segment_end, fix_angle);
261 if (issue_type == IssueType::NO_ISSUE_DETECTED) {
262 return issue_type;
263 }
264 }
265
266 return issue_type;
267}
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type try_to_repair_degenerated_voronoi_diagram_by_rotation(SegmentIterator segment_begin, SegmentIterator segment_end, double fix_angle)
Definition Voronoi.cpp:296
static constexpr double PI
Definition libslic3r.h:81

References m_issue_type, NO_ISSUE_DETECTED, PI, and try_to_repair_degenerated_voronoi_diagram_by_rotation().

Referenced by construct_voronoi().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ try_to_repair_degenerated_voronoi_diagram_by_rotation()

template<typename SegmentIterator>
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, VoronoiDiagram::IssueType >::type Slic3r::Geometry::VoronoiDiagram::try_to_repair_degenerated_voronoi_diagram_by_rotation ( SegmentIterator segment_begin,
SegmentIterator segment_end,
double fix_angle )
299{
300 using SegmentType = typename std::iterator_traits<SegmentIterator>::value_type;
301 using PointType = typename boost::polygon::segment_traits<SegmentType>::point_type;
302
303 // Copy all segments and rotate their vertices.
304 std::vector<VoronoiDiagram::Segment> segments_rotated;
305 segments_rotated.reserve(std::distance(segment_begin, segment_end));
306 for (auto segment_it = segment_begin; segment_it != segment_end; ++segment_it) {
307 PointType from = boost::polygon::segment_traits<SegmentType>::get(*segment_it, boost::polygon::LOW);
308 PointType to = boost::polygon::segment_traits<SegmentType>::get(*segment_it, boost::polygon::HIGH);
309 segments_rotated.emplace_back(from.rotated(fix_angle), to.rotated(fix_angle));
310 }
311
312 VoronoiDiagram::voronoi_diagram_type voronoi_diagram_rotated;
313 boost::polygon::construct_voronoi(segments_rotated.begin(), segments_rotated.end(), &voronoi_diagram_rotated);
314
315 this->copy_to_local(voronoi_diagram_rotated);
316 const IssueType issue_type = detect_known_issues(*this, segments_rotated.begin(), segments_rotated.end());
317
318 // We want to remap all Voronoi vertices at the endpoints of input segments
319 // to ensure that Voronoi vertices at endpoints will be preserved after rotation.
320 // So we assign every Voronoi vertices color to map this Vertex into input segments.
321 for (cell_type cell : m_cells) {
322 if (cell.is_degenerate())
323 continue;
324
325 if (cell.contains_segment()) {
326 if (const SegmentCellRange cell_range = VoronoiUtils::compute_segment_cell_range(cell, segments_rotated.begin(), segments_rotated.end()); cell_range.is_valid()) {
327 if (cell_range.edge_end->vertex1()->color() == 0) {
328 // Vertex 1 of edge_end points to the starting endpoint of the input segment (from() or line.a).
329 VD::vertex_type::color_type color = encode_input_segment_endpoint(cell.source_index(), boost::polygon::LOW);
330 cell_range.edge_end->vertex1()->color(color);
331 }
332
333 if (cell_range.edge_begin->vertex0()->color() == 0) {
334 // Vertex 0 of edge_end points to the ending endpoint of the input segment (to() or line.b).
335 VD::vertex_type::color_type color = encode_input_segment_endpoint(cell.source_index(), boost::polygon::HIGH);
336 cell_range.edge_begin->vertex0()->color(color);
337 }
338 } else {
339 // This could happen when there is a missing Voronoi vertex even after rotation.
340 assert(cell_range.is_valid());
341 }
342 }
343
344 // FIXME @hejllukas: Implement mapping also for source points and not just for source segments.
345 }
346
347 // Rotate all Voronoi vertices back.
348 // When a Voronoi vertex can be mapped to the input segment endpoint, then we don't need to do rotation back.
349 for (vertex_type &vertex : m_vertices) {
350 if (vertex.color() == 0) {
351 // This vertex isn't mapped to any vertex, so we rotate it back.
352 vertex = VoronoiUtils::make_rotated_vertex(vertex, -fix_angle);
353 } else {
354 // This vertex can be mapped to the input segment endpoint.
355 PointType endpoint = decode_input_segment_endpoint(vertex.color(), segment_begin, segment_end);
356 vertex_type endpoint_vertex{double(endpoint.x()), double(endpoint.y())};
357 endpoint_vertex.incident_edge(vertex.incident_edge());
358 endpoint_vertex.color(vertex.color());
359 vertex = endpoint_vertex;
360 }
361 }
362
363 // We have to clear all marked vertices because some algorithms expect that all vertices have a color equal to 0.
364 for (vertex_type &vertex : m_vertices)
365 vertex.color(0);
366
367 return issue_type;
368}
void copy_to_local(voronoi_diagram_type &voronoi_diagram)
Definition Voronoi.cpp:96
boost::polygon::voronoi_diagram< coord_type > voronoi_diagram_type
Definition Voronoi.hpp:34
static VoronoiDiagram::vertex_type make_rotated_vertex(VoronoiDiagram::vertex_type &vertex, double angle)
Definition VoronoiUtils.cpp:339
VD::vertex_type::color_type encode_input_segment_endpoint(const VD::cell_type::source_index_type cell_source_index, const boost::polygon::direction_1d dir)
Definition Voronoi.cpp:269
boost::polygon::enable_if< typenameboost::polygon::gtl_if< typenameboost::polygon::is_segment_concept< typenameboost::polygon::geometry_concept< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type >::type, typenameboost::polygon::segment_point_type< typenamestd::iterator_traits< SegmentIterator >::value_type >::type >::type decode_input_segment_endpoint(const VD::vertex_type::color_type color, const SegmentIterator segment_begin, const SegmentIterator segment_end)
Definition Voronoi.cpp:279

References Slic3r::Geometry::VoronoiUtils::compute_segment_cell_range(), copy_to_local(), Slic3r::Geometry::decode_input_segment_endpoint(), detect_known_issues(), Slic3r::Geometry::encode_input_segment_endpoint(), m_cells, m_vertices, and Slic3r::Geometry::VoronoiUtils::make_rotated_vertex().

Referenced by try_to_repair_degenerated_voronoi_diagram().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ vertices()

◆ boost::polygon::segment_traits< Slic3r::Geometry::VoronoiDiagram::Segment >

Member Data Documentation

◆ m_cells

cell_container_type Slic3r::Geometry::VoronoiDiagram::m_cells
private

◆ m_edges

edge_container_type Slic3r::Geometry::VoronoiDiagram::m_edges
private

Referenced by clear(), copy_to_local(), edges(), and num_edges().

◆ m_is_modified

bool Slic3r::Geometry::VoronoiDiagram::m_is_modified = false
private

◆ m_issue_type

◆ m_state

State Slic3r::Geometry::VoronoiDiagram::m_state = State::UNKNOWN
private

◆ m_vertices

vertex_container_type Slic3r::Geometry::VoronoiDiagram::m_vertices
private

◆ m_voronoi_diagram


The documentation for this class was generated from the following files:
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Geometry/Voronoi.hpp
  • /home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/Geometry/Voronoi.cpp