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.

216 lines
5.9 KiB
C++

1 month ago
#include <cstdint>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <string>
#include "clipper2/clipper.h"
#include "../../Utils/clipper.svg.h"
#include "../../Utils/ClipFileLoad.h"
#include "../../Utils/clipper.svg.utils.h"
#include "../../Utils/Colors.h"
#include "../../Utils/Timer.h"
using namespace std;
using namespace Clipper2Lib;
void System(const std::string& filename);
void PressEnterToExit();
void DoEllipses(int cnt);
void DoRectangles(int cnt);
void DoRandomPoly(int count);
void MeasurePerformance(int min, int max, int step);
const int width = 800, height = 600, margin = 120;
int main(int argc, char* argv[])
{
srand((unsigned)time(0));
DoEllipses(500);
DoRectangles(500);
//DoRandomPoly(21);
//MeasurePerformance(1000, 5000, 1000);
PressEnterToExit();
}
Path64 MakeRandomEllipse(int minWidth, int minHeight, int maxWidth, int maxHeight,
int maxRight, int maxBottom)
{
int w = maxWidth > minWidth ? minWidth + rand() % (maxWidth - minWidth) : minWidth;
int h = maxHeight > minHeight ? minHeight + rand() % (maxHeight - minHeight) : minHeight;
int l = rand() % (maxRight - w);
int t = rand() % (maxBottom - h);
return Ellipse(Rect64(l, t, l + w, t + h));
}
void DoEllipses(int cnt)
{
Paths64 sub, clp, sol, store;
Rect64 rect = Rect64(margin, margin, width - margin, height - margin);
clp.push_back(rect.AsPath());
for (int i = 0; i < cnt; ++i)
sub.push_back(MakeRandomEllipse(10, 10, 100, 100, width, height));
//////////////////////////////////
sol = RectClip(rect, sub);
//////////////////////////////////
FillRule fr = FillRule::EvenOdd;
SvgWriter svg;
svg.AddPaths(sub, false, fr, 0x100066FF, 0x400066FF, 1, false);
svg.AddPaths(clp, false, fr, 0x10FFAA00, 0xFFFF0000, 1, false);
svg.AddPaths(sol, false, fr, 0x8066FF66, 0xFF006600, 1, false);
svg.SaveToFile("rectclip1.svg", 800, 600, 0);
System("rectclip1.svg");
}
Path64 MakeRandomRectangle(int minWidth, int minHeight, int maxWidth, int maxHeight,
int maxRight, int maxBottom)
{
int w = maxWidth > minWidth ? minWidth + rand() % (maxWidth - minWidth): minWidth;
int h = maxHeight > minHeight ? minHeight + rand() % (maxHeight - minHeight): minHeight;
int l = rand() % (maxRight - w);
int t = rand() % (maxBottom - h);
Path64 result;
result.reserve(4);
result.push_back(Point64(l, t));
result.push_back(Point64(l+w, t));
result.push_back(Point64(l+w, t+h));
result.push_back(Point64(l, t+h));
return result;
}
void DoRectangles(int cnt)
{
Paths64 sub, clp, sol, store;
Rect64 rect = Rect64(margin, margin, width - margin, height - margin);
clp.push_back(rect.AsPath());
for (int i = 0; i < cnt; ++i)
sub.push_back(MakeRandomRectangle(10, 10, 100, 100, width, height));
sol = RectClip(rect, sub);
FillRule fr = FillRule::EvenOdd;
SvgWriter svg;
svg.AddPaths(sub, false, fr, 0x100066FF, 0x400066FF, 1, false);
svg.AddPaths(clp, false, fr, 0x10FFAA00, 0xFFFF0000, 1, false);
svg.AddPaths(sol, false, fr, 0x8066FF66, 0xFF006600, 1, false);
svg.SaveToFile("rectclip2.svg", 800, 600, 0);
System("rectclip2.svg");
}
Path64 MakeRandomPoly(int width, int height, unsigned vertCnt)
{
Path64 result;
result.reserve(vertCnt);
for (unsigned i = 0; i < vertCnt; ++i)
result.push_back(Point64(rand() % width, rand() % height));
return result;
}
PathD MakeRandomPolyD(int width, int height, unsigned vertCnt)
{
PathD result;
result.reserve(vertCnt);
for (unsigned i = 0; i < vertCnt; ++i)
result.push_back(PointD(rand() % width, rand() % height));
return result;
}
void DoRandomPoly(int count)
{
PathsD sub, clp, sol;
// generate random poly
RectD rect = RectD(margin, margin, width - margin, height - margin);
clp.push_back(rect.AsPath());
sub.push_back(MakeRandomPolyD(width, height, count));
//////////////////////////////////
sol = RectClip(rect, sub, false);
//////////////////////////////////
FillRule fr = FillRule::EvenOdd;
double frac = sol.size() ? 1.0 / sol.size() : 1.0;
double cum_frac = 0;
SvgWriter svg;
svg.AddPaths(sub, false, fr, 0x100066FF, 0x800066FF, 1, false);
svg.AddPaths(clp, false, fr, 0x10FFAA00, 0x80FF0000, 1, false);
//svg.AddPaths(sol, false, fr, 0x30AAFF00, 0xFF00FF00, 1, false);
for (const PathD& sol_path : sol)
{
uint32_t c = RainbowColor(cum_frac, 64);
cum_frac += frac;
uint32_t c2 = (c & 0xFFFFFF) | 0x20000000;
svg.AddPath(sol_path, false, fr, c2, c, 1.2, false);
}
svg.SaveToFile("rectclip3.svg", width, height, 0);
System("rectclip3.svg");
}
void MeasurePerformance(int min, int max, int step)
{
FillRule fr = FillRule::EvenOdd;
Paths64 sub, clp, sol, store;
Rect64 rect = Rect64(margin, margin, width - margin, height - margin);
clp.push_back(rect.AsPath());
for (int cnt = min; cnt <= max; cnt += step)
{
sub.clear();
sub.push_back(MakeRandomPoly(width, height, cnt));
std::cout << std::endl << cnt << " random poly" << std::endl;
{
Timer t("Clipper64: ");
sol = Intersect(sub, clp, fr);
}
{
Timer t("RectClip: ");
sol = RectClip(rect, sub);
}
}
SvgWriter svg;
svg.AddPaths(sub, false, fr, 0x200066FF, 0x400066FF, 1, false);
svg.AddPaths(clp, false, fr, 0x10FFAA00, 0xFFFF0000, 1, false);
//svg.AddPaths(sol, false, fr, 0x8066FF66, 0xFF006600, 1, false);
double frac = sol.size() ? 1.0 / sol.size() : 1.0;
double cum_frac = 0;
for (const Path64& sol_path : sol)
{
uint32_t c = RainbowColor(cum_frac, 64);
cum_frac += frac;
uint32_t c2 = (c & 0xFFFFFF) | 0x20000000;
svg.AddPath(sol_path, false, fr, c2, c, 1.2, false);
}
svg.SaveToFile("RectClipQ2.svg", 800, 600, 0);
System("RectClipQ2.svg");
}
void System(const std::string& filename)
{
#ifdef _WIN32
system(filename.c_str());
#else
system(("firefox " + filename).c_str());
#endif
}
void PressEnterToExit()
{
std::string s;
std::cout << std::endl << "Press Enter to exit" << std::endl;
std::getline(std::cin, s);
}