diff --git a/README.md b/README.md index b3af367..88a0618 100644 --- a/README.md +++ b/README.md @@ -74,14 +74,19 @@ Load data points from a file: ``` build/testbed/p2t ``` +Load data points from a file and automatically fit the geometry to the window: +``` +build/testbed/p2t +``` Random distribution of points inside a constrained box: ``` build/testbed/p2t random ``` Examples: ``` -build/testbed/p2t testbed/data/dude.dat 300 500 2 -build/testbed/p2t testbed/data/nazca_monkey.dat 0 0 9 +build/testbed/p2t testbed/data/dude.dat 350 500 3 + +build/testbed/p2t testbed/data/nazca_monkey.dat build/testbed/p2t random 10 100 5.0 build/testbed/p2t random 1000 20000 0.025 diff --git a/testbed/main.cc b/testbed/main.cc index 007721b..d436c93 100644 --- a/testbed/main.cc +++ b/testbed/main.cc @@ -1,5 +1,5 @@ /* - * Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors + * Poly2Tri Copyright (c) 2009-2022, Poly2Tri Contributors * https://github.com/jhasse/poly2tri * * All rights reserved. @@ -40,10 +40,12 @@ #include #include #include +#include #include #include #include #include +#include #include using namespace std; @@ -51,11 +53,12 @@ using namespace p2t; bool ParseFile(string filename, vector& out_polyline, vector>& out_holes, vector& out_steiner); +std::pair BoundingBox(const std::vector& polyline); void GenerateRandomPointDistribution(size_t num_points, double min, double max, vector& out_polyline, vector>& out_holes, vector& out_steiner); -void Init(); +void Init(int window_width, int window_height); void ShutDown(int return_code); void MainLoop(const double zoom); void Draw(const double zoom); @@ -69,6 +72,13 @@ double rotate_y = 0.0, rotate_z = 0.0; const double rotations_per_tick = 0.2; +/// Default window size +constexpr int default_window_width = 800; +constexpr int default_window_height = 600; + +/// Autozoom border (percentage) +const double autozoom_border = 0.05; + /// Screen center x double cx = 0.0; /// Screen center y @@ -105,14 +115,21 @@ int main(int argc, char* argv[]) double max, min; double zoom; - if (argc != 5) { + if (argc != 2 && argc != 5) { cout << "-== USAGE ==-" << endl; - cout << "Load Data File: p2t filename center_x center_y zoom" << endl; - cout << "Example: ./build/p2t testbed/data/dude.dat 500 500 1" << endl; + cout << "Load Data File: p2t " << endl; + cout << " Example: build/testbed/p2t testbed/data/dude.dat 350 500 3" << endl; + cout << "Load Data File with Auto-Zoom: p2t " << endl; + cout << " Example: build/testbed/p2t testbed/data/nazca_monkey.dat" << endl; + cout << "Generate Random Polygon: p2t random " << endl; + cout << " Example: build/testbed/p2t random 100 1 500" << endl; return 1; } - if (string(argv[1]) == "random") { + // If true, adjust the zoom settings to fit the input geometry to the window + const bool autozoom = (argc == 2); + + if (!autozoom && string(argv[1]) == "random") { num_points = atoi(argv[2]); random_distribution = true; char* pEnd; @@ -122,9 +139,11 @@ int main(int argc, char* argv[]) zoom = atof(argv[4]); } else { filename = string(argv[1]); - cx = atof(argv[2]); - cy = atof(argv[3]); - zoom = atof(argv[4]); + if (!autozoom) { + cx = atof(argv[2]); + cy = atof(argv[3]); + zoom = atof(argv[4]); + } } if (random_distribution) { @@ -136,7 +155,21 @@ int main(int argc, char* argv[]) } } - Init(); + if (autozoom) { + assert(0.0 <= autozoom_border && autozoom_border < 1.0); + const auto bbox = BoundingBox(polyline); + Point center = bbox.first + bbox.second; + center *= 0.5; + cx = center.x; + cy = center.y; + Point sides = bbox.second - bbox.first; + zoom = 2.0 * (1.0 - autozoom_border) * std::min((double)default_window_width / sides.x, (double)default_window_height / sides.y); + std::cout << "center_x = " << cx << std::endl; + std::cout << "center_y = " << cy << std::endl; + std::cout << "zoom = " << zoom << std::endl; + } + + Init(default_window_width, default_window_height); /* * Perform triangulation! @@ -182,6 +215,7 @@ int main(int argc, char* argv[]) cout << "Total number of points = " << (polyline.size() + points_in_holes + steiner.size()) << endl; cout << "Number of triangles = " << triangles.size() << endl; + cout << "Is Delaunay = " << (IsDelaunay(triangles) ? "true" : "false") << endl; cout << "Elapsed time (ms) = " << dt * 1000.0 << endl; MainLoop(zoom); @@ -262,6 +296,21 @@ bool ParseFile(string filename, vector& out_polyline, vector BoundingBox(const std::vector& polyline) +{ + assert(polyline.size() > 0); + using Scalar = decltype(p2t::Point::x); + Point min(std::numeric_limits::max(), std::numeric_limits::max()); + Point max(std::numeric_limits::min(), std::numeric_limits::min()); + for (const Point* point : polyline) { + min.x = std::min(min.x, point->x); + min.y = std::min(min.y, point->y); + max.x = std::max(max.x, point->x); + max.y = std::max(max.y, point->y); + } + return std::make_pair(min, max); +} + void GenerateRandomPointDistribution(size_t num_points, double min, double max, vector& out_polyline, vector>& out_holes, vector& out_steiner) @@ -280,14 +329,11 @@ void GenerateRandomPointDistribution(size_t num_points, double min, double max, } } -void Init() +void Init(int window_width, int window_height) { - const int window_width = 800, - window_height = 600; - if (glfwInit() != GL_TRUE) ShutDown(1); - // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed + // width x height, 16 bit color, no depth, alpha or stencil buffers, windowed window = glfwCreateWindow(window_width, window_height, "Poly2Tri - C++", NULL, NULL); if (!window) ShutDown(1); @@ -373,7 +419,7 @@ void Draw(const double zoom) // reset zoom Point center = Point(cx, cy); - ResetZoom(zoom, center.x, center.y, 800, 600); + ResetZoom(zoom, center.x, center.y, (double)default_window_width, (double)default_window_height); for (int i = 0; i < triangles.size(); i++) { Triangle& t = *triangles[i]; @@ -414,7 +460,7 @@ void DrawMap(const double zoom) // reset zoom Point center = Point(cx, cy); - ResetZoom(zoom, center.x, center.y, 800, 600); + ResetZoom(zoom, center.x, center.y, (double)default_window_width, (double)default_window_height); list::iterator it; for (it = map.begin(); it != map.end(); it++) { @@ -454,8 +500,6 @@ void ConstrainedColor(bool constrain) } } - - double StringToDouble(const std::string& s) { std::istringstream i(s);