You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
5.3 KiB
C++
123 lines
5.3 KiB
C++
|
1 month ago
|
#include <gtest/gtest.h>
|
||
|
|
#include "clipper2/clipper.h"
|
||
|
|
#include "ClipFileLoad.h"
|
||
|
|
inline Clipper2Lib::PathD MakeRandomPath(int width, int height, unsigned vertCnt)
|
||
|
|
{
|
||
|
|
Clipper2Lib::PathD result;
|
||
|
|
result.reserve(vertCnt);
|
||
|
|
for (unsigned i = 0; i < vertCnt; ++i)
|
||
|
|
result.push_back(Clipper2Lib::PointD(double(rand()) / RAND_MAX * width, double(rand()) / RAND_MAX * height));
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
template <size_t N>
|
||
|
|
inline bool IsInList(int num, const int (&intArray)[N])
|
||
|
|
{
|
||
|
|
const int* list = &intArray[0];
|
||
|
|
for (int cnt = N; cnt; --cnt)
|
||
|
|
if (num == *list++) return true;
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
TEST(Clipper2Tests, TestMultiplePolygons)
|
||
|
|
{
|
||
|
|
std::ifstream ifs("Polygons.txt");
|
||
|
|
ASSERT_TRUE(ifs.good());
|
||
|
|
const int start_num = 1;
|
||
|
|
const int end_num = 1000;
|
||
|
|
int test_number = start_num;
|
||
|
|
while (test_number <= end_num)
|
||
|
|
{
|
||
|
|
Clipper2Lib::Paths64 subject, subject_open, clip;
|
||
|
|
Clipper2Lib::Paths64 solution, solution_open;
|
||
|
|
Clipper2Lib::ClipType ct;
|
||
|
|
Clipper2Lib::FillRule fr;
|
||
|
|
int64_t stored_area, stored_count;
|
||
|
|
if (!LoadTestNum(ifs, test_number,
|
||
|
|
subject, subject_open, clip, stored_area, stored_count, ct, fr)) break;
|
||
|
|
// check Paths64 solutions
|
||
|
|
Clipper2Lib::Clipper64 c;
|
||
|
|
c.AddSubject(subject);
|
||
|
|
c.AddOpenSubject(subject_open);
|
||
|
|
c.AddClip(clip);
|
||
|
|
c.Execute(ct, fr, solution, solution_open);
|
||
|
|
const int64_t measured_area = static_cast<int64_t>(Area(solution));
|
||
|
|
const int64_t measured_count = static_cast<int64_t>(solution.size() + solution_open.size());
|
||
|
|
// check the polytree variant too
|
||
|
|
Clipper2Lib::PolyTree64 solution_polytree;
|
||
|
|
Clipper2Lib::Paths64 solution_polytree_open;
|
||
|
|
Clipper2Lib::Clipper64 clipper_polytree;
|
||
|
|
clipper_polytree.AddSubject(subject);
|
||
|
|
clipper_polytree.AddOpenSubject(subject_open);
|
||
|
|
clipper_polytree.AddClip(clip);
|
||
|
|
clipper_polytree.Execute(ct, fr, solution_polytree, solution_polytree_open);
|
||
|
|
const int64_t measured_area_polytree =
|
||
|
|
static_cast<int64_t>(solution_polytree.Area());
|
||
|
|
const auto solution_polytree_paths = PolyTreeToPaths64(solution_polytree);
|
||
|
|
const int64_t measured_count_polytree =
|
||
|
|
static_cast<int64_t>(solution_polytree_paths.size());
|
||
|
|
// check polygon counts
|
||
|
|
if (stored_count <= 0)
|
||
|
|
; // skip count
|
||
|
|
else if (IsInList(test_number, { 120, 121, 130, 138,
|
||
|
|
140, 148, 163, 165, 166, 167, 168, 172, 173, 175, 178, 180 }))
|
||
|
|
EXPECT_NEAR(measured_count, stored_count, 5) << " in test " << test_number;
|
||
|
|
else if (IsInList(test_number, { 27, 181 }))
|
||
|
|
EXPECT_NEAR(measured_count, stored_count, 2) << " in test " << test_number;
|
||
|
|
else if (test_number >= 120 && test_number <= 184)
|
||
|
|
EXPECT_NEAR(measured_count, stored_count, 2) << " in test " << test_number;
|
||
|
|
else if (IsInList(test_number, { 23, 45, 87, 102, 111, 113, 191 }))
|
||
|
|
EXPECT_NEAR(measured_count, stored_count, 1) << " in test " << test_number;
|
||
|
|
else
|
||
|
|
EXPECT_EQ(measured_count, stored_count) << " in test " << test_number;
|
||
|
|
// check polygon areas
|
||
|
|
if (stored_area <= 0)
|
||
|
|
; // skip area
|
||
|
|
else if (IsInList(test_number, { 19, 22, 23, 24 }))
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.5 * measured_area) << " in test " << test_number;
|
||
|
|
else if (test_number == 193)
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.2 * measured_area) << " in test " << test_number;
|
||
|
|
else if (test_number == 63)
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.1 * measured_area) << " in test " << test_number;
|
||
|
|
else if (test_number == 16)
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.075 * measured_area) << " in test " << test_number;
|
||
|
|
else if (test_number == 26)
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.05 * measured_area) << " in test " << test_number;
|
||
|
|
else if (IsInList(test_number, { 15, 52, 53, 54, 59, 60, 64, 117, 119, 184 }))
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.02 * measured_area) << " in test " << test_number;
|
||
|
|
else
|
||
|
|
EXPECT_NEAR(measured_area, stored_area, 0.01 * measured_area) << " in test " << test_number;
|
||
|
|
EXPECT_EQ(measured_count, measured_count_polytree)
|
||
|
|
<< " in test " << test_number;
|
||
|
|
EXPECT_EQ(measured_area, measured_area_polytree)
|
||
|
|
<< " in test " << test_number;
|
||
|
|
++test_number;
|
||
|
|
}
|
||
|
|
//EXPECT_GE(test_number, 188);
|
||
|
|
Clipper2Lib::PathsD subjd, clipd, solutiond;
|
||
|
|
Clipper2Lib::FillRule frd = Clipper2Lib::FillRule::NonZero;
|
||
|
|
}
|
||
|
|
TEST(Clipper2Tests, TestHorzSpikes) //#720
|
||
|
|
{
|
||
|
|
Clipper2Lib::Paths64 paths = {
|
||
|
|
Clipper2Lib::MakePath({1600,0, 1600,100, 2050,100, 2050,300, 450,300, 450, 0}),
|
||
|
|
Clipper2Lib::MakePath({1800,200, 1800,100, 1600,100, 2000,100, 2000,200}) };
|
||
|
|
std::cout << paths << std::endl;
|
||
|
|
Clipper2Lib::Clipper64 c;
|
||
|
|
c.AddSubject(paths);
|
||
|
|
c.Execute(Clipper2Lib::ClipType::Union, Clipper2Lib::FillRule::NonZero, paths);
|
||
|
|
EXPECT_GE(paths.size(), 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(Clipper2Tests, TestCollinearOnMacOs) //#777
|
||
|
|
{
|
||
|
|
Clipper2Lib::Paths64 subject;
|
||
|
|
subject.push_back(Clipper2Lib::MakePath({ 0, -453054451,0, -433253797,-455550000, 0 }));
|
||
|
|
subject.push_back(Clipper2Lib::MakePath({ 0, -433253797,0, 0,-455550000, 0 }));
|
||
|
|
Clipper2Lib::Clipper64 clipper;
|
||
|
|
clipper.PreserveCollinear(false);
|
||
|
|
clipper.AddSubject(subject);
|
||
|
|
Clipper2Lib::Paths64 solution;
|
||
|
|
clipper.Execute(Clipper2Lib::ClipType::Union, Clipper2Lib::FillRule::NonZero, solution);
|
||
|
|
ASSERT_EQ(solution.size(), 1);
|
||
|
|
EXPECT_EQ(solution[0].size(), 3);
|
||
|
|
EXPECT_EQ(IsPositive(subject[0]), IsPositive(solution[0]));
|
||
|
|
}
|