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.
83 lines
3.5 KiB
C++
83 lines
3.5 KiB
C++
|
1 month ago
|
#include <gtest/gtest.h>
|
||
|
|
#include "clipper2/clipper.h"
|
||
|
|
#include <fstream>
|
||
|
|
#include <random>
|
||
|
|
int GenerateRandomInt(std::default_random_engine& rng, int min_value, int max_value)
|
||
|
|
{
|
||
|
|
if (min_value == max_value)
|
||
|
|
return min_value;
|
||
|
|
std::uniform_int_distribution<int> distribution(min_value, max_value);
|
||
|
|
return distribution(rng);
|
||
|
|
}
|
||
|
|
Clipper2Lib::Paths64 GenerateRandomPaths(std::default_random_engine& rng, int min_path_count, int max_complexity)
|
||
|
|
{
|
||
|
|
std::uniform_int_distribution<int> first_point_coordinate_distribution(-max_complexity, max_complexity * 2);
|
||
|
|
std::uniform_int_distribution<int> difference_to_previous_point_distribution(-5, 5);
|
||
|
|
const int path_count = GenerateRandomInt(rng, min_path_count, max_complexity);
|
||
|
|
Clipper2Lib::Paths64 result(path_count);
|
||
|
|
for (int path = 0; path < path_count; ++path)
|
||
|
|
{
|
||
|
|
const int min_point_count = 0;
|
||
|
|
const int path_length = GenerateRandomInt(rng, min_point_count, std::max(min_point_count, max_complexity));
|
||
|
|
auto& result_path = result[path];
|
||
|
|
result_path.reserve(path_length);
|
||
|
|
for (int point = 0; point < path_length; ++point) {
|
||
|
|
if (result_path.empty()) {
|
||
|
|
result_path.emplace_back(
|
||
|
|
first_point_coordinate_distribution(rng),
|
||
|
|
first_point_coordinate_distribution(rng)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
const auto& previous_point = result_path.back();
|
||
|
|
result_path.emplace_back(
|
||
|
|
previous_point.x + difference_to_previous_point_distribution(rng),
|
||
|
|
previous_point.y + difference_to_previous_point_distribution(rng)
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
TEST(Clipper2Tests, TestRandomPaths)
|
||
|
|
{
|
||
|
|
std::default_random_engine rng(42);
|
||
|
|
#if DEBUG
|
||
|
|
for (int i = 0; i < 10; ++i)
|
||
|
|
#else
|
||
|
|
for (int i = 0; i < 750; ++i)
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
const auto max_complexity = std::max(1, i / 10);
|
||
|
|
const auto subject = GenerateRandomPaths(rng, 1, max_complexity);
|
||
|
|
const auto subject_open = GenerateRandomPaths(rng, 0, max_complexity);
|
||
|
|
const auto clip = GenerateRandomPaths(rng, 0, max_complexity);
|
||
|
|
const Clipper2Lib::ClipType ct = static_cast<Clipper2Lib::ClipType>(GenerateRandomInt(rng, 0, 4));
|
||
|
|
const Clipper2Lib::FillRule fr = static_cast<Clipper2Lib::FillRule>(GenerateRandomInt(rng, 0, 3));
|
||
|
|
//SaveInputToFile(subject, subject_open, clip, ct, fr);
|
||
|
|
Clipper2Lib::Paths64 solution, solution_open;
|
||
|
|
Clipper2Lib::Clipper64 c;
|
||
|
|
c.AddSubject(subject);
|
||
|
|
c.AddOpenSubject(subject_open);
|
||
|
|
c.AddClip(clip);
|
||
|
|
c.Execute(ct, fr, solution, solution_open);
|
||
|
|
const int64_t area_paths = static_cast<int64_t>(Area(solution));
|
||
|
|
const int64_t count_paths = solution.size() + solution_open.size();
|
||
|
|
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 auto solution_polytree_paths = PolyTreeToPaths64(solution_polytree);
|
||
|
|
const int64_t area_polytree = static_cast<int64_t>(Area(solution_polytree_paths));
|
||
|
|
const int64_t count_polytree = solution_polytree_paths.size() + solution_polytree_open.size();
|
||
|
|
EXPECT_EQ(area_paths, area_polytree);
|
||
|
|
// polytree does an additional bounds check on each path
|
||
|
|
// and discards paths with empty bounds, so count_polytree
|
||
|
|
// may on occasions be slightly less than count_paths even
|
||
|
|
// though areas match
|
||
|
|
//EXPECT_LE(count_paths - count_polytree, 2);
|
||
|
|
}
|
||
|
|
}
|