PrusaSlicer/tests/libslic3r/test_voronoi.cpp
Lukáš Hejl 8784ca0ecf SPE-1729: Try to compute the Voronoi diagram again on modified ExPolygon when an invalid Voronoi diagram is produced during the calculation of the medial axis.
There are several ExPolygons with very thin lines and holes formed by very close (1-5nm) vertices that are on the edge of our resolution. Those thin lines and holes are both unprintable and cause the Voronoi diagram to be invalid.
So, we filtered out such thin lines and holes and tried to compute the Voronoi diagram again.
2024-02-08 15:40:20 +01:00

2292 lines
96 KiB
C++

#include <catch2/catch.hpp>
#include <test_utils.hpp>
#include <libslic3r/Polygon.hpp>
#include <libslic3r/Polyline.hpp>
#include <libslic3r/EdgeGrid.hpp>
#include <libslic3r/Geometry.hpp>
#include "libslic3r/Geometry/VoronoiUtilsCgal.hpp"
#include <libslic3r/Geometry/VoronoiOffset.hpp>
#include <libslic3r/Geometry/VoronoiVisualUtils.hpp>
#include <numeric>
// #define VORONOI_DEBUG_OUT
#ifdef VORONOI_DEBUG_OUT
#include <libslic3r/VoronoiVisualUtils.hpp>
#endif
using boost::polygon::voronoi_builder;
using boost::polygon::voronoi_diagram;
using namespace Slic3r;
using VD = Geometry::VoronoiDiagram;
// https://svn.boost.org/trac10/ticket/12067
// This bug seems to be confirmed.
// Vojtech supposes that there may be no Voronoi edges produced for
// the 1st and last sweep line positions.
TEST_CASE("Voronoi missing edges - points 12067", "[Voronoi]")
{
Points pts {
{ -10, -20 },
{ 10, -20 },
{ 5, 0 },
{ 10, 20 },
{ -10, 20 },
{ -5, 0 }
};
#if 0
for (Point &p : pts) {
Vec2d q = p.cast<double>();
p.x() = scale_(p.x());
p.y() = scale_(p.y());
}
#endif
#if 0
// Try to rotate, maybe the issue is caused by incorrect handling of vertical or horizontal edges?
double a = 0.18764587962597876897475f;
double c = cos(a);
double s = sin(a);
for (Point &p : poly.points) {
Vec2d q = p.cast<double>();
p.x() = coord_t(q.x() * c + q.y() * s + 0.5);
p.y() = coord_t(- q.x() * s + q.y() * c + 0.5);
}
#endif
// Construction of the Voronoi Diagram.
VD vd;
vd.construct_voronoi(pts.begin(), pts.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-pts.svg").c_str(),
vd, pts, Lines());
#endif
// REQUIRE(closest_point.z() == Approx(1.));
}
// https://svn.boost.org/trac10/ticket/12707
// This issue is confirmed, there are no self intersections in the polygon.
// A minimal test case is created at the end of this test,
// a new issue opened with the minimal test case:
// https://github.com/boostorg/polygon/issues/43
TEST_CASE("Voronoi missing edges - Alessandro gapfill 12707", "[Voronoi]")
{
Lines lines0 {
{ { 42127548, 699996}, { 42127548, 10135750 } },
{ { 42127548, 10135750}, { 50487352, 10135750 } },
{ { 50487352, 10135750}, { 50487352, 699995 } },
{ { 50487352, 699995}, { 51187348, 0 } },
{ { 51187348, 0}, { 64325952, 0 } },
{ { 64325952, 0}, { 64325952, 699996 } },
{ { 64325952, 699996}, { 51187348, 699996 } },
{ { 51187348, 699996}, { 51187348, 10835701 } },
{ { 51187348, 10835701}, { 41427552, 10835701 } },
{ { 41427552, 10835701}, { 41427552, 699996 } },
{ { 41427552, 699996}, { 28664848, 699996 } },
{ { 28664848, 699996}, { 28664848, 10835701 } },
{ { 28664848, 10835701}, { 19280052, 10835701 } },
{ { 19280052, 10835701}, { 27964852, 699996 } },
{ { 27964852, 699996}, { 28664848, 0 } },
{ { 28664848, 0}, { 41427551, 0 } },
{ { 41427551, 0}, { 42127548, 699996 } }
};
Lines lines1 {
{ { 42127548, 699996}, { 42127548, 10135750 } },
{ { 42127548, 10135750}, { 50487352, 10135750 } },
{ { 50487352, 10135750}, { 50487352, 699995 } },
{ { 50487352, 699995}, { 51187348, 0 } },
{ { 51187348, 0}, { 51187348, 10835701 } },
{ { 51187348, 10835701}, { 41427552, 10835701 } },
{ { 41427552, 10835701}, { 41427552, 699996 } },
{ { 41427552, 699996}, { 28664848, 699996 } },
{ { 28664848, 699996}, { 28664848, 10835701 } },
{ { 28664848, 10835701}, { 19280052, 10835701 } },
{ { 19280052, 10835701}, { 27964852, 699996 } },
{ { 27964852, 699996}, { 28664848, 0 } },
{ { 28664848, 0}, { 41427551, 0 } },
{ { 41427551, 0}, { 42127548, 699996 } }
};
Lines lines2 {
{ { 42127548, 699996}, { 42127548, 10135750 } },
{ { 42127548, 10135750}, { 50487352, 10135750 } },
{ { 50487352, 10135750}, { 50487352, 699995 } },
{ { 50487352, 699995}, { 51187348, 0 } },
{ { 51187348, 0}, { 51187348, 10835701 } },
{ { 51187348, 10835701}, { 41427552, 10835701 } },
{ { 41427552, 10835701}, { 41427552, 699996 } },
{ { 41427552, 699996}, { 28664848, 699996 } },
{ { 28664848, 699996}, { 28664848, 10835701 } },
{ { 28664848, 10835701}, { 19280052, 10835701 } },
{ { 19280052, 10835701}, { 28664848, 0 } },
{ { 28664848, 0}, { 41427551, 0 } },
{ { 41427551, 0}, { 42127548, 699996 } }
};
Lines lines3 {
{ { 42127548, 699996}, { 42127548, 10135750 } },
{ { 42127548, 10135750}, { 50487352, 10135750 } },
{ { 50487352, 10135750}, { 50487352, 699995 } },
{ { 50487352, 699995}, { 51187348, 0 } },
{ { 51187348, 0}, { 51187348, 10835701 } },
{ { 51187348, 10835701}, { 41427552, 10835701 } },
{ { 41427552, 10835701}, { 41427552, 699996 } },
{ { 41427552, 699996}, { 41427551, 0 } },
{ { 41427551, 0}, { 42127548, 699996 } }
};
Lines lines4 {
{ { 42127548, 699996}, { 42127548, 10135750 } },
{ { 42127548, 10135750}, { 50487352, 10135750 } },
{ { 50487352, 10135750}, { 50487352, 699995 } },
{ { 50487352, 699995}, { 51187348, 0 } },
{ { 51187348, 0}, { 51187348, 10835701 } },
{ { 51187348, 10835701}, { 41427552, 10835701 } },
{ { 41427552, 10835701}, { 41427551, 0 } },
{ { 41427551, 0}, { 42127548, 699996 } }
};
Polygon poly {
{ 0, 10000000},
{ 700000, 1}, // it has to be 1, higher number, zero or -1 work.
{ 700000, 9000000},
{ 9100000, 9000000},
{ 9100000, 0},
{10000000, 10000000}
};
#if 1
// Try to rotate, maybe the issue is caused by incorrect handling of vertical or horizontal edges?
double a = 0.18764587962597876897475f;
double c = cos(a);
double s = sin(a);
for (Point &p : poly.points) {
Vec2d q = p.cast<double>();
p.x() = coord_t(q.x() * c + q.y() * s + 0.5);
p.y() = coord_t(- q.x() * s + q.y() * c + 0.5);
}
#endif
std::mt19937 gen;
std::uniform_int_distribution<coord_t> dist(-100, 100);
#if 0
for (Point &p : poly.points) {
// Wiggle the points a bit to find out whether this fixes the voronoi diagram for this particular polygon.
p.x() = (p.x() += dist(gen));
p.y() = (p.y() += dist(gen));
}
#endif
REQUIRE(intersecting_edges({ poly }).empty());
Lines lines = to_lines(poly);
VD vd;
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-lines.svg").c_str(),
vd, Points(), lines);
#endif
}
TEST_CASE("Voronoi weirdness", "[Voronoi]")
{
Polygon poly2 {
{ 0, 0 },
{ 70000000, 0 },
{ 70000000, 1300000 },
// { 70000001, 14000000 }
{ 70700000, 14000000 }
};
Polygon poly5 {
{ 35058884, -25732145 },
{ 35058884, -19586070 },
{ 32753739, -20246796 },
{ 28756244, -21010725 },
{ 24657532, -21657939 },
{ 20836260, -21960233 },
{ 16115145, -22070742 },
{ 11850152, -21839761 },
{ 7646240, -21470177 },
{ 3607605, -20786940 },
{ 1280947, -20329742 },
{ -292823, -19963790 },
{ -3844469, -18809741 },
{ -7237277, -17593723 },
{ -10225900, -16143761 },
{ -13030266, -14643721 },
{ -15404294, -12977561 },
{ -17601713, -11280712 },
{ -19241930, -9435607 },
{ -20714420, -7583739 },
{ -21726144, -5664355 },
{ -22579294, -3741947 },
{ -22966684, -1786321 },
{ -23200322, 170140 },
{ -22966684, 2126602 },
{ -22579296, 4082227 },
{ -21726148, 6004637 },
{ -20714424, 7924020 },
{ -19241932, 9775888 },
{ -17601717, 11620994 },
{ -15404423, 13317749 },
{ -13030276, 14984003 },
{ -10225910, 16484042 },
{ -7237288, 17934005 },
{ -3844482, 19150025 },
{ -292841, 20304074 },
{ 1280949, 20670031 },
{ 3607587, 21127226 },
{ 7646218, 21810465 },
{ 11850128, 22180055 },
{ 16115122, 22411036 },
{ 20836263, 22300531 },
{ 24657513, 21998239 },
{ 28756227, 21351025 },
{ 32753725, 20587092 },
{ 35058893, 19926309 },
{ 35058893, 35000000 },
{ -31657232, 35000000 },
{ -31657202, -35000000 },
{ 35058881, -35000000 }
};
Polygon poly7 {
{ 35058884, -25732145 },
{ 35058884, -19586070 },
{ -31657202, -35000000 },
{ 35058881, -35000000 }
};
// coord_t shift = 35058881;
// coord_t shift_ok = 17000000;
coord_t shift = 35058881;
Polygon poly {
// <-4, 0>: bug
// -5: ok
// 1 - ok
{ 0 + shift, -35000000 },
{ 0 + shift, -25732145 },
{ 0 + shift, -19586070 },
{ -66716086 + shift, -35000000 }
};
REQUIRE(intersecting_edges({ poly }).empty());
REQUIRE(poly.area() > 0.);
#if 0
// Try to rotate, maybe the issue is caused by incorrect handling of vertical or horizontal edges?
double a = 0.18764587962597876897475f;
double c = cos(a);
double s = sin(a);
for (Point &p : poly.points) {
Vec2d q = p.cast<double>();
p.x() = coord_t(q.x() * c + q.y() * s + 0.5);
p.y() = coord_t(- q.x() * s + q.y() * c + 0.5);
}
#endif
VD vd;
Lines lines = to_lines(poly);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-weirdness.svg").c_str(),
vd, Points(), lines);
#endif
}
// https://svn.boost.org/trac10/ticket/12903
// division by zero reported, but this issue is most likely a non-issue, as it produces an infinity for the interval of validity
// of the floating point calculation, therefore forcing a recalculation with extended accuracy.
TEST_CASE("Voronoi division by zero 12903", "[Voronoi]")
{
Points pts { { 1, 1 }, { 3, 1 }, { 1, 3 }, { 3, 3 },
{ -1, 1 }, { 1, -1 }, { 5, 1 }, { 3, -1 },
{ -1, 3 }, { 1, 5 }, { 5, 3 }, { 3, 5 } };
{
auto pts2 { pts };
std::sort(pts2.begin(), pts2.end(), [](auto &l, auto &r) { return (l.x() == r.x()) ? l.y() < r.y() : l.x() < r.x(); });
// No point removed -> no duplicate.
REQUIRE(std::unique(pts2.begin(), pts2.end()) == pts2.end());
}
VD 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.
for (auto &pt : vd.vertices()) {
const_cast<double&>(pt.x()) = scale_(pt.x());
const_cast<double&>(pt.y()) = scale_(pt.y());
}
for (auto &pt : pts)
pt = Point::new_scale(pt.x(), pt.y());
dump_voronoi_to_svg(debug_out_path("voronoi-div-by-zero.svg").c_str(), vd, pts, Lines());
#endif
}
// https://svn.boost.org/trac10/ticket/12139
// Funny sample from a dental industry?
// Vojtech confirms this test fails and rightly so, because the input data contain self intersections.
// This test is suppressed.
TEST_CASE("Voronoi NaN coordinates 12139", "[Voronoi][!hide][!mayfail]")
{
Lines lines = {
{ { 260500,1564400 }, { 261040,1562960 } },
{ { 261040,1562960 }, { 260840,1561780 } },
{ { 260840,1561780 }, { 262620,1561480 } },
{ { 262620,1561480 }, { 263160,1561220 } },
{ { 263160,1561220 }, { 264100,1563259 } },
{ { 264100,1563259 }, { 262380,1566980 } },
{ { 262380,1566980 }, { 260500,1564400 } },
{ { 137520,1851640 }, { 132160,1851100 } },
{ { 132160,1851100 }, { 126460,1848779 } },
{ { 126460,1848779 }, { 123960,1847320 } },
{ { 123960,1847320 }, { 120960,1844559 } },
{ { 120960,1844559 }, { 119640,1843040 } },
{ { 119640,1843040 }, { 118320,1840900 } },
{ { 118320,1840900 }, { 117920,1838120 } },
{ { 117920,1838120 }, { 118219,1833340 } },
{ { 118219,1833340 }, { 116180,1835000 } },
{ { 116180,1835000 }, { 115999,1834820 } },
{ { 115999,1834820 }, { 114240,1836340 } },
{ { 114240,1836340 }, { 112719,1837260 } },
{ { 112719,1837260 }, { 109460,1838239 } },
{ { 109460,1838239 }, { 103639,1837480 } },
{ { 103639,1837480 }, { 99819,1835460 } },
{ { 99819,1835460 }, { 96320,1834260 } },
{ { 96320,1834260 }, { 95339,1834260 } },
{ { 95339,1834260 }, { 93660,1833720 } },
{ { 93660,1833720 }, { 90719,1833300 } },
{ { 90719,1833300 }, { 87860,1831660 } },
{ { 87860,1831660 }, { 84580,1830499 } },
{ { 84580,1830499 }, { 79780,1827419 } },
{ { 79780,1827419 }, { 76020,1824280 } },
{ { 76020,1824280 }, { 73680,1821180 } },
{ { 73680,1821180 }, { 72560,1818960 } },
{ { 72560,1818960 }, { 71699,1817719 } },
{ { 71699,1817719 }, { 70280,1814260 } },
{ { 70280,1814260 }, { 69460,1811060 } },
{ { 69460,1811060 }, { 69659,1807320 } },
{ { 69659,1807320 }, { 69640,1803300 } },
{ { 69640,1803300 }, { 69360,1799780 } },
{ { 69360,1799780 }, { 69320,1796720 } },
{ { 69320,1796720 }, { 69640,1793980 } },
{ { 69640,1793980 }, { 70160,1791780 } },
{ { 70160,1791780 }, { 72460,1784879 } },
{ { 72460,1784879 }, { 74420,1780780 } },
{ { 74420,1780780 }, { 76500,1772899 } },
{ { 76500,1772899 }, { 76760,1769359 } },
{ { 76760,1769359 }, { 76480,1766259 } },
{ { 76480,1766259 }, { 76839,1760360 } },
{ { 76839,1760360 }, { 77539,1756680 } },
{ { 77539,1756680 }, { 80540,1748140 } },
{ { 80540,1748140 }, { 84200,1742619 } },
{ { 84200,1742619 }, { 90900,1735220 } },
{ { 90900,1735220 }, { 94159,1732679 } },
{ { 94159,1732679 }, { 101259,1729559 } },
{ { 101259,1729559 }, { 107299,1727939 } },
{ { 107299,1727939 }, { 110979,1727919 } },
{ { 110979,1727919 }, { 113499,1727240 } },
{ { 113499,1727240 }, { 113619,1727359 } },
{ { 113619,1727359 }, { 114280,1727280 } },
{ { 114280,1727280 }, { 131440,1732560 } },
{ { 131440,1732560 }, { 118140,1727119 } },
{ { 118140,1727119 }, { 117120,1723759 } },
{ { 117120,1723759 }, { 113840,1720660 } },
{ { 113840,1720660 }, { 111399,1716760 } },
{ { 111399,1716760 }, { 109700,1712979 } },
{ { 109700,1712979 }, { 108879,1708400 } },
{ { 108879,1708400 }, { 108060,1696360 } },
{ { 108060,1696360 }, { 110040,1687760 } },
{ { 110040,1687760 }, { 112140,1682480 } },
{ { 112140,1682480 }, { 112540,1681780 } },
{ { 112540,1681780 }, { 115260,1678320 } },
{ { 115260,1678320 }, { 118720,1675320 } },
{ { 118720,1675320 }, { 126100,1670980 } },
{ { 126100,1670980 }, { 132400,1668080 } },
{ { 132400,1668080 }, { 136700,1667440 } },
{ { 136700,1667440 }, { 142440,1667159 } },
{ { 142440,1667159 }, { 143340,1666720 } },
{ { 143340,1666720 }, { 138679,1661319 } },
{ { 138679,1661319 }, { 137240,1657480 } },
{ { 137240,1657480 }, { 136760,1650739 } },
{ { 136760,1650739 }, { 136780,1647339 } },
{ { 136780,1647339 }, { 135940,1644280 } },
{ { 135940,1644280 }, { 136000,1640820 } },
{ { 136000,1640820 }, { 135480,1638020 } },
{ { 135480,1638020 }, { 137060,1634220 } },
{ { 137060,1634220 }, { 136320,1631340 } },
{ { 136320,1631340 }, { 134620,1629700 } },
{ { 134620,1629700 }, { 132460,1628199 } },
{ { 132460,1628199 }, { 132299,1627860 } },
{ { 132299,1627860 }, { 138360,1618020 } },
{ { 138360,1618020 }, { 142440,1611859 } },
{ { 142440,1611859 }, { 143180,1611299 } },
{ { 143180,1611299 }, { 144000,1611259 } },
{ { 144000,1611259 }, { 145960,1612540 } },
{ { 145960,1612540 }, { 146720,1613700 } },
{ { 146720,1613700 }, { 147700,1613539 } },
{ { 147700,1613539 }, { 148520,1614039 } },
{ { 148520,1614039 }, { 149840,1613740 } },
{ { 149840,1613740 }, { 150620,1614079 } },
{ { 150620,1614079 }, { 154760,1612740 } },
{ { 154760,1612740 }, { 159000,1608420 } },
{ { 159000,1608420 }, { 161120,1606780 } },
{ { 161120,1606780 }, { 164060,1605139 } },
{ { 164060,1605139 }, { 168079,1603620 } },
{ { 168079,1603620 }, { 170240,1603400 } },
{ { 170240,1603400 }, { 172400,1603499 } },
{ { 172400,1603499 }, { 194440,1613740 } },
{ { 194440,1613740 }, { 195880,1616460 } },
{ { 195880,1616460 }, { 197060,1618140 } },
{ { 197060,1618140 }, { 198039,1617860 } },
{ { 198039,1617860 }, { 198739,1618900 } },
{ { 198739,1618900 }, { 200259,1619200 } },
{ { 200259,1619200 }, { 201940,1618920 } },
{ { 201940,1618920 }, { 201700,1617139 } },
{ { 201700,1617139 }, { 203860,1618179 } },
{ { 203860,1618179 }, { 203500,1617540 } },
{ { 203500,1617540 }, { 205000,1616579 } },
{ { 205000,1616579 }, { 206780,1615020 } },
{ { 206780,1615020 }, { 210159,1614059 } },
{ { 210159,1614059 }, { 217080,1611080 } },
{ { 217080,1611080 }, { 219200,1611579 } },
{ { 219200,1611579 }, { 223219,1610980 } },
{ { 223219,1610980 }, { 224580,1610540 } },
{ { 224580,1610540 }, { 227460,1611440 } },
{ { 227460,1611440 }, { 229359,1611859 } },
{ { 229359,1611859 }, { 230620,1612580 } },
{ { 230620,1612580 }, { 232340,1614460 } },
{ { 232340,1614460 }, { 232419,1617040 } },
{ { 232419,1617040 }, { 231740,1619480 } },
{ { 231740,1619480 }, { 231880,1624899 } },
{ { 231880,1624899 }, { 231540,1625820 } },
{ { 231540,1625820 }, { 231700,1627079 } },
{ { 231700,1627079 }, { 231320,1628239 } },
{ { 231320,1628239 }, { 231420,1636080 } },
{ { 231420,1636080 }, { 231099,1637200 } },
{ { 231099,1637200 }, { 228660,1643280 } },
{ { 228660,1643280 }, { 227699,1644960 } },
{ { 227699,1644960 }, { 226080,1651140 } },
{ { 226080,1651140 }, { 225259,1653420 } },
{ { 225259,1653420 }, { 225159,1655399 } },
{ { 225159,1655399 }, { 223760,1659260 } },
{ { 223760,1659260 }, { 219860,1666360 } },
{ { 219860,1666360 }, { 219180,1667220 } },
{ { 219180,1667220 }, { 212580,1673680 } },
{ { 212580,1673680 }, { 207880,1676460 } },
{ { 207880,1676460 }, { 205560,1677560 } },
{ { 205560,1677560 }, { 199700,1678920 } },
{ { 199700,1678920 }, { 195280,1679420 } },
{ { 195280,1679420 }, { 193939,1679879 } },
{ { 193939,1679879 }, { 188780,1679440 } },
{ { 188780,1679440 }, { 188100,1679639 } },
{ { 188100,1679639 }, { 186680,1679339 } },
{ { 186680,1679339 }, { 184760,1679619 } },
{ { 184760,1679619 }, { 183520,1681440 } },
{ { 183520,1681440 }, { 183860,1682200 } },
{ { 183860,1682200 }, { 186620,1686120 } },
{ { 186620,1686120 }, { 190380,1688380 } },
{ { 190380,1688380 }, { 192780,1690739 } },
{ { 192780,1690739 }, { 195860,1694839 } },
{ { 195860,1694839 }, { 196620,1696539 } },
{ { 196620,1696539 }, { 197540,1701819 } },
{ { 197540,1701819 }, { 198939,1705699 } },
{ { 198939,1705699 }, { 198979,1711819 } },
{ { 198979,1711819 }, { 198240,1716900 } },
{ { 198240,1716900 }, { 197440,1720139 } },
{ { 197440,1720139 }, { 195340,1724639 } },
{ { 195340,1724639 }, { 194040,1726140 } },
{ { 194040,1726140 }, { 192559,1728239 } },
{ { 192559,1728239 }, { 187780,1732339 } },
{ { 187780,1732339 }, { 182519,1735520 } },
{ { 182519,1735520 }, { 181239,1736140 } },
{ { 181239,1736140 }, { 177340,1737619 } },
{ { 177340,1737619 }, { 175439,1738140 } },
{ { 175439,1738140 }, { 171380,1738880 } },
{ { 171380,1738880 }, { 167860,1739059 } },
{ { 167860,1739059 }, { 166040,1738920 } },
{ { 166040,1738920 }, { 163680,1738539 } },
{ { 163680,1738539 }, { 157660,1736859 } },
{ { 157660,1736859 }, { 154900,1735460 } },
{ { 154900,1735460 }, { 151420,1735159 } },
{ { 151420,1735159 }, { 142100,1736160 } },
{ { 142100,1736160 }, { 140880,1735920 } },
{ { 140880,1735920 }, { 142820,1736859 } },
{ { 142820,1736859 }, { 144080,1737240 } },
{ { 144080,1737240 }, { 144280,1737460 } },
{ { 144280,1737460 }, { 144239,1738120 } },
{ { 144239,1738120 }, { 144980,1739420 } },
{ { 144980,1739420 }, { 146340,1741039 } },
{ { 146340,1741039 }, { 147160,1741720 } },
{ { 147160,1741720 }, { 154260,1745800 } },
{ { 154260,1745800 }, { 156560,1746879 } },
{ { 156560,1746879 }, { 165180,1752679 } },
{ { 165180,1752679 }, { 168240,1755860 } },
{ { 168240,1755860 }, { 170940,1759260 } },
{ { 170940,1759260 }, { 173440,1762079 } },
{ { 173440,1762079 }, { 174540,1764079 } },
{ { 174540,1764079 }, { 176479,1766640 } },
{ { 176479,1766640 }, { 178900,1768960 } },
{ { 178900,1768960 }, { 180819,1772780 } },
{ { 180819,1772780 }, { 181479,1776859 } },
{ { 181479,1776859 }, { 181660,1788499 } },
{ { 181660,1788499 }, { 181460,1791740 } },
{ { 181460,1791740 }, { 181160,1792840 } },
{ { 181160,1792840 }, { 179580,1797180 } },
{ { 179580,1797180 }, { 174620,1808960 } },
{ { 174620,1808960 }, { 174100,1809839 } },
{ { 174100,1809839 }, { 171660,1812419 } },
{ { 171660,1812419 }, { 169639,1813840 } },
{ { 169639,1813840 }, { 168880,1814720 } },
{ { 168880,1814720 }, { 168960,1815980 } },
{ { 168960,1815980 }, { 169979,1819160 } },
{ { 169979,1819160 }, { 170080,1820159 } },
{ { 170080,1820159 }, { 168280,1830540 } },
{ { 168280,1830540 }, { 167580,1832200 } },
{ { 167580,1832200 }, { 165679,1835720 } },
{ { 165679,1835720 }, { 164720,1836819 } },
{ { 164720,1836819 }, { 161840,1841740 } },
{ { 161840,1841740 }, { 159880,1843519 } },
{ { 159880,1843519 }, { 158959,1844120 } },
{ { 158959,1844120 }, { 154960,1847500 } },
{ { 154960,1847500 }, { 152140,1848580 } },
{ { 152140,1848580 }, { 150440,1849520 } },
{ { 150440,1849520 }, { 144940,1850980 } },
{ { 144940,1850980 }, { 138340,1851700 } },
{ { 138340,1851700 }, { 137520,1851640 } },
{ { 606940,1873860 }, { 602860,1872460 } },
{ { 602860,1872460 }, { 600680,1871539 } },
{ { 600680,1871539 }, { 599300,1870640 } },
{ { 599300,1870640 }, { 598120,1869579 } },
{ { 598120,1869579 }, { 594680,1867180 } },
{ { 594680,1867180 }, { 589680,1861460 } },
{ { 589680,1861460 }, { 586300,1855020 } },
{ { 586300,1855020 }, { 584700,1848060 } },
{ { 584700,1848060 }, { 585199,1843499 } },
{ { 585199,1843499 }, { 584000,1842079 } },
{ { 584000,1842079 }, { 582900,1841480 } },
{ { 582900,1841480 }, { 581020,1839899 } },
{ { 581020,1839899 }, { 579440,1838040 } },
{ { 579440,1838040 }, { 577840,1834299 } },
{ { 577840,1834299 }, { 576160,1831859 } },
{ { 576160,1831859 }, { 574540,1828499 } },
{ { 574540,1828499 }, { 572140,1822860 } },
{ { 572140,1822860 }, { 570180,1815219 } },
{ { 570180,1815219 }, { 570080,1812280 } },
{ { 570080,1812280 }, { 570340,1808300 } },
{ { 570340,1808300 }, { 570160,1807119 } },
{ { 570160,1807119 }, { 570140,1804039 } },
{ { 570140,1804039 }, { 571640,1796660 } },
{ { 571640,1796660 }, { 571740,1794680 } },
{ { 571740,1794680 }, { 572279,1794039 } },
{ { 572279,1794039 }, { 575480,1788300 } },
{ { 575480,1788300 }, { 576379,1787419 } },
{ { 576379,1787419 }, { 577020,1786120 } },
{ { 577020,1786120 }, { 578000,1785100 } },
{ { 578000,1785100 }, { 579960,1783720 } },
{ { 579960,1783720 }, { 581420,1782079 } },
{ { 581420,1782079 }, { 585480,1778440 } },
{ { 585480,1778440 }, { 586680,1777079 } },
{ { 586680,1777079 }, { 590520,1774639 } },
{ { 590520,1774639 }, { 592440,1773199 } },
{ { 592440,1773199 }, { 595160,1772260 } },
{ { 595160,1772260 }, { 598079,1770920 } },
{ { 598079,1770920 }, { 601420,1769019 } },
{ { 601420,1769019 }, { 606400,1767280 } },
{ { 606400,1767280 }, { 607320,1766620 } },
{ { 607320,1766620 }, { 605760,1766460 } },
{ { 605760,1766460 }, { 604420,1766780 } },
{ { 604420,1766780 }, { 601660,1766579 } },
{ { 601660,1766579 }, { 597160,1766980 } },
{ { 597160,1766980 }, { 591420,1766720 } },
{ { 591420,1766720 }, { 585360,1765460 } },
{ { 585360,1765460 }, { 578540,1763680 } },
{ { 578540,1763680 }, { 574020,1761599 } },
{ { 574020,1761599 }, { 572520,1760560 } },
{ { 572520,1760560 }, { 570959,1759000 } },
{ { 570959,1759000 }, { 566580,1755620 } },
{ { 566580,1755620 }, { 563820,1752000 } },
{ { 563820,1752000 }, { 563140,1751380 } },
{ { 563140,1751380 }, { 560800,1747899 } },
{ { 560800,1747899 }, { 558640,1742280 } },
{ { 558640,1742280 }, { 557860,1741620 } },
{ { 557860,1741620 }, { 555820,1739099 } },
{ { 555820,1739099 }, { 553920,1737540 } },
{ { 553920,1737540 }, { 551900,1735179 } },
{ { 551900,1735179 }, { 551180,1733880 } },
{ { 551180,1733880 }, { 549540,1729559 } },
{ { 549540,1729559 }, { 548860,1720720 } },
{ { 548860,1720720 }, { 549080,1719099 } },
{ { 549080,1719099 }, { 548200,1714700 } },
{ { 548200,1714700 }, { 547560,1713860 } },
{ { 547560,1713860 }, { 544500,1711259 } },
{ { 544500,1711259 }, { 543939,1709780 } },
{ { 543939,1709780 }, { 544520,1705439 } },
{ { 544520,1705439 }, { 543520,1701519 } },
{ { 543520,1701519 }, { 543920,1699319 } },
{ { 543920,1699319 }, { 546360,1697440 } },
{ { 546360,1697440 }, { 546680,1695419 } },
{ { 546680,1695419 }, { 545600,1694180 } },
{ { 545600,1694180 }, { 543220,1692000 } },
{ { 543220,1692000 }, { 538260,1685139 } },
{ { 538260,1685139 }, { 537540,1683000 } },
{ { 537540,1683000 }, { 537020,1682220 } },
{ { 537020,1682220 }, { 535560,1675940 } },
{ { 535560,1675940 }, { 535940,1671220 } },
{ { 535940,1671220 }, { 536320,1669379 } },
{ { 536320,1669379 }, { 535420,1666400 } },
{ { 535420,1666400 }, { 533540,1664460 } },
{ { 533540,1664460 }, { 530720,1662860 } },
{ { 530720,1662860 }, { 529240,1662260 } },
{ { 529240,1662260 }, { 528780,1659160 } },
{ { 528780,1659160 }, { 528820,1653560 } },
{ { 528820,1653560 }, { 529779,1650900 } },
{ { 529779,1650900 }, { 536760,1640840 } },
{ { 536760,1640840 }, { 540360,1636120 } },
{ { 540360,1636120 }, { 541160,1635380 } },
{ { 541160,1635380 }, { 544719,1629480 } },
{ { 544719,1629480 }, { 545319,1626140 } },
{ { 545319,1626140 }, { 543560,1623740 } },
{ { 543560,1623740 }, { 539880,1620739 } },
{ { 539880,1620739 }, { 533400,1617300 } },
{ { 533400,1617300 }, { 527840,1613020 } },
{ { 527840,1613020 }, { 525200,1611579 } },
{ { 525200,1611579 }, { 524360,1610800 } },
{ { 524360,1610800 }, { 517320,1605739 } },
{ { 517320,1605739 }, { 516240,1604240 } },
{ { 516240,1604240 }, { 515220,1602000 } },
{ { 515220,1602000 }, { 514079,1594240 } },
{ { 514079,1594240 }, { 513740,1581460 } },
{ { 513740,1581460 }, { 514660,1577359 } },
{ { 514660,1577359 }, { 514660,1576380 } },
{ { 514660,1576380 }, { 514199,1575380 } },
{ { 514199,1575380 }, { 514680,1572860 } },
{ { 514680,1572860 }, { 513440,1573940 } },
{ { 513440,1573940 }, { 512399,1575580 } },
{ { 512399,1575580 }, { 511620,1576220 } },
{ { 511620,1576220 }, { 507840,1581880 } },
{ { 507840,1581880 }, { 504600,1584579 } },
{ { 504600,1584579 }, { 502440,1584599 } },
{ { 502440,1584599 }, { 499060,1584059 } },
{ { 499060,1584059 }, { 498019,1581960 } },
{ { 498019,1581960 }, { 497819,1581240 } },
{ { 497819,1581240 }, { 498019,1576039 } },
{ { 498019,1576039 }, { 497539,1574740 } },
{ { 497539,1574740 }, { 495459,1574460 } },
{ { 495459,1574460 }, { 492320,1575600 } },
{ { 492320,1575600 }, { 491040,1576360 } },
{ { 491040,1576360 }, { 490080,1575640 } },
{ { 490080,1575640 }, { 490020,1575040 } },
{ { 490020,1575040 }, { 490220,1574400 } },
{ { 490220,1574400 }, { 490819,1573440 } },
{ { 490819,1573440 }, { 492680,1568259 } },
{ { 492680,1568259 }, { 492920,1566799 } },
{ { 492920,1566799 }, { 495760,1563660 } },
{ { 495760,1563660 }, { 496100,1562139 } },
{ { 496100,1562139 }, { 497879,1560240 } },
{ { 497879,1560240 }, { 497059,1558020 } },
{ { 497059,1558020 }, { 495620,1557399 } },
{ { 495620,1557399 }, { 494800,1556839 } },
{ { 494800,1556839 }, { 493500,1555479 } },
{ { 493500,1555479 }, { 491860,1554100 } },
{ { 491860,1554100 }, { 487840,1552139 } },
{ { 487840,1552139 }, { 485900,1551720 } },
{ { 485900,1551720 }, { 483639,1555439 } },
{ { 483639,1555439 }, { 482080,1556480 } },
{ { 482080,1556480 }, { 480200,1556259 } },
{ { 480200,1556259 }, { 478519,1556259 } },
{ { 478519,1556259 }, { 474020,1554019 } },
{ { 474020,1554019 }, { 472660,1551539 } },
{ { 472660,1551539 }, { 471260,1549899 } },
{ { 471260,1549899 }, { 470459,1548020 } },
{ { 470459,1548020 }, { 469920,1545479 } },
{ { 469920,1545479 }, { 469079,1542939 } },
{ { 469079,1542939 }, { 469120,1541799 } },
{ { 469120,1541799 }, { 465840,1537139 } },
{ { 465840,1537139 }, { 463360,1539059 } },
{ { 463360,1539059 }, { 459680,1546900 } },
{ { 459680,1546900 }, { 458439,1547160 } },
{ { 458439,1547160 }, { 456480,1549319 } },
{ { 456480,1549319 }, { 454160,1551400 } },
{ { 454160,1551400 }, { 452819,1550820 } },
{ { 452819,1550820 }, { 451699,1549839 } },
{ { 451699,1549839 }, { 449620,1548440 } },
{ { 449620,1548440 }, { 449419,1548080 } },
{ { 449419,1548080 }, { 447879,1547720 } },
{ { 447879,1547720 }, { 446540,1546819 } },
{ { 446540,1546819 }, { 445720,1545640 } },
{ { 445720,1545640 }, { 444800,1545100 } },
{ { 444800,1545100 }, { 443500,1542899 } },
{ { 443500,1542899 }, { 443320,1541799 } },
{ { 443320,1541799 }, { 443519,1540220 } },
{ { 443519,1540220 }, { 445060,1537099 } },
{ { 445060,1537099 }, { 445840,1533040 } },
{ { 445840,1533040 }, { 442720,1529079 } },
{ { 442720,1529079 }, { 442479,1528360 } },
{ { 442479,1528360 }, { 436820,1529240 } },
{ { 436820,1529240 }, { 436279,1529200 } },
{ { 436279,1529200 }, { 433280,1529859 } },
{ { 433280,1529859 }, { 420220,1529899 } },
{ { 420220,1529899 }, { 414740,1528539 } },
{ { 414740,1528539 }, { 411340,1527960 } },
{ { 411340,1527960 }, { 406860,1524660 } },
{ { 406860,1524660 }, { 405379,1523080 } },
{ { 405379,1523080 }, { 403639,1520320 } },
{ { 403639,1520320 }, { 402040,1517220 } },
{ { 402040,1517220 }, { 400519,1517059 } },
{ { 400519,1517059 }, { 399180,1516720 } },
{ { 399180,1516720 }, { 395300,1515179 } },
{ { 395300,1515179 }, { 394780,1515080 } },
{ { 394780,1515080 }, { 394759,1515900 } },
{ { 394759,1515900 }, { 394339,1516579 } },
{ { 394339,1516579 }, { 393200,1516640 } },
{ { 393200,1516640 }, { 392599,1521799 } },
{ { 392599,1521799 }, { 391699,1525200 } },
{ { 391699,1525200 }, { 391040,1525600 } },
{ { 391040,1525600 }, { 390540,1526500 } },
{ { 390540,1526500 }, { 388999,1527939 } },
{ { 388999,1527939 }, { 387059,1531100 } },
{ { 387059,1531100 }, { 386540,1531440 } },
{ { 386540,1531440 }, { 382140,1531839 } },
{ { 382140,1531839 }, { 377360,1532619 } },
{ { 377360,1532619 }, { 375640,1532220 } },
{ { 375640,1532220 }, { 372580,1531019 } },
{ { 372580,1531019 }, { 371079,1529019 } },
{ { 371079,1529019 }, { 367280,1526039 } },
{ { 367280,1526039 }, { 366460,1521900 } },
{ { 366460,1521900 }, { 364320,1516400 } },
{ { 364320,1516400 }, { 363779,1515780 } },
{ { 363779,1515780 }, { 362220,1515320 } },
{ { 362220,1515320 }, { 361979,1515060 } },
{ { 361979,1515060 }, { 360820,1515739 } },
{ { 360820,1515739 }, { 353360,1518620 } },
{ { 353360,1518620 }, { 347840,1520080 } },
{ { 347840,1520080 }, { 342399,1521140 } },
{ { 342399,1521140 }, { 334899,1523380 } },
{ { 334899,1523380 }, { 333220,1523400 } },
{ { 333220,1523400 }, { 332599,1522919 } },
{ { 332599,1522919 }, { 329780,1521640 } },
{ { 329780,1521640 }, { 325360,1521220 } },
{ { 325360,1521220 }, { 319000,1520999 } },
{ { 319000,1520999 }, { 316180,1520240 } },
{ { 316180,1520240 }, { 312700,1518960 } },
{ { 312700,1518960 }, { 310520,1517679 } },
{ { 310520,1517679 }, { 309280,1517260 } },
{ { 309280,1517260 }, { 306440,1515040 } },
{ { 306440,1515040 }, { 304140,1512780 } },
{ { 304140,1512780 }, { 301640,1509720 } },
{ { 301640,1509720 }, { 301500,1509879 } },
{ { 301500,1509879 }, { 300320,1509059 } },
{ { 300320,1509059 }, { 299140,1507339 } },
{ { 299140,1507339 }, { 297340,1502659 } },
{ { 297340,1502659 }, { 298960,1508280 } },
{ { 298960,1508280 }, { 299120,1509299 } },
{ { 299120,1509299 }, { 298720,1510100 } },
{ { 298720,1510100 }, { 298420,1512240 } },
{ { 298420,1512240 }, { 297420,1514540 } },
{ { 297420,1514540 }, { 296900,1515340 } },
{ { 296900,1515340 }, { 294780,1517500 } },
{ { 294780,1517500 }, { 293040,1518380 } },
{ { 293040,1518380 }, { 289140,1521360 } },
{ { 289140,1521360 }, { 283600,1523300 } },
{ { 283600,1523300 }, { 280140,1525220 } },
{ { 280140,1525220 }, { 279620,1525679 } },
{ { 279620,1525679 }, { 274960,1527379 } },
{ { 274960,1527379 }, { 273440,1528819 } },
{ { 273440,1528819 }, { 269840,1532840 } },
{ { 269840,1532840 }, { 264800,1536240 } },
{ { 264800,1536240 }, { 261199,1540419 } },
{ { 261199,1540419 }, { 257359,1541400 } },
{ { 257359,1541400 }, { 250460,1539299 } },
{ { 250460,1539299 }, { 250240,1539400 } },
{ { 250240,1539400 }, { 249840,1540460 } },
{ { 249840,1540460 }, { 249779,1541140 } },
{ { 249779,1541140 }, { 248482,1539783 } },
{ { 248482,1539783 }, { 251320,1544120 } },
{ { 251320,1544120 }, { 252500,1548320 } },
{ { 252500,1548320 }, { 252519,1549740 } },
{ { 252519,1549740 }, { 253000,1553140 } },
{ { 253000,1553140 }, { 252920,1556539 } },
{ { 252920,1556539 }, { 253160,1556700 } },
{ { 253160,1556700 }, { 254019,1558220 } },
{ { 254019,1558220 }, { 253039,1559339 } },
{ { 253039,1559339 }, { 252300,1561920 } },
{ { 252300,1561920 }, { 251080,1565260 } },
{ { 251080,1565260 }, { 251120,1566160 } },
{ { 251120,1566160 }, { 249979,1570240 } },
{ { 249979,1570240 }, { 248799,1575380 } },
{ { 248799,1575380 }, { 247180,1579520 } },
{ { 247180,1579520 }, { 243380,1588440 } },
{ { 243380,1588440 }, { 241700,1591780 } },
{ { 241700,1591780 }, { 240280,1593080 } },
{ { 240280,1593080 }, { 231859,1598380 } },
{ { 231859,1598380 }, { 228840,1600060 } },
{ { 228840,1600060 }, { 226420,1601080 } },
{ { 226420,1601080 }, { 223620,1601940 } },
{ { 223620,1601940 }, { 220919,1603819 } },
{ { 220919,1603819 }, { 219599,1604420 } },
{ { 219599,1604420 }, { 218380,1605200 } },
{ { 218380,1605200 }, { 213219,1607260 } },
{ { 213219,1607260 }, { 210040,1607740 } },
{ { 210040,1607740 }, { 186439,1596440 } },
{ { 186439,1596440 }, { 185159,1594559 } },
{ { 185159,1594559 }, { 182239,1588300 } },
{ { 182239,1588300 }, { 181040,1585380 } },
{ { 181040,1585380 }, { 180380,1578580 } },
{ { 180380,1578580 }, { 180679,1573220 } },
{ { 180679,1573220 }, { 181220,1568539 } },
{ { 181220,1568539 }, { 181859,1565020 } },
{ { 181859,1565020 }, { 184499,1555500 } },
{ { 184499,1555500 }, { 183480,1558160 } },
{ { 183480,1558160 }, { 182600,1561700 } },
{ { 182600,1561700 }, { 171700,1554359 } },
{ { 171700,1554359 }, { 176880,1545920 } },
{ { 176880,1545920 }, { 189940,1529000 } },
{ { 189940,1529000 }, { 200040,1535759 } },
{ { 200040,1535759 }, { 207559,1531660 } },
{ { 207559,1531660 }, { 218039,1527520 } },
{ { 218039,1527520 }, { 222360,1526640 } },
{ { 222360,1526640 }, { 225439,1526440 } },
{ { 225439,1526440 }, { 231160,1527079 } },
{ { 231160,1527079 }, { 232300,1527399 } },
{ { 232300,1527399 }, { 236579,1529140 } },
{ { 236579,1529140 }, { 238139,1529120 } },
{ { 238139,1529120 }, { 238799,1529319 } },
{ { 238799,1529319 }, { 240999,1531780 } },
{ { 240999,1531780 }, { 238280,1528799 } },
{ { 238280,1528799 }, { 236900,1523840 } },
{ { 236900,1523840 }, { 236800,1522700 } },
{ { 236800,1522700 }, { 235919,1518880 } },
{ { 235919,1518880 }, { 236080,1514299 } },
{ { 236080,1514299 }, { 238260,1508380 } },
{ { 238260,1508380 }, { 240119,1505159 } },
{ { 240119,1505159 }, { 233319,1496360 } },
{ { 233319,1496360 }, { 239140,1490759 } },
{ { 239140,1490759 }, { 258760,1478080 } },
{ { 258760,1478080 }, { 263940,1484760 } },
{ { 263940,1484760 }, { 263460,1485159 } },
{ { 263460,1485159 }, { 265960,1483519 } },
{ { 265960,1483519 }, { 270380,1482020 } },
{ { 270380,1482020 }, { 272880,1481420 } },
{ { 272880,1481420 }, { 275700,1481400 } },
{ { 275700,1481400 }, { 278380,1481740 } },
{ { 278380,1481740 }, { 281220,1482979 } },
{ { 281220,1482979 }, { 284680,1484859 } },
{ { 284680,1484859 }, { 285979,1486140 } },
{ { 285979,1486140 }, { 290220,1489100 } },
{ { 290220,1489100 }, { 292680,1489520 } },
{ { 292680,1489520 }, { 293280,1490240 } },
{ { 293280,1490240 }, { 293140,1489160 } },
{ { 293140,1489160 }, { 293280,1488580 } },
{ { 293280,1488580 }, { 294100,1486980 } },
{ { 294100,1486980 }, { 294580,1484960 } },
{ { 294580,1484960 }, { 295680,1481660 } },
{ { 295680,1481660 }, { 297840,1477339 } },
{ { 297840,1477339 }, { 302240,1472280 } },
{ { 302240,1472280 }, { 307120,1469000 } },
{ { 307120,1469000 }, { 314500,1466340 } },
{ { 314500,1466340 }, { 324979,1464740 } },
{ { 324979,1464740 }, { 338999,1462059 } },
{ { 338999,1462059 }, { 345599,1461579 } },
{ { 345599,1461579 }, { 349020,1461620 } },
{ { 349020,1461620 }, { 353420,1461160 } },
{ { 353420,1461160 }, { 357000,1461500 } },
{ { 357000,1461500 }, { 359860,1461579 } },
{ { 359860,1461579 }, { 364520,1462740 } },
{ { 364520,1462740 }, { 367280,1464000 } },
{ { 367280,1464000 }, { 372020,1467560 } },
{ { 372020,1467560 }, { 373999,1469980 } },
{ { 373999,1469980 }, { 375580,1472240 } },
{ { 375580,1472240 }, { 376680,1474460 } },
{ { 376680,1474460 }, { 377259,1478620 } },
{ { 377259,1478620 }, { 379279,1480880 } },
{ { 379279,1480880 }, { 379260,1481600 } },
{ { 379260,1481600 }, { 378760,1482000 } },
{ { 378760,1482000 }, { 379300,1482040 } },
{ { 379300,1482040 }, { 380220,1482460 } },
{ { 380220,1482460 }, { 380840,1483020 } },
{ { 380840,1483020 }, { 385519,1482600 } },
{ { 385519,1482600 }, { 386019,1482320 } },
{ { 386019,1482320 }, { 386499,1481600 } },
{ { 386499,1481600 }, { 386540,1480139 } },
{ { 386540,1480139 }, { 387500,1478220 } },
{ { 387500,1478220 }, { 388280,1476100 } },
{ { 388280,1476100 }, { 390060,1473000 } },
{ { 390060,1473000 }, { 393659,1469460 } },
{ { 393659,1469460 }, { 396540,1467860 } },
{ { 396540,1467860 }, { 401260,1466040 } },
{ { 401260,1466040 }, { 406200,1465100 } },
{ { 406200,1465100 }, { 410920,1465439 } },
{ { 410920,1465439 }, { 420659,1467399 } },
{ { 420659,1467399 }, { 433500,1471480 } },
{ { 433500,1471480 }, { 441340,1473540 } },
{ { 441340,1473540 }, { 448620,1475139 } },
{ { 448620,1475139 }, { 450720,1475880 } },
{ { 450720,1475880 }, { 453299,1477059 } },
{ { 453299,1477059 }, { 456620,1478940 } },
{ { 456620,1478940 }, { 458480,1480399 } },
{ { 458480,1480399 }, { 461100,1482780 } },
{ { 461100,1482780 }, { 463820,1486519 } },
{ { 463820,1486519 }, { 464780,1488199 } },
{ { 464780,1488199 }, { 466579,1493960 } },
{ { 466579,1493960 }, { 467120,1497700 } },
{ { 467120,1497700 }, { 466999,1500280 } },
{ { 466999,1500280 }, { 467300,1502580 } },
{ { 467300,1502580 }, { 467399,1505280 } },
{ { 467399,1505280 }, { 466979,1506920 } },
{ { 466979,1506920 }, { 467920,1504780 } },
{ { 467920,1504780 }, { 468159,1505040 } },
{ { 468159,1505040 }, { 469400,1504859 } },
{ { 469400,1504859 }, { 470300,1505540 } },
{ { 470300,1505540 }, { 471240,1505200 } },
{ { 471240,1505200 }, { 471579,1504280 } },
{ { 471579,1504280 }, { 473939,1502379 } },
{ { 473939,1502379 }, { 476860,1500200 } },
{ { 476860,1500200 }, { 479800,1498620 } },
{ { 479800,1498620 }, { 480840,1498120 } },
{ { 480840,1498120 }, { 485220,1497480 } },
{ { 485220,1497480 }, { 489979,1497460 } },
{ { 489979,1497460 }, { 494899,1498700 } },
{ { 494899,1498700 }, { 500099,1501320 } },
{ { 500099,1501320 }, { 501439,1501839 } },
{ { 501439,1501839 }, { 503400,1502939 } },
{ { 503400,1502939 }, { 510760,1508340 } },
{ { 510760,1508340 }, { 513640,1510920 } },
{ { 513640,1510920 }, { 518579,1514599 } },
{ { 518579,1514599 }, { 519020,1515260 } },
{ { 519020,1515260 }, { 520700,1516480 } },
{ { 520700,1516480 }, { 524960,1521480 } },
{ { 524960,1521480 }, { 526820,1524820 } },
{ { 526820,1524820 }, { 528280,1527820 } },
{ { 528280,1527820 }, { 529120,1533120 } },
{ { 529120,1533120 }, { 528820,1537139 } },
{ { 528820,1537139 }, { 527020,1543920 } },
{ { 527020,1543920 }, { 526959,1546780 } },
{ { 526959,1546780 }, { 526420,1548060 } },
{ { 526420,1548060 }, { 527020,1547919 } },
{ { 527020,1547919 }, { 527620,1548160 } },
{ { 527620,1548160 }, { 528980,1548020 } },
{ { 528980,1548020 }, { 535180,1544980 } },
{ { 535180,1544980 }, { 540860,1542979 } },
{ { 540860,1542979 }, { 546480,1542720 } },
{ { 546480,1542720 }, { 547420,1542860 } },
{ { 547420,1542860 }, { 551800,1544140 } },
{ { 551800,1544140 }, { 558740,1547939 } },
{ { 558740,1547939 }, { 569920,1556259 } },
{ { 569920,1556259 }, { 573660,1560220 } },
{ { 573660,1560220 }, { 573040,1559500 } },
{ { 573040,1559500 }, { 574740,1559220 } },
{ { 574740,1559220 }, { 588480,1562899 } },
{ { 588480,1562899 }, { 585180,1576019 } },
{ { 585180,1576019 }, { 583440,1577979 } },
{ { 583440,1577979 }, { 584280,1582399 } },
{ { 584280,1582399 }, { 584520,1588960 } },
{ { 584520,1588960 }, { 583420,1601620 } },
{ { 583420,1601620 }, { 582840,1603880 } },
{ { 582840,1603880 }, { 579860,1611400 } },
{ { 579860,1611400 }, { 577980,1614579 } },
{ { 577980,1614579 }, { 577380,1616080 } },
{ { 577380,1616080 }, { 563800,1621579 } },
{ { 563800,1621579 }, { 561320,1622320 } },
{ { 561320,1622320 }, { 565080,1621960 } },
{ { 565080,1621960 }, { 571680,1620780 } },
{ { 571680,1620780 }, { 583260,1628340 } },
{ { 583260,1628340 }, { 583100,1630399 } },
{ { 583100,1630399 }, { 582200,1632160 } },
{ { 582200,1632160 }, { 595380,1627020 } },
{ { 595380,1627020 }, { 597400,1627320 } },
{ { 597400,1627320 }, { 602240,1628459 } },
{ { 602240,1628459 }, { 605660,1630260 } },
{ { 605660,1630260 }, { 610319,1634140 } },
{ { 610319,1634140 }, { 612340,1636319 } },
{ { 612340,1636319 }, { 614820,1638020 } },
{ { 614820,1638020 }, { 616460,1638740 } },
{ { 616460,1638740 }, { 620420,1639500 } },
{ { 620420,1639500 }, { 623000,1639280 } },
{ { 623000,1639280 }, { 624459,1639359 } },
{ { 624459,1639359 }, { 626180,1640159 } },
{ { 626180,1640159 }, { 627279,1640940 } },
{ { 627279,1640940 }, { 629980,1643759 } },
{ { 629980,1643759 }, { 632380,1648000 } },
{ { 632380,1648000 }, { 635020,1654800 } },
{ { 635020,1654800 }, { 636320,1659140 } },
{ { 636320,1659140 }, { 636680,1663620 } },
{ { 636680,1663620 }, { 636180,1665780 } },
{ { 636180,1665780 }, { 630620,1669720 } },
{ { 630620,1669720 }, { 628760,1672979 } },
{ { 628760,1672979 }, { 627540,1676859 } },
{ { 627540,1676859 }, { 627040,1680699 } },
{ { 627040,1680699 }, { 624700,1686500 } },
{ { 624700,1686500 }, { 623260,1688799 } },
{ { 623260,1688799 }, { 619620,1693799 } },
{ { 619620,1693799 }, { 621720,1694859 } },
{ { 621720,1694859 }, { 624940,1694379 } },
{ { 624940,1694379 }, { 627120,1695600 } },
{ { 627120,1695600 }, { 627740,1696120 } },
{ { 627740,1696120 }, { 631120,1697460 } },
{ { 631120,1697460 }, { 633980,1698340 } },
{ { 633980,1698340 }, { 638380,1700460 } },
{ { 638380,1700460 }, { 642660,1703300 } },
{ { 642660,1703300 }, { 643620,1704140 } },
{ { 643620,1704140 }, { 646300,1707000 } },
{ { 646300,1707000 }, { 649060,1710880 } },
{ { 649060,1710880 }, { 651160,1714879 } },
{ { 651160,1714879 }, { 651740,1716559 } },
{ { 651740,1716559 }, { 653139,1722619 } },
{ { 653139,1722619 }, { 653020,1728320 } },
{ { 653020,1728320 }, { 652719,1731420 } },
{ { 652719,1731420 }, { 651619,1736360 } },
{ { 651619,1736360 }, { 649819,1743160 } },
{ { 649819,1743160 }, { 646440,1749059 } },
{ { 646440,1749059 }, { 645219,1750399 } },
{ { 645219,1750399 }, { 643959,1752679 } },
{ { 643959,1752679 }, { 643959,1753740 } },
{ { 643959,1753740 }, { 642140,1754240 } },
{ { 642140,1754240 }, { 643760,1754099 } },
{ { 643760,1754099 }, { 644320,1754280 } },
{ { 644320,1754280 }, { 645000,1754879 } },
{ { 645000,1754879 }, { 646940,1755620 } },
{ { 646940,1755620 }, { 654779,1757820 } },
{ { 654779,1757820 }, { 661100,1761559 } },
{ { 661100,1761559 }, { 664099,1763980 } },
{ { 664099,1763980 }, { 668220,1768480 } },
{ { 668220,1768480 }, { 671920,1773640 } },
{ { 671920,1773640 }, { 674939,1779540 } },
{ { 674939,1779540 }, { 677760,1782440 } },
{ { 677760,1782440 }, { 679080,1785739 } },
{ { 679080,1785739 }, { 678780,1788100 } },
{ { 678780,1788100 }, { 678020,1791500 } },
{ { 678020,1791500 }, { 677120,1793600 } },
{ { 677120,1793600 }, { 676860,1795800 } },
{ { 676860,1795800 }, { 676440,1797320 } },
{ { 676440,1797320 }, { 676459,1798519 } },
{ { 676459,1798519 }, { 675620,1800159 } },
{ { 675620,1800159 }, { 675520,1801019 } },
{ { 675520,1801019 }, { 673360,1804899 } },
{ { 673360,1804899 }, { 672740,1807079 } },
{ { 672740,1807079 }, { 673300,1809260 } },
{ { 673300,1809260 }, { 674539,1811019 } },
{ { 674539,1811019 }, { 675499,1812020 } },
{ { 675499,1812020 }, { 677660,1817240 } },
{ { 677660,1817240 }, { 679659,1824280 } },
{ { 679659,1824280 }, { 680380,1828779 } },
{ { 680380,1828779 }, { 679519,1837999 } },
{ { 679519,1837999 }, { 677940,1844379 } },
{ { 677940,1844379 }, { 676940,1846900 } },
{ { 676940,1846900 }, { 675479,1849379 } },
{ { 675479,1849379 }, { 674000,1851200 } },
{ { 674000,1851200 }, { 671380,1853480 } },
{ { 671380,1853480 }, { 667019,1855240 } },
{ { 667019,1855240 }, { 662540,1856060 } },
{ { 662540,1856060 }, { 660960,1856599 } },
{ { 660960,1856599 }, { 656240,1857020 } },
{ { 656240,1857020 }, { 655600,1856960 } },
{ { 655600,1856960 }, { 652839,1855880 } },
{ { 652839,1855880 }, { 652019,1855840 } },
{ { 652019,1855840 }, { 651459,1855060 } },
{ { 651459,1855060 }, { 652179,1854359 } },
{ { 652179,1854359 }, { 652019,1849919 } },
{ { 652019,1849919 }, { 650620,1846920 } },
{ { 650620,1846920 }, { 647299,1844540 } },
{ { 647299,1844540 }, { 644500,1843819 } },
{ { 644500,1843819 }, { 641860,1844859 } },
{ { 641860,1844859 }, { 641059,1845340 } },
{ { 641059,1845340 }, { 638860,1845820 } },
{ { 638860,1845820 }, { 638000,1845820 } },
{ { 638000,1845820 }, { 636340,1845479 } },
{ { 636340,1845479 }, { 634980,1844800 } },
{ { 634980,1844800 }, { 632660,1842979 } },
{ { 632660,1842979 }, { 631140,1841120 } },
{ { 631140,1841120 }, { 629140,1839520 } },
{ { 629140,1839520 }, { 626640,1839540 } },
{ { 626640,1839540 }, { 624159,1840739 } },
{ { 624159,1840739 }, { 623820,1841380 } },
{ { 623820,1841380 }, { 622440,1842719 } },
{ { 622440,1842719 }, { 622100,1843680 } },
{ { 622100,1843680 }, { 623780,1846100 } },
{ { 623780,1846100 }, { 624580,1846920 } },
{ { 624580,1846920 }, { 626120,1856720 } },
{ { 626120,1856720 }, { 627440,1860000 } },
{ { 627440,1860000 }, { 628000,1864299 } },
{ { 628000,1864299 }, { 627380,1865999 } },
{ { 627380,1865999 }, { 626260,1867580 } },
{ { 626260,1867580 }, { 623660,1869520 } },
{ { 623660,1869520 }, { 618680,1872780 } },
{ { 618680,1872780 }, { 617699,1873140 } },
{ { 617699,1873140 }, { 612000,1874160 } },
{ { 612000,1874160 }, { 609840,1874220 } },
{ { 609840,1874220 }, { 606940,1873860 } },
{ { 136680,1926960 }, { 135500,1926360 } },
{ { 135500,1926360 }, { 137360,1923060 } },
{ { 137360,1923060 }, { 139500,1918559 } },
{ { 139500,1918559 }, { 140780,1913239 } },
{ { 140780,1913239 }, { 139600,1913020 } },
{ { 139600,1913020 }, { 127380,1923600 } },
{ { 127380,1923600 }, { 122800,1926059 } },
{ { 122800,1926059 }, { 118879,1927719 } },
{ { 118879,1927719 }, { 114420,1928300 } },
{ { 114420,1928300 }, { 111480,1927020 } },
{ { 111480,1927020 }, { 110619,1925399 } },
{ { 110619,1925399 }, { 109620,1924200 } },
{ { 109620,1924200 }, { 108860,1922780 } },
{ { 108860,1922780 }, { 108479,1920999 } },
{ { 108479,1920999 }, { 106600,1918080 } },
{ { 106600,1918080 }, { 106220,1917740 } },
{ { 106220,1917740 }, { 105199,1916960 } },
{ { 105199,1916960 }, { 101460,1914859 } },
{ { 101460,1914859 }, { 99480,1914379 } },
{ { 99480,1914379 }, { 97179,1913499 } },
{ { 97179,1913499 }, { 94900,1911100 } },
{ { 94900,1911100 }, { 94100,1909639 } },
{ { 94100,1909639 }, { 93379,1907740 } },
{ { 93379,1907740 }, { 93960,1898259 } },
{ { 93960,1898259 }, { 93739,1896460 } },
{ { 93739,1896460 }, { 94299,1893080 } },
{ { 94299,1893080 }, { 97240,1883440 } },
{ { 97240,1883440 }, { 99799,1879780 } },
{ { 99799,1879780 }, { 100400,1878120 } },
{ { 100400,1878120 }, { 100199,1877200 } },
{ { 100199,1877200 }, { 98940,1877460 } },
{ { 98940,1877460 }, { 96320,1878480 } },
{ { 96320,1878480 }, { 86020,1881039 } },
{ { 86020,1881039 }, { 84340,1881080 } },
{ { 84340,1881080 }, { 76780,1882600 } },
{ { 76780,1882600 }, { 74380,1883580 } },
{ { 74380,1883580 }, { 72679,1884019 } },
{ { 72679,1884019 }, { 70900,1885940 } },
{ { 70900,1885940 }, { 71240,1888340 } },
{ { 71240,1888340 }, { 72720,1889940 } },
{ { 72720,1889940 }, { 74640,1891360 } },
{ { 74640,1891360 }, { 75620,1893179 } },
{ { 75620,1893179 }, { 77140,1895340 } },
{ { 77140,1895340 }, { 81040,1899500 } },
{ { 81040,1899500 }, { 82760,1900380 } },
{ { 82760,1900380 }, { 83720,1902300 } },
{ { 83720,1902300 }, { 85459,1903700 } },
{ { 85459,1903700 }, { 86960,1905940 } },
{ { 86960,1905940 }, { 88280,1913020 } },
{ { 88280,1913020 }, { 88160,1913539 } },
{ { 88160,1913539 }, { 88020,1913860 } },
{ { 88020,1913860 }, { 86080,1915200 } },
{ { 86080,1915200 }, { 85660,1916740 } },
{ { 85660,1916740 }, { 83899,1918799 } },
{ { 83899,1918799 }, { 79360,1921160 } },
{ { 79360,1921160 }, { 76400,1923140 } },
{ { 76400,1923140 }, { 70800,1926180 } },
{ { 70800,1926180 }, { 64460,1927659 } },
{ { 64460,1927659 }, { 60880,1927820 } },
{ { 60880,1927820 }, { 55780,1925580 } },
{ { 55780,1925580 }, { 54940,1925040 } },
{ { 54940,1925040 }, { 52199,1921700 } },
{ { 52199,1921700 }, { 49680,1916579 } },
{ { 49680,1916579 }, { 48719,1914180 } },
{ { 48719,1914180 }, { 48620,1913080 } },
{ { 48620,1913080 }, { 47640,1909120 } },
{ { 47640,1909120 }, { 48280,1899319 } },
{ { 48280,1899319 }, { 49140,1895600 } },
{ { 49140,1895600 }, { 50320,1892899 } },
{ { 50320,1892899 }, { 51559,1890640 } },
{ { 51559,1890640 }, { 52140,1889960 } },
{ { 52140,1889960 }, { 54640,1887999 } },
{ { 54640,1887999 }, { 55639,1886500 } },
{ { 55639,1886500 }, { 55720,1885080 } },
{ { 55720,1885080 }, { 55439,1883220 } },
{ { 55439,1883220 }, { 54640,1882159 } },
{ { 54640,1882159 }, { 54100,1880300 } },
{ { 54100,1880300 }, { 52479,1874079 } },
{ { 52479,1874079 }, { 51700,1869000 } },
{ { 51700,1869000 }, { 51600,1865419 } },
{ { 51600,1865419 }, { 51720,1859820 } },
{ { 51720,1859820 }, { 52160,1857260 } },
{ { 52160,1857260 }, { 52539,1856120 } },
{ { 52539,1856120 }, { 57240,1845720 } },
{ { 57240,1845720 }, { 58280,1844400 } },
{ { 58280,1844400 }, { 60639,1840820 } },
{ { 60639,1840820 }, { 65580,1835540 } },
{ { 65580,1835540 }, { 68340,1833340 } },
{ { 68340,1833340 }, { 71660,1831480 } },
{ { 71660,1831480 }, { 73460,1829960 } },
{ { 73460,1829960 }, { 75200,1829319 } },
{ { 75200,1829319 }, { 77200,1828960 } },
{ { 77200,1828960 }, { 78640,1828920 } },
{ { 78640,1828920 }, { 111780,1842700 } },
{ { 111780,1842700 }, { 112800,1843480 } },
{ { 112800,1843480 }, { 113879,1844879 } },
{ { 113879,1844879 }, { 116379,1847379 } },
{ { 116379,1847379 }, { 116360,1847580 } },
{ { 116360,1847580 }, { 117100,1848799 } },
{ { 117100,1848799 }, { 120160,1851799 } },
{ { 120160,1851799 }, { 121860,1852320 } },
{ { 121860,1852320 }, { 124280,1852679 } },
{ { 124280,1852679 }, { 128920,1854659 } },
{ { 128920,1854659 }, { 130840,1856360 } },
{ { 130840,1856360 }, { 133520,1859460 } },
{ { 133520,1859460 }, { 135079,1860860 } },
{ { 135079,1860860 }, { 137280,1864440 } },
{ { 137280,1864440 }, { 142980,1872899 } },
{ { 142980,1872899 }, { 144600,1875840 } },
{ { 144600,1875840 }, { 147240,1883480 } },
{ { 147240,1883480 }, { 147460,1886539 } },
{ { 147460,1886539 }, { 147660,1886920 } },
{ { 147660,1886920 }, { 148399,1891720 } },
{ { 148399,1891720 }, { 148820,1896799 } },
{ { 148820,1896799 }, { 148399,1898880 } },
{ { 148399,1898880 }, { 148799,1899420 } },
{ { 148799,1899420 }, { 150520,1898539 } },
{ { 150520,1898539 }, { 154760,1892760 } },
{ { 154760,1892760 }, { 156580,1889240 } },
{ { 156580,1889240 }, { 156940,1888900 } },
{ { 156940,1888900 }, { 157540,1889540 } },
{ { 157540,1889540 }, { 156860,1896819 } },
{ { 156860,1896819 }, { 155639,1903940 } },
{ { 155639,1903940 }, { 153679,1908100 } },
{ { 153679,1908100 }, { 152859,1909039 } },
{ { 152859,1909039 }, { 149660,1915580 } },
{ { 149660,1915580 }, { 148000,1918600 } },
{ { 148000,1918600 }, { 141640,1926980 } },
{ { 141640,1926980 }, { 140060,1927899 } },
{ { 140060,1927899 }, { 136960,1929019 } },
{ { 136960,1929019 }, { 136680,1926960 } },
{ { 627100,1941519 }, { 625120,1940060 } },
{ { 625120,1940060 }, { 614580,1934680 } },
{ { 614580,1934680 }, { 608780,1929319 } },
{ { 608780,1929319 }, { 607400,1927679 } },
{ { 607400,1927679 }, { 606160,1925920 } },
{ { 606160,1925920 }, { 604480,1922240 } },
{ { 604480,1922240 }, { 602420,1916819 } },
{ { 602420,1916819 }, { 602279,1915260 } },
{ { 602279,1915260 }, { 602880,1907960 } },
{ { 602880,1907960 }, { 604140,1902719 } },
{ { 604140,1902719 }, { 605880,1898539 } },
{ { 605880,1898539 }, { 606640,1897399 } },
{ { 606640,1897399 }, { 609680,1894420 } },
{ { 609680,1894420 }, { 611099,1893640 } },
{ { 611099,1893640 }, { 616099,1890340 } },
{ { 616099,1890340 }, { 617520,1889160 } },
{ { 617520,1889160 }, { 620220,1885540 } },
{ { 620220,1885540 }, { 624480,1882260 } },
{ { 624480,1882260 }, { 628660,1880280 } },
{ { 628660,1880280 }, { 632520,1879659 } },
{ { 632520,1879659 }, { 637760,1879859 } },
{ { 637760,1879859 }, { 640899,1881500 } },
{ { 640899,1881500 }, { 644220,1883980 } },
{ { 644220,1883980 }, { 643900,1890860 } },
{ { 643900,1890860 }, { 643060,1894160 } },
{ { 643060,1894160 }, { 642459,1900320 } },
{ { 642459,1900320 }, { 642400,1903120 } },
{ { 642400,1903120 }, { 643819,1908519 } },
{ { 643819,1908519 }, { 644700,1912560 } },
{ { 644700,1912560 }, { 644640,1916380 } },
{ { 644640,1916380 }, { 644959,1918600 } },
{ { 644959,1918600 }, { 642540,1925620 } },
{ { 642540,1925620 }, { 642439,1926640 } },
{ { 642439,1926640 }, { 641860,1928300 } },
{ { 641860,1928300 }, { 638700,1932939 } },
{ { 638700,1932939 }, { 634820,1934200 } },
{ { 634820,1934200 }, { 631980,1936539 } },
{ { 631980,1936539 }, { 630160,1940600 } },
{ { 630160,1940600 }, { 627740,1941640 } },
{ { 627740,1941640 }, { 627400,1941660 } },
{ { 627400,1941660 }, { 627100,1941519 } }
};
#if 0
// Verify whether two any two non-neighbor line segments intersect. They should not, otherwise the Voronoi builder
// is not guaranteed to succeed.
for (size_t i = 0; i < lines.size(); ++ i)
for (size_t j = i + 1; j < lines.size(); ++ j) {
Point &ip1 = lines[i].a;
Point &ip2 = lines[i].b;
Point &jp1 = lines[j].a;
Point &jp2 = lines[j].b;
if (&ip1 != &jp2 && &jp1 != &ip2) {
REQUIRE(! Slic3r::Geometry::segments_intersect(ip1, ip2, jp1, jp2));
}
}
#endif
VD vd;
vd.construct_voronoi(lines.begin(), lines.end());
for (const auto& edge : vd.edges())
if (edge.is_finite()) {
auto v0 = edge.vertex0();
auto v1 = edge.vertex1();
REQUIRE((v0->x() == 0 || std::isnormal(v0->x())));
REQUIRE((v0->y() == 0 || std::isnormal(v0->y())));
REQUIRE((v1->x() == 0 || std::isnormal(v1->x())));
REQUIRE((v1->y() == 0 || std::isnormal(v1->y())));
}
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-NaNs.svg").c_str(),
vd, Points(), lines, Polygons(), Lines(), 0.015);
#endif
}
struct OffsetTest {
double distance;
size_t num_outer;
size_t num_inner;
};
TEST_CASE("Voronoi offset", "[VoronoiOffset]")
{
Polygons poly_with_hole = { Polygon {
{ 0, 10000000},
{ 700000, 0},
{ 700000, 9000000},
{ 9100000, 9000000},
{ 9100000, 0},
{10000000, 10000000}
}
};
double area = std::accumulate(poly_with_hole.begin(), poly_with_hole.end(), 0., [](double a, auto &poly){ return a + poly.area(); });
REQUIRE(area > 0.);
VD vd;
Lines lines = to_lines(poly_with_hole);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 1, 1 },
OffsetTest { scale_(0.4), 1, 1 },
OffsetTest { scale_(0.5), 1, 2 },
OffsetTest { scale_(0.505), 1, 2 },
OffsetTest { scale_(0.51), 1, 2 },
OffsetTest { scale_(0.52), 1, 1 },
OffsetTest { scale_(0.53), 1, 1 },
OffsetTest { scale_(0.54), 1, 1 },
OffsetTest { scale_(0.55), 1, 0 }
}) {
#if 0
Polygons offsetted_polygons_out = Slic3r::Voronoi::offset(vd, lines, ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset-out-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_out);
#endif
REQUIRE(offsetted_polygons_out.size() == ot.num_outer);
#endif
Polygons offsetted_polygons_in = Slic3r::Voronoi::offset(vd, lines, - ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset-in-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_in);
#endif
REQUIRE(offsetted_polygons_in.size() == ot.num_inner);
}
}
TEST_CASE("Voronoi offset 2", "[VoronoiOffset]")
{
coord_t mm = coord_t(scale_(1.));
Polygons poly = {
Polygon {
{ 0, 0 },
{ 1, 0 },
{ 1, 1 },
{ 2, 1 },
{ 2, 0 },
{ 3, 0 },
{ 3, 2 },
{ 0, 2 }
},
Polygon {
{ 0, - 1 - 2 },
{ 3, - 1 - 2 },
{ 3, - 1 - 0 },
{ 2, - 1 - 0 },
{ 2, - 1 - 1 },
{ 1, - 1 - 1 },
{ 1, - 1 - 0 },
{ 0, - 1 - 0 }
},
};
for (Polygon &p : poly)
for (Point &pt : p.points)
pt *= mm;
double area = std::accumulate(poly.begin(), poly.end(), 0., [](double a, auto &poly){ return a + poly.area(); });
REQUIRE(area > 0.);
VD vd;
Lines lines = to_lines(poly);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
OffsetTest { scale_(0.4), 2, 2 },
OffsetTest { scale_(0.45), 2, 2 },
OffsetTest { scale_(0.48), 2, 2 },
OffsetTest { scale_(0.5), 2, 4 },
OffsetTest { scale_(0.505), 2, 4 },
OffsetTest { scale_(0.7), 2, 0 },
OffsetTest { scale_(0.8), 1, 0 }
}) {
Polygons offsetted_polygons_out = Slic3r::Voronoi::offset(vd, lines, ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset2-out-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_out);
#endif
REQUIRE(offsetted_polygons_out.size() == ot.num_outer);
Polygons offsetted_polygons_in = Slic3r::Voronoi::offset(vd, lines, - ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset2-in-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_in);
#endif
REQUIRE(offsetted_polygons_in.size() == ot.num_inner);
}
}
TEST_CASE("Voronoi offset 3", "[VoronoiOffset]")
{
coord_t mm = coord_t(scale_(1.));
Polygons poly = {
Polygon {
{ 0, 0 },
{ 2, 0 },
{ 2, 1 },
{ 3, 1 },
{ 3, 0 },
{ 5, 0 },
{ 5, 2 },
{ 4, 2 },
{ 4, 3 },
{ 1, 3 },
{ 1, 2 },
{ 0, 2 }
},
Polygon {
{ 0, -1 - 2 },
{ 1, -1 - 2 },
{ 1, -1 - 3 },
{ 4, -1 - 3 },
{ 4, -1 - 2 },
{ 5, -1 - 2 },
{ 5, -1 - 0 },
{ 3, -1 - 0 },
{ 3, -1 - 1 },
{ 2, -1 - 1 },
{ 2, -1 - 0 },
{ 0, -1 - 0 }
},
};
for (Polygon &p : poly) {
REQUIRE(p.area() > 0.);
for (Point &pt : p.points)
pt *= mm;
}
VD vd;
Lines lines = to_lines(poly);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
OffsetTest { scale_(0.4), 2, 2 },
OffsetTest { scale_(0.49), 2, 2 },
OffsetTest { scale_(0.5), 2, 2 },
OffsetTest { scale_(0.51), 2, 2 },
OffsetTest { scale_(0.56), 2, 2 },
OffsetTest { scale_(0.6), 2, 2 },
OffsetTest { scale_(0.7), 2, 2 },
OffsetTest { scale_(0.8), 1, 6 },
OffsetTest { scale_(0.9), 1, 6 },
OffsetTest { scale_(0.99), 1, 6 },
OffsetTest { scale_(1.0), 1, 0 },
OffsetTest { scale_(1.01), 1, 0 },
}) {
Polygons offsetted_polygons_out = Slic3r::Voronoi::offset(vd, lines, ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset3-out-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_out);
#endif
REQUIRE(offsetted_polygons_out.size() == ot.num_outer);
Polygons offsetted_polygons_in = Slic3r::Voronoi::offset(vd, lines, - ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset3-in-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_in);
#endif
REQUIRE(offsetted_polygons_in.size() == ot.num_inner);
}
}
TEST_CASE("Voronoi offset with edge collapse", "[VoronoiOffset4]")
{
Polygons poly
{
// Outer contour
{
{ 434890, -64754575 },
{ 541060, -64669076 },
{ 585647, -64583538 },
{ 576999, -64484233 },
{ 485666, -64191173 },
{ 1029323, -63646261 },
{ 1416925, -63666243 },
{ 1541532, -63643075 },
{ 1541535, -63643075 },
{ 1541535, -63643074 },
{ 1552612, -63641015 },
{ 1631609, -63568270 },
{ 1678393, -63443639 },
{ 1725519, -63219942 },
{ 1770552, -62903321 },
{ 1742544, -62755934 },
{ 1758152, -62588378 },
{ 1702289, -62474826 },
{ 1638627, -62242058 },
{ 1671281, -61938568 },
{ 1792676, -61478332 },
{ 1934894, -60760597 },
{ 2160333, -60064089 },
{ 2638183, -58972890 },
{ 2933095, -58478536 },
{ 3173586, -58159527 },
{ 3557779, -57556727 },
{ 3707088, -57158174 },
{ 3758053, -56907139 },
{ 3935932, -56278649 },
{ 4077331, -56033426 },
{ 4151386, -55768739 },
{ 4293796, -55561683 },
{ 4383089, -55387391 },
{ 4614128, -55201443 },
{ 5268755, -54333831 },
{ 5547634, -53797296 },
{ 5573864, -53639250 },
{ 5736812, -53304157 },
{ 6090973, -52066302 },
{ 6148630, -51666664 },
{ 6189511, -50974991 },
{ 6244112, -50774489 },
{ 6302489, -50761556 },
{ 6511179, -50579861 },
{ 6778128, -50398667 },
{ 6896879, -50350264 },
{ 7388259, -49913262 },
{ 7630584, -49602449 },
{ 7886846, -48987881 },
{ 7871333, -48318666 },
{ 7770349, -47841179 },
{ 7570223, -47234733 },
{ 7283115, -46705503 },
{ 6842948, -46056539 },
{ 6612732, -45760004 },
{ 6150430, -44991494 },
{ 5564326, -44168114 },
{ 5193032, -43807544 },
{ 4932097, -43489047 },
{ 3857385, -42548846 },
{ 3764745, -42081468 },
{ 3539887, -41422273 },
{ 3283048, -40803856 },
{ 3005925, -40367981 },
{ 3136185, -39834533 },
{ 3333757, -38499972 },
{ 3360660, -38183895 },
{ 3353375, -38036005 },
{ 3398808, -37582504 },
{ 3604229, -37221781 },
{ 3698079, -36962934 },
{ 4000449, -36007804 },
{ 4256811, -35016707 },
{ 4405951, -34581428 },
{ 4364534, -34178439 },
{ 4124603, -33432250 },
{ 3806159, -32765167 },
{ 3359088, -32109020 },
{ 2880790, -31317192 },
{ 1548334, -30402139 },
{ -7, -30131023 },
{ -1548347, -30402139 },
{ -2880803, -31317189 },
{ -3359100, -32109018 },
{ -3806173, -32765166 },
{ -4124617, -33432248 },
{ -4364548, -34178436 },
{ -4405966, -34581423 },
{ -4256825, -35016707 },
{ -4000461, -36007800 },
{ -3698093, -36962933 },
{ -3604243, -37221781 },
{ -3398823, -37582501 },
{ -3353390, -38036003 },
{ -3360675, -38183892 },
{ -3333772, -38499972 },
{ -3136200, -39834530 },
{ -3005940, -40367980 },
{ -3283062, -40803852 },
{ -3539902, -41422273 },
{ -3764761, -42081468 },
{ -3857402, -42548846 },
{ -4932112, -43489047 },
{ -5193047, -43807544 },
{ -5564341, -44168114 },
{ -6150446, -44991494 },
{ -6612748, -45760000 },
{ -6842965, -46056536 },
{ -7283130, -46705503 },
{ -7570238, -47234733 },
{ -7770365, -47841179 },
{ -7871349, -48318666 },
{ -7886860, -48987873 },
{ -7630599, -49602451 },
{ -7388277, -49913260 },
{ -6896896, -50350264 },
{ -6778145, -50398667 },
{ -6511196, -50579862 },
{ -6302504, -50761557 },
{ -6244127, -50774488 },
{ -6189527, -50974989 },
{ -6148648, -51666664 },
{ -6090990, -52066302 },
{ -5736829, -53304157 },
{ -5573882, -53639250 },
{ -5547651, -53797296 },
{ -5268772, -54333831 },
{ -4614145, -55201443 },
{ -4383106, -55387389 },
{ -4293814, -55561683 },
{ -4151404, -55768739 },
{ -4077350, -56033423 },
{ -3935952, -56278647 },
{ -3758072, -56907137 },
{ -3707107, -57158170 },
{ -3557796, -57556727 },
{ -3173605, -58159527 },
{ -2933113, -58478536 },
{ -2638201, -58972890 },
{ -2295003, -59738435 },
{ -2160353, -60064089 },
{ -1978487, -60596626 },
{ -1792695, -61478332 },
{ -1671298, -61938574 },
{ -1638646, -62242058 },
{ -1702306, -62474826 },
{ -1758168, -62588380 },
{ -1742563, -62755934 },
{ -1770570, -62903317 },
{ -1725537, -63219946 },
{ -1678412, -63443639 },
{ -1631627, -63568270 },
{ -1553479, -63640201 },
{ -1416944, -63666243 },
{ -998854, -63645714 },
{ -485685, -64191173 },
{ -577019, -64484225 },
{ -585667, -64583538 },
{ -541079, -64669076 },
{ -434910, -64754575 },
{ -294192, -64810609 },
{ 294172, -64810609 },
},
// Hole 1
{
{ -842246, -45167428 },
{ -1473641, -45154392 },
{ -2181728, -45100161 },
{ -2804308, -44985842 },
{ -3100514, -44879269 },
{ -3836807, -44802155 },
{ -4035816, -44718913 },
{ -4167175, -44583299 },
{ -4496705, -44467674 },
{ -4486674, -44382045 },
{ -4343949, -44070577 },
{ -3740991, -43494686 },
{ -2701372, -43313358 },
{ -1493599, -43312838 },
{ -8, -43352868 },
{ 1414575, -43313336 },
{ 2701358, -43313358 },
{ 3095462, -43374735 },
{ 3740975, -43494686 },
{ 4343934, -44070583 },
{ 4486657, -44382044 },
{ 4496688, -44467670 },
{ 4167159, -44583300 },
{ 4035800, -44718913 },
{ 3836792, -44802155 },
{ 3100498, -44879269 },
{ 2804292, -44985842 },
{ 2181712, -45100161 },
{ 1473625, -45154389 },
{ 842231, -45167428 },
{ -8, -45232686 },
},
// Hole 2
{
{ 1657455, -63016679 },
{ 1723196, -63056286 },
{ 1541535, -63643074 },
{ 1541532, -63643075 },
{ 1030020, -63645562 },
}
};
VD vd;
Lines lines = to_lines(poly);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(0.2), 2, 2 },
OffsetTest { scale_(0.4), 2, 2 },
OffsetTest { scale_(0.49), 2, 3 },
OffsetTest { scale_(0.51), 2, 2 },
OffsetTest { scale_(0.56), 2, 2 },
OffsetTest { scale_(0.6), 2, 2 },
OffsetTest { scale_(0.7), 2, 2 },
OffsetTest { scale_(0.8), 2, 2 },
OffsetTest { scale_(0.9), 2, 2 },
OffsetTest { scale_(0.99), 1, 2 },
OffsetTest { scale_(1.0), 1, 2 },
OffsetTest { scale_(1.01), 1, 2 },
}) {
Polygons offsetted_polygons_out = Slic3r::Voronoi::offset(vd, lines, ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset3-out-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_out);
#endif
REQUIRE(offsetted_polygons_out.size() == ot.num_outer);
Polygons offsetted_polygons_in = Slic3r::Voronoi::offset(vd, lines, - ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset3-in-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_in);
#endif
REQUIRE(offsetted_polygons_in.size() == ot.num_inner);
}
}
// A sample extracted from file medallion_printable_fixed-teeth.stl from https://www.thingiverse.com/thing:1347129
// This test for offset scale_(2.9) and bigger
// triggers assert(r < std::max(d0, d1) + EPSILON) in function first_circle_segment_intersection_parameter.
TEST_CASE("Voronoi offset 5", "[VoronoiOffset5]")
{
Polygons poly = {
Polygon {
{ 0 , -16077501 },
{ 3015222 , -16142836 },
{ 3072642 , -16138163 },
{ 3094279 , -16105662 },
{ 3110660 , -15140728 },
{ 3157438 , -14105326 },
{ 3338367 , -11081394 },
{ 3443412 , -8381621 },
{ 3472489 , -6084497 },
{ 3445790 , -5962924 },
{ 3061725 , -6003484 },
{ 3030326 , -6030622 },
{ 2989343 , -6270378 },
{ 2903752 , -7368176 },
{ 2856704 , -7740619 },
{ 2795743 , -7978809 },
{ 2729231 , -8098866 },
{ 2666509 , -8131138 },
{ 2614169 , -8112308 },
{ 2561157 , -8032014 },
{ 2488290 , -7479351 },
{ 2453360 , -6911556 },
{ 2456148 , -6463146 },
{ 2546029 , -4580396 },
{ 2688181 , -2593262 },
{ 2717617 , -1700519 },
{ 2682232 , -1128411 },
{ 2631029 , -832886 },
{ 2535941 , -504483 },
{ 2399115 , -199303 },
{ 2290997 , -171213 },
{ 611824 , -132865 },
{ 6419 , -375849 },
{ -611825 , -132865 },
{ -2377355 , -185241 },
{ -2420740 , -231171 },
{ -2535942 , -504484 },
{ -2631030 , -832887 },
{ -2684831 , -1150821 },
{ -2714840 , -1586454 },
{ -2688181 , -2593262 },
{ -2546030 , -4580396 },
{ -2456149 , -6463145 },
{ -2453361 , -6911557 },
{ -2488291 , -7479352 },
{ -2561159 , -8032018 },
{ -2614171 , -8112309 },
{ -2666509 , -8131138 },
{ -2729233 , -8098868 },
{ -2795744 , -7978809 },
{ -2856706 , -7740619 },
{ -2903752 , -7368176 },
{ -2989345 , -6270378 },
{ -3030327 , -6030622 },
{ -3061726 , -6003484 },
{ -3445790 , -5962924 },
{ -3472490 , -6084498 },
{ -3468804 , -7244095 },
{ -3399287 , -9714025 },
{ -3338368 , -11081395 },
{ -3141015 , -14446051 },
{ -3094280 , -16105662 },
{ -3072643 , -16138163 },
{ -3008836 , -16143225 }
}
};
double area = std::accumulate(poly.begin(), poly.end(), 0., [](double a, auto &poly){ return a + poly.area(); });
REQUIRE(area > 0.);
VD vd;
Lines lines = to_lines(poly);
vd.construct_voronoi(lines.begin(), lines.end());
for (const OffsetTest &ot : {
OffsetTest { scale_(2.8), 1, 1 },
OffsetTest { scale_(2.9), 1, 1 },
OffsetTest { scale_(3.0), 1, 1 },
}) {
Polygons offsetted_polygons_out = Slic3r::Voronoi::offset(vd, lines, ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset5-out-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_out);
#endif
REQUIRE(offsetted_polygons_out.size() == ot.num_outer);
Polygons offsetted_polygons_in = Slic3r::Voronoi::offset(vd, lines, - ot.distance, scale_(0.005));
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("voronoi-offset5-in-%lf.svg", ot.distance).c_str(),
vd, Points(), lines, offsetted_polygons_in);
#endif
REQUIRE(offsetted_polygons_in.size() == ot.num_inner);
}
}
TEST_CASE("Voronoi skeleton", "[VoronoiSkeleton]")
{
coord_t mm = coord_t(scale_(1.));
Polygons poly = {
Polygon {
{ 0, 0 },
{ 1, 0 },
{ 1, 1 },
{ 2, 1 },
{ 2, 0 },
{ 3, 0 },
{ 3, 2 },
{ 0, 2 }
},
Polygon {
{ 0, - 1 - 2 },
{ 3, - 1 - 2 },
{ 3, - 1 - 0 },
{ 2, - 1 - 0 },
{ 2, - 1 - 1 },
{ 1, - 1 - 1 },
{ 1, - 1 - 0 },
{ 0, - 1 - 0 }
},
};
for (Polygon &p : poly)
for (Point &pt : p.points)
pt *= mm;
double area = std::accumulate(poly.begin(), poly.end(), 0., [](double a, auto &poly){ return a + poly.area(); });
REQUIRE(area > 0.);
VD vd;
Lines lines = to_lines(poly);
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);
REQUIRE(! skeleton_edges.empty());
}
// Simple detection with complexity N^2 if there is any point in the input polygons that doesn't have Voronoi vertex.
[[maybe_unused]] static bool has_missing_voronoi_vertices(const Polygons &polygons, const VD &vd)
{
auto are_equal = [](const VD::vertex_type v, const Point &p) { return (Vec2d(v.x(), v.y()) - p.cast<double>()).norm() <= SCALED_EPSILON; };
Points poly_points = to_points(polygons);
std::vector<bool> found_vertices(poly_points.size());
for (const Point &point : poly_points)
for (const auto &vertex : vd.vertices())
if (are_equal(vertex, point)) {
found_vertices[&point - &poly_points.front()] = true;
break;
}
return std::find(found_vertices.begin(), found_vertices.end(), false) != found_vertices.end();
}
// This case is composed of one square polygon, and one of the edges is divided into two parts by a point that lies on this edge.
// In some applications, this point is unnecessary and can be removed (merge two parts to one edge). But for the case of
// multi-material segmentation, these points are necessary. In this case, Voronoi vertex for the point, which divides the edge
// into two parts. Even we add more points to the edge, and then for these points, the Voronoin vertex is also missing. An
// infinity-edge passes through the missing Voronoi vertex. Therefore, this missing Voronoi vertex and edge can be reconstructed
// using the intersection between the infinity-edge with the input polygon.
// Rotation of the polygon solves this problem.
TEST_CASE("Voronoi missing vertex 1", "[VoronoiMissingVertex1]")
{
Polygon poly = {
{ 25000000, 25000000},
{-25000000, 25000000},
{-25000000, -25000000},
{-12412500, -25000000},
// {- 1650000, -25000000},
{ 25000000, -25000000}
};
// poly.rotate(PI / 6);
REQUIRE(poly.area() > 0.);
REQUIRE(intersecting_edges({poly}).empty());
VD vd;
Lines lines = to_lines(poly);
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
// REQUIRE(!has_missing_voronoi_vertices({poly}, vd));
}
// This case is composed of two square polygons (contour and hole), and again one of the edges is divided into two parts by a
// point that lies on this edge, and for this point is Voronoi vertex missing. A difference between the previous and this case is
// that for this case, through the missing Voronoi vertex is passing a finite edge between two internal Voronoin vertices.
// Therefore, this missing Voronoi vertex and edge can be reconstructed using the intersection between the finite edge with the
// input polygon.
// Rotation of the polygons solves this problem.
TEST_CASE("Voronoi missing vertex 2", "[VoronoiMissingVertex2]")
{
Polygons poly = {
Polygon {
{ 50000000, 50000000},
{-50000000, 50000000},
{-50000000, -50000000},
{ 50000000, -50000000},
},
Polygon {
{-45000000, -45000000},
{-45000000, 45000000},
{ 45000000, 45000000},
{ 45000000, 8280000},
{ 45000000, -45000000},
}
};
// polygons_rotate(poly, PI / 6);
double area = std::accumulate(poly.begin(), poly.end(), 0., [](double a, auto &poly) { return a + poly.area(); });
REQUIRE(area > 0.);
REQUIRE(intersecting_edges(poly).empty());
VD vd;
Lines lines = to_lines(poly);
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
// REQUIRE(!has_missing_voronoi_vertices(poly, vd));
}
// This case is composed of two polygons, and again one of the edges is divided into two parts by a point that lies on this edge,
// and for this point is Voronoi vertex missing. A difference between the previous cases and this case through the missing
// Voronoi vertex is passing finite edge between one inner Voronoi vertex and one outer Voronoi vertex.
// Rotating the polygon also help solve this problem.
TEST_CASE("Voronoi missing vertex 3", "[VoronoiMissingVertex3]")
{
Polygons poly = {
Polygon {
{-29715088, -29310899},
{-29022573, -28618384},
{-27771147, -27366958},
{-28539221, -26519393},
{-30619013, -28586348},
{-29812018, -29407830},
},
Polygon {
{-27035112, -28071875},
{-27367482, -27770679},
{-28387008, -28790205},
{-29309438, -29712635},
{-29406319, -29809515},
{-29032985, -30179156},
}
};
double area = std::accumulate(poly.begin(), poly.end(), 0., [](double a, auto &poly){ return a + poly.area(); });
REQUIRE(area > 0.);
REQUIRE(intersecting_edges(poly).empty());
// polygons_rotate(poly, PI/180);
// polygons_rotate(poly, PI/6);
VD vd;
Lines lines = to_lines(poly);
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
// REQUIRE(!has_missing_voronoi_vertices(poly, vd));
}
TEST_CASE("Voronoi missing vertex 4", "[VoronoiMissingVertex4]")
{
// Probably the reason why Voronoi vertex is missing is that 19299999 and 19300000 are very close.
Polygon polygon_1 = {
Point(27000000, -18900000),
Point(27000000, 20000000),
Point(19000000, 20000000),
Point(19000000, 19299999),
Point(26000000, -18000000),
Point(-19000000, -18000000),
Point(-27000000, 19300000),
Point(-19000000, 19300000),
Point(-19000000, 20000000),
Point(-28000000, 20000000),
Point(-20000000, -18900000),
};
// Maybe this is the same case as the previous, but the missing Voronoi vertex is different.
Polygon polygon_2 = {
Point(27000000, -18900000),
Point(27000000, 20000000),
Point(19000000, 20000000),
Point(19000000, 19299999),
Point(19000000, -18000000), // Just this point is different other points are the same as previous.
Point(-19000000, -18000000),
Point(-27000000, 19300000),
Point(-19000000, 19300000),
Point(-19000000, 20000000),
Point(-28000000, 20000000),
Point(-20000000, -18900000),
};
Geometry::VoronoiDiagram vd_1;
Geometry::VoronoiDiagram vd_2;
Lines lines_1 = to_lines(polygon_1);
Lines lines_2 = to_lines(polygon_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);
#endif
}
// In this case, the Voronoi vertex (146873, -146873) is included twice.
// Also, near to those duplicate Voronoi vertices is another Voronoi vertex (146872, -146872).
// Rotating the polygon will help solve this problem, but then there arise three very close Voronoi vertices.
// Rotating of the input polygon will help solve this problem.
TEST_CASE("Duplicate Voronoi vertices", "[Voronoi]")
{
Polygon poly = {
{ 25000000, 25000000},
{-25000000, 25000000},
{-25000000, -25000000},
{ 146872, -25000000},
{ 9912498, -25000000},
{ 25000000, -25000000},
{ 25000000, - 8056252},
{ 25000000, - 146873},
{ 25000000, 10790627},
};
// poly.rotate(PI / 6);
REQUIRE(poly.area() > 0.);
REQUIRE(intersecting_edges({poly}).empty());
VD vd;
Lines lines = to_lines(poly);
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
[[maybe_unused]] auto has_duplicate_vertices = [](const VD &vd) -> bool {
std::vector<Vec2d> vertices;
for (const auto &vertex : vd.vertices())
vertices.emplace_back(Vec2d(vertex.x(), vertex.y()));
std::sort(vertices.begin(), vertices.end(), [](const Vec2d &l, const Vec2d &r) { return l.x() < r.x() || (l.x() == r.x() && l.y() < r.y()); });
return std::unique(vertices.begin(), vertices.end()) != vertices.end();
};
// REQUIRE(!has_duplicate_vertices(vd));
}
// In this case, there are three very close Voronoi vertices like in the previous test case after rotation. There is also one
// missing Voronoi vertex. One infinity-edge (after clip [(146872, -70146871), (146872, -146871)]) passes through this missing
// Voronoi vertex. This infinite edge [(146872, -70146871), (146872, -146871)] and edge [(146873, -146873), (0, 0)] are intersecting.
// They intersect probably because the three points are very close to each other, with a combination of the missing Voronoi vertex.
// Rotating of the input polygon will help solve this problem.
TEST_CASE("Intersecting Voronoi edges", "[Voronoi]")
{
Polygon poly = {
{ 25000000, 25000000},
{-25000000, 25000000},
{-25000000, -25000000},
{ 146872, -25000000},
{ 25000000, -25000000},
{ 25000000, - 146873},
};
// poly.rotate(PI / 6);
REQUIRE(poly.area() > 0.);
REQUIRE(intersecting_edges({poly}).empty());
VD vd;
Lines lines = to_lines(poly);
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
[[maybe_unused]] auto has_intersecting_edges = [](const Polygon &poly, const VD &vd) -> bool {
BoundingBox bbox = get_extents(poly);
const double bbox_dim_max = double(std::max(bbox.size().x(), bbox.size().y()));
std::vector<Voronoi::Internal::segment_type> segments;
for (const Line &line : to_lines(poly))
segments.emplace_back(Voronoi::Internal::point_type(double(line.a.x()), double(line.a.y())),
Voronoi::Internal::point_type(double(line.b.x()), double(line.b.y())));
Lines edges;
for (const auto &edge : vd.edges())
if (edge.cell()->source_index() < edge.twin()->cell()->source_index()) {
if (edge.is_finite()) {
edges.emplace_back(Point(coord_t(edge.vertex0()->x()), coord_t(edge.vertex0()->y())),
Point(coord_t(edge.vertex1()->x()), coord_t(edge.vertex1()->y())));
} else if (edge.is_infinite()) {
std::vector<Voronoi::Internal::point_type> samples;
Voronoi::Internal::clip_infinite_edge(poly.points, segments, edge, bbox_dim_max, &samples);
if (!samples.empty())
edges.emplace_back(Point(coord_t(samples[0].x()), coord_t(samples[0].y())), Point(coord_t(samples[1].x()), coord_t(samples[1].y())));
}
}
Point intersect_point;
for (auto first_it = edges.begin(); first_it != edges.end(); ++first_it)
for (auto second_it = first_it + 1; second_it != edges.end(); ++second_it)
if (first_it->intersection(*second_it, &intersect_point) && first_it->a != intersect_point && first_it->b != intersect_point)
return true;
return false;
};
// REQUIRE(!has_intersecting_edges(poly, vd));
}
// In this case resulting Voronoi diagram is not planar. This case was distilled from GH issue #8474.
// Also, in GH issue #8514, a non-planar Voronoi diagram is generated for several polygons.
// Rotating the input polygon will solve this issue.
TEST_CASE("Non-planar voronoi diagram", "[VoronoiNonPlanar]")
{
Polygon poly {
{ 5500000, -42000000},
{ 8000000, -17000000},
{ 8000000, 40000000},
{ 7500000, 40000000},
{ 7500000, -18000000},
{ 6000001, -18000000},
{ 6000000, 40000000},
{ 5500000, 40000000},
};
// poly.rotate(PI / 6);
REQUIRE(poly.area() > 0.);
REQUIRE(intersecting_edges({poly}).empty());
VD vd;
Lines lines = to_lines(poly);
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
// REQUIRE(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(vd));
}
// This case is extracted from SPE-1729, where several ExPolygon with very thin lines
// and holes formed by very close (1-5nm) vertices that are on the edge of our resolution.
// Those thin lines and holes are both unprintable and cause the Voronoi diagram to be invalid.
TEST_CASE("Invalid Voronoi diagram - Thin lines - SPE-1729", "[InvalidVoronoiDiagramThinLinesSPE1729]")
{
Polygon contour = {
{32247689, -2405501},
{32247733, -2308514},
{32247692, -2405496},
{50484384, 332941},
{50374839, 1052546},
{32938040, -1637993},
{32938024, -1673788},
{32942107, 7220481},
{32252205, 7447599},
{32252476, 8037808},
{32555965, 8277599},
{17729260, 8904718},
{17729236, 8853233},
{17729259, 8904722},
{17039259, 8935481},
{17033440, -3880421},
{17204385, -3852156},
{17723645, -3441873},
{17723762, -3187210},
{17728957, 8240730},
{17728945, 8213866},
{31716233, 7614090},
{20801623, -1009882},
{21253963, -1580792},
{32252082, 7157187},
{32248022, -1673787},
{24245653, -2925506},
{18449246, -3809095},
{18728385, -4449246}
};
Polygon hole = {
{32247789, -2181284},
{32247870, -2003865},
{32247872, -2003866},
{32247752, -2267007}
};
Polygons polygons = {contour, hole};
VD vd;
Lines lines = to_lines(polygons);
vd.construct_voronoi(lines.begin(), lines.end());
#ifdef VORONOI_DEBUG_OUT
dump_voronoi_to_svg(debug_out_path("invalid-voronoi-diagram-thin-lines.svg").c_str(), vd, Points(), lines);
#endif
// REQUIRE(vd.is_valid());
}