Refactored code for the detection of degenerated Voronoi diagrams. Added detection for cases when some Voronoi edge is intersection input segments, which should fix another case reported in #8846.
This commit is contained in:
parent
8ac60ccc7a
commit
22091a9e3e
@ -573,6 +573,59 @@ 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)
|
||||||
|
{
|
||||||
|
for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) {
|
||||||
|
if (!cell.incident_edge())
|
||||||
|
continue; // Degenerated cell, there is no spoon
|
||||||
|
|
||||||
|
if (!cell.contains_segment())
|
||||||
|
continue; // Skip cells that don't contain segments.
|
||||||
|
|
||||||
|
const VoronoiUtils::Segment &source_segment = VoronoiUtils::getSourceSegment(cell, segments);
|
||||||
|
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;
|
||||||
|
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())
|
||||||
|
if (const Vec2d edge_v1(edge->vertex1()->x(), edge->vertex1()->y()); Slic3r::cross2(source_segment_vec, edge_v1 - source_segment_from) < 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class VoronoiDiagramStatus {
|
||||||
|
NO_ISSUE_DETECTED,
|
||||||
|
MISSING_VORONOI_VERTEX,
|
||||||
|
NON_PLANAR_VORONOI_DIAGRAM,
|
||||||
|
VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT,
|
||||||
|
OTHER_TYPE_OF_VORONOI_DIAGRAM_DEGENERATION
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
const std::vector<SkeletalTrapezoidation::Segment> &segments)
|
||||||
|
{
|
||||||
|
if (const bool has_missing_voronoi_vertex = detect_missing_voronoi_vertex(voronoi_diagram, segments); has_missing_voronoi_vertex) {
|
||||||
|
return VoronoiDiagramStatus::MISSING_VORONOI_VERTEX;
|
||||||
|
} else if (const bool has_voronoi_edge_intersecting_input_segment = detect_voronoi_edge_intersecting_input_segment(voronoi_diagram, segments); has_voronoi_edge_intersecting_input_segment) {
|
||||||
|
// Detection if Voronoi edge is intersecting input segment detects at least one model in GH issue #8446.
|
||||||
|
return VoronoiDiagramStatus::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT;
|
||||||
|
} else if (const bool is_voronoi_diagram_planar = Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments); !is_voronoi_diagram_planar) {
|
||||||
|
// Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514 and #8446.
|
||||||
|
return VoronoiDiagramStatus::NON_PLANAR_VORONOI_DIAGRAM;
|
||||||
|
}
|
||||||
|
return VoronoiDiagramStatus::NO_ISSUE_DETECTED;
|
||||||
|
}
|
||||||
|
|
||||||
void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
||||||
{
|
{
|
||||||
#ifdef ARACHNE_DEBUG
|
#ifdef ARACHNE_DEBUG
|
||||||
@ -614,36 +667,35 @@ void SkeletalTrapezoidation::constructFromPolygons(const Polygons& polys)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Try to detect cases when some Voronoi vertex is missing and when
|
// When any Voronoi vertex is missing, the Voronoi diagram is not planar, or some voronoi edge is
|
||||||
// the Voronoi diagram is not planar.
|
// intersecting input segment, rotate the input polygon and try again.
|
||||||
// When any Voronoi vertex is missing, or the Voronoi diagram is not
|
VoronoiDiagramStatus status = detect_voronoi_diagram_known_issues(voronoi_diagram, segments);
|
||||||
// planar, rotate the input polygon and try again.
|
|
||||||
const bool has_missing_voronoi_vertex = detect_missing_voronoi_vertex(voronoi_diagram, segments);
|
|
||||||
// Detection of non-planar Voronoi diagram detects at least GH issues #8474, #8514, #8446 and #8846.
|
|
||||||
const bool is_voronoi_diagram_planar = Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments);
|
|
||||||
const double fix_angle = PI / 6;
|
const double fix_angle = PI / 6;
|
||||||
|
|
||||||
std::unordered_map<Point, Point, PointHash> vertex_mapping;
|
std::unordered_map<Point, Point, PointHash> vertex_mapping;
|
||||||
// polys_copy is referenced through items stored in the std::vector segments.
|
// polys_copy is referenced through items stored in the std::vector segments.
|
||||||
Polygons polys_copy = polys;
|
Polygons polys_copy = polys;
|
||||||
if (has_missing_voronoi_vertex || !is_voronoi_diagram_planar) {
|
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
|
||||||
if (has_missing_voronoi_vertex)
|
if (status == VoronoiDiagramStatus::MISSING_VORONOI_VERTEX)
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth.";
|
BOOST_LOG_TRIVIAL(warning) << "Detected missing Voronoi vertex, input polygons will be rotated back and forth.";
|
||||||
else if (!is_voronoi_diagram_planar)
|
else if (status == VoronoiDiagramStatus::NON_PLANAR_VORONOI_DIAGRAM)
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth.";
|
BOOST_LOG_TRIVIAL(warning) << "Detected non-planar Voronoi diagram, input polygons will be rotated back and forth.";
|
||||||
|
else if (status == VoronoiDiagramStatus::VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT)
|
||||||
|
BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth.";
|
||||||
|
|
||||||
vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle);
|
vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle);
|
||||||
|
|
||||||
assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments));
|
assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments));
|
||||||
assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments));
|
assert(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments));
|
||||||
|
assert(!detect_voronoi_edge_intersecting_input_segment(voronoi_diagram, segments));
|
||||||
if (detect_missing_voronoi_vertex(voronoi_diagram, segments))
|
if (detect_missing_voronoi_vertex(voronoi_diagram, segments))
|
||||||
BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input.";
|
BOOST_LOG_TRIVIAL(error) << "Detected missing Voronoi vertex even after the rotation of input.";
|
||||||
else if (!Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments))
|
else if (!Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segments))
|
||||||
BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input.";
|
BOOST_LOG_TRIVIAL(error) << "Detected non-planar Voronoi diagram even after the rotation of input.";
|
||||||
|
else if (detect_voronoi_edge_intersecting_input_segment(voronoi_diagram, segments))
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input.";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool degenerated_voronoi_diagram = has_missing_voronoi_vertex || !is_voronoi_diagram_planar;
|
|
||||||
|
|
||||||
process_voronoi_diagram:
|
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());
|
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_t::cell_type cell : voronoi_diagram.cells()) {
|
||||||
@ -652,35 +704,35 @@ process_voronoi_diagram:
|
|||||||
|
|
||||||
Point start_source_point;
|
Point start_source_point;
|
||||||
Point end_source_point;
|
Point end_source_point;
|
||||||
vd_t::edge_type* starting_vonoroi_edge = nullptr;
|
vd_t::edge_type* starting_voronoi_edge = nullptr;
|
||||||
vd_t::edge_type* ending_vonoroi_edge = nullptr;
|
vd_t::edge_type* ending_voronoi_edge = nullptr;
|
||||||
// Compute and store result in above variables
|
// Compute and store result in above variables
|
||||||
|
|
||||||
if (cell.contains_point()) {
|
if (cell.contains_point()) {
|
||||||
const bool keep_going = computePointCellRange(cell, start_source_point, end_source_point, starting_vonoroi_edge, ending_vonoroi_edge, segments);
|
const bool keep_going = computePointCellRange(cell, start_source_point, end_source_point, starting_voronoi_edge, ending_voronoi_edge, segments);
|
||||||
if (!keep_going)
|
if (!keep_going)
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
assert(cell.contains_segment());
|
assert(cell.contains_segment());
|
||||||
computeSegmentCellRange(cell, start_source_point, end_source_point, starting_vonoroi_edge, ending_vonoroi_edge, segments);
|
computeSegmentCellRange(cell, start_source_point, end_source_point, starting_voronoi_edge, ending_voronoi_edge, segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!starting_vonoroi_edge || !ending_vonoroi_edge) {
|
if (!starting_voronoi_edge || !ending_voronoi_edge) {
|
||||||
assert(false && "Each cell should start / end in a polygon vertex");
|
assert(false && "Each cell should start / end in a polygon vertex");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy start to end edge to graph
|
// Copy start to end edge to graph
|
||||||
edge_t* prev_edge = nullptr;
|
edge_t* prev_edge = nullptr;
|
||||||
assert(VoronoiUtils::p(starting_vonoroi_edge->vertex1()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex1()).x() >= std::numeric_limits<coord_t>::lowest());
|
assert(VoronoiUtils::p(starting_voronoi_edge->vertex1()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex1()).x() >= std::numeric_limits<coord_t>::lowest());
|
||||||
assert(VoronoiUtils::p(starting_vonoroi_edge->vertex1()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex1()).y() >= std::numeric_limits<coord_t>::lowest());
|
assert(VoronoiUtils::p(starting_voronoi_edge->vertex1()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex1()).y() >= std::numeric_limits<coord_t>::lowest());
|
||||||
transferEdge(start_source_point, VoronoiUtils::p(starting_vonoroi_edge->vertex1()).cast<coord_t>(), *starting_vonoroi_edge, prev_edge, start_source_point, end_source_point, segments);
|
transferEdge(start_source_point, VoronoiUtils::p(starting_voronoi_edge->vertex1()).cast<coord_t>(), *starting_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
|
||||||
node_t* starting_node = vd_node_to_he_node[starting_vonoroi_edge->vertex0()];
|
node_t* starting_node = vd_node_to_he_node[starting_voronoi_edge->vertex0()];
|
||||||
starting_node->data.distance_to_boundary = 0;
|
starting_node->data.distance_to_boundary = 0;
|
||||||
|
|
||||||
constexpr bool is_next_to_start_or_end = true;
|
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);
|
graph.makeRib(prev_edge, start_source_point, end_source_point, is_next_to_start_or_end);
|
||||||
for (vd_t::edge_type* vd_edge = starting_vonoroi_edge->next(); vd_edge != ending_vonoroi_edge; vd_edge = vd_edge->next()) {
|
for (vd_t::edge_type* vd_edge = starting_voronoi_edge->next(); vd_edge != ending_voronoi_edge; vd_edge = vd_edge->next()) {
|
||||||
assert(vd_edge->is_finite());
|
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());
|
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());
|
||||||
@ -692,12 +744,12 @@ process_voronoi_diagram:
|
|||||||
Point v2 = VoronoiUtils::p(vd_edge->vertex1()).cast<coord_t>();
|
Point v2 = VoronoiUtils::p(vd_edge->vertex1()).cast<coord_t>();
|
||||||
transferEdge(v1, v2, *vd_edge, prev_edge, start_source_point, end_source_point, segments);
|
transferEdge(v1, v2, *vd_edge, prev_edge, start_source_point, end_source_point, segments);
|
||||||
|
|
||||||
graph.makeRib(prev_edge, start_source_point, end_source_point, vd_edge->next() == ending_vonoroi_edge);
|
graph.makeRib(prev_edge, start_source_point, end_source_point, vd_edge->next() == ending_voronoi_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(VoronoiUtils::p(starting_vonoroi_edge->vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
|
assert(VoronoiUtils::p(starting_voronoi_edge->vertex0()).x() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex0()).x() >= std::numeric_limits<coord_t>::lowest());
|
||||||
assert(VoronoiUtils::p(starting_vonoroi_edge->vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_vonoroi_edge->vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
|
assert(VoronoiUtils::p(starting_voronoi_edge->vertex0()).y() <= std::numeric_limits<coord_t>::max() && VoronoiUtils::p(starting_voronoi_edge->vertex0()).y() >= std::numeric_limits<coord_t>::lowest());
|
||||||
transferEdge(VoronoiUtils::p(ending_vonoroi_edge->vertex0()).cast<coord_t>(), end_source_point, *ending_vonoroi_edge, prev_edge, start_source_point, end_source_point, segments);
|
transferEdge(VoronoiUtils::p(ending_voronoi_edge->vertex0()).cast<coord_t>(), end_source_point, *ending_voronoi_edge, prev_edge, start_source_point, end_source_point, segments);
|
||||||
prev_edge->to->data.distance_to_boundary = 0;
|
prev_edge->to->data.distance_to_boundary = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,9 +757,9 @@ process_voronoi_diagram:
|
|||||||
// When this degenerated Voronoi diagram is processed, the resulting half-edge structure contains some edges that don't have
|
// When this degenerated Voronoi diagram is processed, the resulting half-edge structure contains some edges that don't have
|
||||||
// a twin edge. Based on this, we created a fast mechanism that detects those causes and tries to recompute the Voronoi
|
// a twin edge. Based on this, we created a fast mechanism that detects those causes and tries to recompute the Voronoi
|
||||||
// diagram on slightly rotated input polygons that usually make the Voronoi generator generate a non-degenerated Voronoi diagram.
|
// diagram on slightly rotated input polygons that usually make the Voronoi generator generate a non-degenerated Voronoi diagram.
|
||||||
if (!degenerated_voronoi_diagram && has_missing_twin_edge(this->graph)) {
|
if (status == VoronoiDiagramStatus::NO_ISSUE_DETECTED && has_missing_twin_edge(this->graph)) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << "Detected degenerated Voronoi diagram, input polygons will be rotated back and forth.";
|
BOOST_LOG_TRIVIAL(warning) << "Detected degenerated Voronoi diagram, input polygons will be rotated back and forth.";
|
||||||
degenerated_voronoi_diagram = true;
|
status = VoronoiDiagramStatus::OTHER_TYPE_OF_VORONOI_DIAGRAM_DEGENERATION;
|
||||||
vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle);
|
vertex_mapping = try_to_fix_degenerated_voronoi_diagram_by_rotation(voronoi_diagram, polys, polys_copy, segments, fix_angle);
|
||||||
|
|
||||||
assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments));
|
assert(!detect_missing_voronoi_vertex(voronoi_diagram, segments));
|
||||||
@ -724,14 +776,14 @@ process_voronoi_diagram:
|
|||||||
goto process_voronoi_diagram;
|
goto process_voronoi_diagram;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (degenerated_voronoi_diagram) {
|
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED) {
|
||||||
assert(!has_missing_twin_edge(this->graph));
|
assert(!has_missing_twin_edge(this->graph));
|
||||||
|
|
||||||
if (has_missing_twin_edge(this->graph))
|
if (has_missing_twin_edge(this->graph))
|
||||||
BOOST_LOG_TRIVIAL(error) << "Detected degenerated Voronoi diagram even after the rotation of input.";
|
BOOST_LOG_TRIVIAL(error) << "Detected degenerated Voronoi diagram even after the rotation of input.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (degenerated_voronoi_diagram)
|
if (status != VoronoiDiagramStatus::NO_ISSUE_DETECTED)
|
||||||
rotate_back_skeletal_trapezoidation_graph_after_fix(this->graph, fix_angle, vertex_mapping);
|
rotate_back_skeletal_trapezoidation_graph_after_fix(this->graph, fix_angle, vertex_mapping);
|
||||||
|
|
||||||
#ifdef ARACHNE_DEBUG
|
#ifdef ARACHNE_DEBUG
|
||||||
@ -742,7 +794,7 @@ process_voronoi_diagram:
|
|||||||
|
|
||||||
graph.collapseSmallEdges();
|
graph.collapseSmallEdges();
|
||||||
|
|
||||||
// Set [incident_edge] the the first possible edge that way we can iterate over all reachable edges from node.incident_edge,
|
// Set [incident_edge] the first possible edge that way we can iterate over all reachable edges from node.incident_edge,
|
||||||
// without needing to iterate backward
|
// without needing to iterate backward
|
||||||
for (edge_t& edge : graph.edges)
|
for (edge_t& edge : graph.edges)
|
||||||
if (!edge.prev)
|
if (!edge.prev)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <memory> // smart pointers
|
#include <memory> // smart pointers
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility> // pair
|
#include <utility> // pair
|
||||||
|
#include <Arachne/utils/VoronoiUtils.hpp>
|
||||||
|
|
||||||
#include "utils/HalfEdgeGraph.hpp"
|
#include "utils/HalfEdgeGraph.hpp"
|
||||||
#include "utils/PolygonsSegmentIndex.hpp"
|
#include "utils/PolygonsSegmentIndex.hpp"
|
||||||
@ -229,7 +230,7 @@ protected:
|
|||||||
* /return Whether the cell is inside of the polygon. If it's outside of the
|
* /return Whether the cell is inside of the polygon. If it's outside of the
|
||||||
* polygon we should skip processing it altogether.
|
* polygon we should skip processing it altogether.
|
||||||
*/
|
*/
|
||||||
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_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);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Compute the range of line segments that surround a cell of the skeletal
|
* Compute the range of line segments that surround a cell of the skeletal
|
||||||
@ -255,7 +256,7 @@ protected:
|
|||||||
* /return Whether the cell is inside of the polygon. If it's outside of the
|
* /return Whether the cell is inside of the polygon. If it's outside of the
|
||||||
* polygon we should skip processing it altogether.
|
* polygon we should skip processing it altogether.
|
||||||
*/
|
*/
|
||||||
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_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);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* 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
|
* 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
|
||||||
@ -597,6 +598,8 @@ protected:
|
|||||||
* Genrate small segments for local maxima where the beading would only result in a single bead
|
* Genrate small segments for local maxima where the beading would only result in a single bead
|
||||||
*/
|
*/
|
||||||
void generateLocalMaximaSingleBeads();
|
void generateLocalMaximaSingleBeads();
|
||||||
|
|
||||||
|
friend bool detect_voronoi_edge_intersecting_input_segment(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<VoronoiUtils::Segment> &segments);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::Arachne
|
} // namespace Slic3r::Arachne
|
||||||
|
Loading…
Reference in New Issue
Block a user