Merge pull request #40 from roystgnr/no_collinearity_tolerance

Disable collinearity tolerance
This commit is contained in:
Jan Niklas Hasse 2022-03-23 21:34:31 +01:00 committed by GitHub
commit 529470f1d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 3 deletions

View File

@ -68,7 +68,11 @@ Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc)
double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x); double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright; double val = detleft - detright;
if (val > -EPSILON && val < EPSILON) {
// Using a tolerance here fails on concave-by-subepsilon boundaries
// if (val > -EPSILON && val < EPSILON) {
// Using == on double makes -Wfloat-equal warnings yell at us
if (std::fpclassify(val) == FP_ZERO) {
return COLLINEAR; return COLLINEAR;
} else if (val > 0) { } else if (val > 0) {
return CCW; return CCW;

View File

@ -49,7 +49,8 @@ BOOST_AUTO_TEST_CASE(QuadTest)
BOOST_AUTO_TEST_CASE(NarrowQuadTest) BOOST_AUTO_TEST_CASE(NarrowQuadTest)
{ {
// Very narrow quad that demonstrates a failure case during triangulation // Very narrow quad that used to demonstrate a failure case during
// triangulation
std::vector<p2t::Point*> polyline { std::vector<p2t::Point*> polyline {
new p2t::Point(0.0, 0.0), new p2t::Point(0.0, 0.0),
new p2t::Point(1.0e-05, 0.0), new p2t::Point(1.0e-05, 0.0),
@ -57,12 +58,61 @@ BOOST_AUTO_TEST_CASE(NarrowQuadTest)
new p2t::Point(1.0e-04, 3.0e-07) new p2t::Point(1.0e-04, 3.0e-07)
}; };
p2t::CDT cdt{ polyline }; p2t::CDT cdt{ polyline };
BOOST_CHECK_THROW(cdt.Triangulate(), std::runtime_error); BOOST_CHECK_NO_THROW(cdt.Triangulate());
const auto result = cdt.GetTriangles();
BOOST_REQUIRE_EQUAL(result.size(), 2);
BOOST_CHECK(p2t::IsDelaunay(result));
for (const auto p : polyline) { for (const auto p : polyline) {
delete p; delete p;
} }
} }
BOOST_AUTO_TEST_CASE(ConcaveBoundaryTest)
{
// Concave-by-less-than-epsilon boundaries used to potentially fail
// during triangulation
const double eps = 1e-15; // This gave EdgeEvent - null triangle
std::vector<p2t::Point*> polyline {
new p2t::Point(0,0),
new p2t::Point(0.5,eps),
new p2t::Point(1,0),
new p2t::Point(1-eps,0.836541),
new p2t::Point(1,2),
new p2t::Point(.46,1.46+eps),
new p2t::Point(0,1),
new p2t::Point(eps,0.5)
};
const double r2o4 = std::sqrt(2.)/4;
std::vector<p2t::Point*> hole {
new p2t::Point(0.5+r2o4,0.5),
new p2t::Point(0.5,0.5+r2o4),
new p2t::Point(0.5-r2o4,0.5),
new p2t::Point(0.5-eps,0.5-r2o4)
};
std::vector<p2t::Point> interior_points
{{0.21,0.79},{0.21,0.21},{0.79,0.21}};
p2t::CDT cdt{ polyline };
cdt.AddHole(hole);
for (auto & p : interior_points)
cdt.AddPoint(&p);
BOOST_CHECK_NO_THROW(cdt.Triangulate());
const auto result = cdt.GetTriangles();
BOOST_REQUIRE_EQUAL(result.size(), 18);
BOOST_CHECK(p2t::IsDelaunay(result));
for (const auto p : polyline) {
delete p;
}
for (const auto p : hole) {
delete p;
}
}
BOOST_AUTO_TEST_CASE(TestbedFilesTest) BOOST_AUTO_TEST_CASE(TestbedFilesTest)
{ {
for (const auto& filename : { "custom.dat", "diamond.dat", "star.dat", "test.dat" }) { for (const auto& filename : { "custom.dat", "diamond.dat", "star.dat", "test.dat" }) {