SPE-2298: Add detection of Voronoi diagram with parabolic edge without a focus point.

This commit is contained in:
Lukáš Hejl 2024-05-17 15:15:34 +02:00 committed by Lukas Matena
parent 4de0fdebda
commit c44ffed475
3 changed files with 84 additions and 7 deletions

View File

@ -35,6 +35,8 @@ VoronoiDiagram::construct_voronoi(const SegmentIterator segment_begin, const Seg
BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth."; BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth.";
} else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) {
BOOST_LOG_TRIVIAL(warning) << "Detected finite Voronoi vertex with non finite vertex, input polygons will be rotated back and forth."; BOOST_LOG_TRIVIAL(warning) << "Detected finite Voronoi vertex with non finite vertex, input polygons will be rotated back and forth.";
} else if (m_issue_type == IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT) {
BOOST_LOG_TRIVIAL(warning) << "Detected parabolic Voronoi edges without focus point, input polygons will be rotated back and forth.";
} else { } else {
BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue, input polygons will be rotated back and forth."; BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue, input polygons will be rotated back and forth.";
} }
@ -48,6 +50,8 @@ VoronoiDiagram::construct_voronoi(const SegmentIterator segment_begin, const Seg
BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input."; BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input.";
} else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) {
BOOST_LOG_TRIVIAL(error) << "Detected finite Voronoi vertex with non finite vertex even after the rotation of input."; BOOST_LOG_TRIVIAL(error) << "Detected finite Voronoi vertex with non finite vertex even after the rotation of input.";
} else if (m_issue_type == IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT) {
BOOST_LOG_TRIVIAL(error) << "Detected parabolic Voronoi edges without focus point even after the rotation of input.";
} else { } else {
BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue even after the rotation of input."; BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue even after the rotation of input.";
} }
@ -159,8 +163,8 @@ typename boost::polygon::enable_if<
VoronoiDiagram::IssueType>::type VoronoiDiagram::IssueType>::type
VoronoiDiagram::detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end) VoronoiDiagram::detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end)
{ {
if (has_finite_edge_with_non_finite_vertex(voronoi_diagram)) { if (const IssueType edge_issue_type = detect_known_voronoi_edge_issues(voronoi_diagram); edge_issue_type != IssueType::NO_ISSUE_DETECTED) {
return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX; return edge_issue_type;
} 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) { } 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) {
return cell_issue_type; return cell_issue_type;
} else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) { } else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) {
@ -218,16 +222,20 @@ VoronoiDiagram::detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_d
return IssueType::NO_ISSUE_DETECTED; return IssueType::NO_ISSUE_DETECTED;
} }
bool VoronoiDiagram::has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram) VoronoiDiagram::IssueType VoronoiDiagram::detect_known_voronoi_edge_issues(const VoronoiDiagram &voronoi_diagram)
{ {
for (const voronoi_diagram_type::edge_type &edge : voronoi_diagram.edges()) { for (const voronoi_diagram_type::edge_type &edge : voronoi_diagram.edges()) {
if (edge.is_finite()) { if (edge.is_finite()) {
assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr); assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr);
if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || !VoronoiUtils::is_finite(*edge.vertex1())) if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || !VoronoiUtils::is_finite(*edge.vertex1()))
return true; return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX;
if (edge.is_curved() && !edge.cell()->contains_point() && !edge.twin()->cell()->contains_point())
return IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT;
} }
} }
return false;
return IssueType::NO_ISSUE_DETECTED;
} }
template<typename SegmentIterator> template<typename SegmentIterator>

View File

@ -48,7 +48,8 @@ public:
MISSING_VORONOI_VERTEX, MISSING_VORONOI_VERTEX,
NON_PLANAR_VORONOI_DIAGRAM, NON_PLANAR_VORONOI_DIAGRAM,
VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT, VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT,
UNKNOWN // Repairs are disabled in the constructor. PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT,
UNKNOWN // Repairs are disabled in the constructor.
}; };
enum class State { enum class State {
@ -162,7 +163,10 @@ private:
IssueType>::type IssueType>::type
detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end); detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end);
static bool has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram); // Detect issues related to Voronoi edges, or that can be detected by iterating over Voronoi edges.
// The first type of issue that can be detected is a finite Voronoi edge with a non-finite vertex.
// The second type of issue that can be detected is a parabolic Voronoi edge without a focus point (produced by two segments).
static IssueType detect_known_voronoi_edge_issues(const VoronoiDiagram &voronoi_diagram);
voronoi_diagram_type m_voronoi_diagram; voronoi_diagram_type m_voronoi_diagram;
vertex_container_type m_vertices; vertex_container_type m_vertices;

View File

@ -2217,3 +2217,68 @@ TEST_CASE("Invalid Voronoi diagram - Thin lines - SPE-1729", "[InvalidVoronoiDia
// REQUIRE(vd.is_valid()); // REQUIRE(vd.is_valid());
} }
TEST_CASE("Voronoi cell doesn't contain a source point - SPE-2298", "[VoronoiCellSourcePointSPE2298]")
{
Polygon polygon = {
{ 9854534, -39739718}, {- 4154002, -34864557}, {-13073118, -31802214},
{-21265508, -29026626}, {-31388055, -25645073}, {-32409943, -25279942},
{-33418087, -24864987}, {-34400568, -24404312}, {-35354754, -23899358},
{-36278795, -23351325}, {-37170015, -22762146}, {-38025776, -22134628},
{-38845825, -21468175}, {-39627905, -20764801}, {-40370549, -20026061},
{-41072075, -19253859}, {-41731000, -18450032}, {-42345940, -17616466},
{-42915530, -16755283}, {-43438684, -15868338}, {-43914245, -14957822},
{-44341235, -14025879}, {-44718686, -13074712}, {-45045890, -12106566},
{-45322386, -11123499}, {-45547674, -10127656}, {-45721021, - 9121581},
{-45842174, - 8107658}, {-45910990, - 7088089}, {-45927405, - 6065217},
{-45891432, - 5041288}, {-45803222, - 4018728}, {-45663042, - 2999801},
{-45471245, - 1986784}, {-45230690, - 991761}, {-38655400, 23513180},
{-38366034, 24494742}, {-38025334, 25467666}, {-37636844, 26420074},
{-37200678, 27349843}, {-36718169, 28254419}, {-36191104, 29131704},
{-35620587, 29979748}, {-35007621, 30796895}, {-34353751, 31580950},
{-33660293, 32330182}, {-32928806, 33042775}, {-32160862, 33717057},
{-31358104, 34351432}, {-30522331, 34944323}, {-29655434, 35494277},
{-28759338, 35999922}, {-27835963, 36460011}, {-26921721, 36858494},
{-25914008, 37239556}, {-24919466, 37557049}, {-24204878, 37746930},
{-22880526, 38041931}, {-21833362, 38209050}, {-21449204, 38252031},
{-20775657, 38324377}, {-19711119, 38387480}, {-18638667, 38398812},
{-17762260, 38366962}, {-16480321, 38266321}, {-15396213, 38120856},
{-14327987, 37925343}, {- 5801522, 36175494}, { 7791637, 33457589},
{ 15887399, 31878986}, { 28428609, 29478881}, { 28438392, 29512722},
{ 27850323, 29743358}, { 27058729, 29970066}, { 14135560, 32452875},
{ 6101685, 34019760}, {- 5352362, 36305237}, {-14423391, 38160442},
{-15528705, 38361745}, {-16625379, 38507834}, {-17721787, 38600631},
{-18812787, 38641330}, {-19563804, 38633844}, {-20975692, 38563412},
{-22036069, 38446419}, {-23087710, 38277136}, {-24123993, 38056689},
{-25141240, 37786307}, {-26138324, 37466465}, {-26851801, 37197652},
{-28067514, 36680229}, {-28988984, 36219404}, {-29886302, 35711371},
{-30754551, 35158840}, {-31124518, 34896643}, {-31589528, 34564743},
{-32392776, 33928220}, {-33161225, 33251721}, {-33454722, 32966117},
{-33891684, 32538320}, {-34585318, 31787066}, {-35239508, 31000793},
{-35527715, 30616853}, {-35851756, 30182731}, {-36422833, 29331982},
{-36950377, 28452000}, {-37265788, 27860633}, {-37432874, 27545549},
{-37870512, 26612217}, {-38261423, 25655915}, {-38581885, 24744387},
{-38902507, 23671594}, {-45523689, - 1006672}, {-45770290, - 2026713},
{-45963584, - 3043930}, {-46104330, - 4066310}, {-46192377, - 5092635},
{-46228310, - 6120019}, {-46211987, - 7145807}, {-46143426, - 8167812},
{-46022719, - 9183674}, {-45850055, -10191399}, {-45625772, -11188531},
{-45350245, -12172975}, {-45023965, -13142600}, {-44647538, -14095222},
{-44221691, -15028602}, {-43747176, -15940794}, {-43224933, -16829570},
{-42655872, -17693052}, {-42041183, -18529065}, {-41381752, -19335983},
{-40677899, -20112975}, {-39932077, -20856972}, {-39145730, -21566171},
{-38320552, -22238686}, {-37458030, -22872953}, {-36560036, -23467217},
{-35627745, -24020614}, {-34662272, -24532977}, {-33667551, -25000722},
{-32645434, -25422669}, {-31588226, -25801077}, {-24380013, -28208306},
{-24380013, -28208306}, {-13354262, -31942517}, {-13354261, -31942515},
{-2032305, -35842454}, { 8025116, -39348505}, { 8820397, -39587703},
{ 9636283, -39751794}, { 9847092, -39773278}};
VD vd;
Lines lines = to_lines(polygon);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
// dump_voronoi_to_svg(debug_out_path("voronoi-cell-source-point-spe2298.svg").c_str(), vd, Points(), lines);
#endif
REQUIRE(vd.is_valid());
}