2020-10-25 20:50:14 +01:00
|
|
|
#if !defined(_WIN32) && !defined(BOOST_TEST_DYN_LINK)
|
2018-05-28 19:55:02 +02:00
|
|
|
#define BOOST_TEST_DYN_LINK
|
2020-07-14 18:16:18 +02:00
|
|
|
#endif
|
2018-05-28 19:55:02 +02:00
|
|
|
#define BOOST_TEST_MODULE Poly2triTest
|
2020-07-14 18:16:18 +02:00
|
|
|
|
2020-10-25 15:58:16 +01:00
|
|
|
#include <poly2tri/poly2tri.h>
|
|
|
|
|
2020-07-14 18:16:18 +02:00
|
|
|
#include <boost/filesystem/path.hpp>
|
2018-05-28 19:55:02 +02:00
|
|
|
#include <boost/test/unit_test.hpp>
|
2020-10-25 15:58:16 +01:00
|
|
|
|
2019-02-21 14:42:20 +01:00
|
|
|
#include <fstream>
|
2018-05-28 19:55:02 +02:00
|
|
|
#include <iostream>
|
2019-06-11 12:05:12 +02:00
|
|
|
#include <iterator>
|
2020-05-21 16:14:10 +02:00
|
|
|
#include <stdexcept>
|
2018-05-28 19:55:02 +02:00
|
|
|
|
2019-02-21 14:42:20 +01:00
|
|
|
BOOST_AUTO_TEST_CASE(BasicTest)
|
|
|
|
{
|
|
|
|
std::vector<p2t::Point*> polyline{
|
|
|
|
new p2t::Point(0, 0),
|
|
|
|
new p2t::Point(1, 0),
|
|
|
|
new p2t::Point(1, 1),
|
|
|
|
};
|
|
|
|
p2t::CDT cdt{ polyline };
|
2020-10-25 17:32:28 +01:00
|
|
|
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
2019-02-21 14:42:20 +01:00
|
|
|
const auto result = cdt.GetTriangles();
|
|
|
|
BOOST_REQUIRE_EQUAL(result.size(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(*result[0]->GetPoint(0), *polyline[0]);
|
|
|
|
BOOST_CHECK_EQUAL(*result[0]->GetPoint(1), *polyline[1]);
|
|
|
|
BOOST_CHECK_EQUAL(*result[0]->GetPoint(2), *polyline[2]);
|
|
|
|
BOOST_CHECK(p2t::IsDelaunay(result));
|
|
|
|
for (const auto p : polyline) {
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(QuadTest)
|
|
|
|
{
|
|
|
|
std::vector<p2t::Point*> polyline{ new p2t::Point(0, 0), new p2t::Point(0, 1),
|
|
|
|
new p2t::Point(1, 1), new p2t::Point(1, 0) };
|
|
|
|
p2t::CDT cdt{ polyline };
|
2020-10-25 17:32:28 +01:00
|
|
|
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
2019-02-21 14:42:20 +01:00
|
|
|
const auto result = cdt.GetTriangles();
|
|
|
|
BOOST_REQUIRE_EQUAL(result.size(), 2);
|
|
|
|
BOOST_CHECK(p2t::IsDelaunay(result));
|
|
|
|
for (const auto p : polyline) {
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-25 17:32:28 +01:00
|
|
|
BOOST_AUTO_TEST_CASE(NarrowQuadTest)
|
2020-05-21 16:14:10 +02:00
|
|
|
{
|
2022-03-16 02:36:53 +01:00
|
|
|
// Very narrow quad that used to demonstrate a failure case during
|
|
|
|
// triangulation
|
2020-05-21 16:14:10 +02:00
|
|
|
std::vector<p2t::Point*> polyline {
|
|
|
|
new p2t::Point(0.0, 0.0),
|
|
|
|
new p2t::Point(1.0e-05, 0.0),
|
|
|
|
new p2t::Point(1.1e-04, 3.0e-07),
|
|
|
|
new p2t::Point(1.0e-04, 3.0e-07)
|
|
|
|
};
|
|
|
|
p2t::CDT cdt{ polyline };
|
2022-03-16 02:36:53 +01:00
|
|
|
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
|
|
|
const auto result = cdt.GetTriangles();
|
|
|
|
BOOST_REQUIRE_EQUAL(result.size(), 2);
|
|
|
|
BOOST_CHECK(p2t::IsDelaunay(result));
|
2020-05-21 16:14:10 +02:00
|
|
|
for (const auto p : polyline) {
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-16 02:37:14 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-02-21 14:42:20 +01:00
|
|
|
BOOST_AUTO_TEST_CASE(TestbedFilesTest)
|
|
|
|
{
|
|
|
|
for (const auto& filename : { "custom.dat", "diamond.dat", "star.dat", "test.dat" }) {
|
|
|
|
std::vector<p2t::Point*> polyline;
|
|
|
|
// Load pointset from file
|
|
|
|
// Parse and tokenize data file
|
|
|
|
std::string line;
|
2020-07-14 18:16:18 +02:00
|
|
|
#ifndef P2T_BASE_DIR
|
|
|
|
const auto basedir = boost::filesystem::path(__FILE__).remove_filename().parent_path();
|
|
|
|
#else
|
|
|
|
const auto basedir = boost::filesystem::path(P2T_BASE_DIR);
|
|
|
|
#endif
|
|
|
|
const auto datafile = basedir / boost::filesystem::path("testbed/data") / boost::filesystem::path(filename);
|
|
|
|
std::ifstream myfile(datafile.string());
|
2019-02-21 14:42:20 +01:00
|
|
|
BOOST_REQUIRE(myfile.is_open());
|
|
|
|
while (!myfile.eof()) {
|
|
|
|
getline(myfile, line);
|
|
|
|
if (line.empty()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
std::istringstream iss(line);
|
|
|
|
std::vector<std::string> tokens;
|
|
|
|
copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(),
|
|
|
|
std::back_inserter<std::vector<std::string>>(tokens));
|
|
|
|
double x = std::stod(tokens[0]);
|
|
|
|
double y = std::stod(tokens[1]);
|
|
|
|
polyline.push_back(new p2t::Point(x, y));
|
|
|
|
}
|
|
|
|
p2t::CDT cdt{ polyline };
|
2020-10-25 17:32:28 +01:00
|
|
|
BOOST_CHECK_NO_THROW(cdt.Triangulate());
|
2019-02-21 14:42:20 +01:00
|
|
|
const auto result = cdt.GetTriangles();
|
|
|
|
BOOST_REQUIRE(result.size() * 3 > polyline.size());
|
|
|
|
BOOST_CHECK_MESSAGE(p2t::IsDelaunay(result), filename + std::to_string(polyline.size()));
|
|
|
|
for (const auto p : polyline) {
|
|
|
|
delete p;
|
|
|
|
}
|
|
|
|
}
|
2018-05-28 19:55:02 +02:00
|
|
|
}
|