diff --git a/Display.cpp b/Display.cpp index f245179..f4a9005 100644 --- a/Display.cpp +++ b/Display.cpp @@ -7,7 +7,7 @@ #include "Point.h" #include "Utility.h" -Display::Display (const std::vector &pts, int stepSize) : m_stepSize(stepSize) +Display::Display (const std::vector &pts, int stepSize, bool akl) : m_stepSize(stepSize), m_useAkl(akl) { if (!m_font.loadFromFile("Resources/LiberationSans-Regular.ttf")) { @@ -100,9 +100,6 @@ void Display::show() void Display::update () { - // TODO: maybe include Akl–Toussaint heuristic first? - // https://en.wikipedia.org/wiki/Convex_hull_algorithms#Akl%E2%80%93Toussaint_heuristic - unsigned int curStep = (m_step > 5) ? ((m_step - 2) % 4 + 2) : (m_step % 6); // skip init and first step after first run if (m_stepSize == 0 && curStep > 0) { @@ -117,8 +114,7 @@ void Display::update () m_textStatus.setString(text + "select min - max x coordinates..."); // if use Akl–Toussaint heuristic - bool useAkl = false; - if (useAkl) + if (m_useAkl) { sf::Vector2f topLeft(WIDTH, HEIGHT); sf::Vector2f topRight(0, HEIGHT); diff --git a/Display.h b/Display.h index 9a7f53a..9e06985 100644 --- a/Display.h +++ b/Display.h @@ -20,6 +20,8 @@ class Display { private: int m_stepSize; + bool m_useAkl; + sf::Font m_font; sf::Text m_textStatus; @@ -46,7 +48,7 @@ private: void render(sf::RenderWindow &); public: - Display(const std::vector &, int stepSize = 0); + Display(const std::vector &, int stepSize = 0, bool akl = false); void show(); }; diff --git a/NumberGenerator.h b/NumberGenerator.h index 1628dc5..92861f7 100644 --- a/NumberGenerator.h +++ b/NumberGenerator.h @@ -5,11 +5,6 @@ class NumberGenerator { -private: - static const int OFFSET = 0; - static const int WIDTH = 700; - static const int HEIGHT = 700; - public: static std::list get_random_numbers(int valCount) { @@ -35,7 +30,7 @@ public: { std::list points; - float diff = (2.f * HEIGHT / valCount); + float diff = (2.f * HEIGHT/valCount); float x = 0; float y = 0; @@ -54,7 +49,7 @@ public: { std::list points; - float rad = HEIGHT / 2; //8.0f; + float rad = HEIGHT/2; float deg = (float)(2 * 3.14159 / valCount); float x = 0; diff --git a/Quickhull.h b/Quickhull.h index 94c61b2..4b76fbb 100644 --- a/Quickhull.h +++ b/Quickhull.h @@ -3,16 +3,72 @@ #include #include +#include +#include - +#include "Display.h" #include "Point.h" -#include "Line.h" +//#include "Line.h" #include "Triangle.h" class Quickhull { public: - static void get_hull(std::list input, std::list &output) + static void run(std::list points, std::list& hull, bool akl) + { + auto start = std::chrono::high_resolution_clock::now(); + std::cout << "running quickhull perf mode..." << std::endl; + + Quickhull::get_hull(points, hull); + + auto diff = std::chrono::duration(std::chrono::high_resolution_clock::now() - start); + std::cout << "time spent: " << diff.count() << "ms" << std::endl; // shit runs about 120 milliseconds for 1Mio numbers + + // showing points in window after calculation + // create the window + sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "ALGO Prog2: Quickhull - performance"); + + sf::CircleShape normal_p(2); + normal_p.setFillColor(sf::Color(250, 250, 250)); + + sf::CircleShape hull_p(2); + hull_p.setFillColor(sf::Color(250, 100, 50)); + + // run the program as long as the window is open + while (window.isOpen()) + { + // check all the window's events that were triggered since the last iteration of the loop + sf::Event event; + while (window.pollEvent(event)) + { + // "close requested" event: we close the window + if (event.type == sf::Event::Closed) + window.close(); + } + + // clear the window with black color + window.clear(sf::Color::Black); + + // Draw all points + for (const Point& point : points) + { + normal_p.setPosition(point.x(), point.y()); + window.draw(normal_p); + } + + // Draw hull points + for (const Point& point : hull) + { + hull_p.setPosition(point.x(), point.y()); + window.draw(hull_p); + } + + // end the current frame + window.display(); + } + } + + static void get_hull(std::list input, std::list &output) { // Get leftmost and rightmost point Point leftmost(INFINITY, 0.0), rightmost(-INFINITY, 0.0); diff --git a/main.cpp b/main.cpp index 2e24203..02d42c0 100644 --- a/main.cpp +++ b/main.cpp @@ -4,74 +4,62 @@ #include // time #include // strcmp #include // TODO: or use arrays for maximum performance? +#include // TODO: replace vector with list for easier insertion! #include "Display.h" +#include "NumberGenerator.h" #include "Point.h" - -// TODOs: -// - use SFML vec2 instead of Point class -// - calc min and max points for x, y -// *) just a loop and save/override points -> maybe in Data Block? -// *) std::minmax_element for x, y -> not saving just temp draw -// https://en.cppreference.com/w/cpp/algorithm/minmax_element -// - actual algorithm :p -// - architecture: -// # vis in own thread, calls "lib" functions? -// # seperate implementation for vis and perf? +#include "Quickhull.h" int main (int argc, char **argv) { // read program arguments // -v mode with enabled visualization + // -akl using Akl-Toussaint heuristic beforehand + // https://en.wikipedia.org/wiki/Convex_hull_algorithms#Akl%E2%80%93Toussaint_heuristic // -f read random numbers from file + // -rngCount generates count random float values + // -rngMode if generating float values this specifies the mode: + // 1. random numbers in screen range + // 2. numbers are ordered as rectangle + // 3. numbers are ordered as circle around screen center // -stepsize time between autosteps; if 0 or not provided -> manual steps // TODO: care a little more <3 int stepSize = 0; + int valCount = 1000000; + int rngMode = 1; std::string fileRnd = ""; bool vis = false; + bool akl = false; for (int i = 0; i < argc; ++i) { if (strcmp(argv[i], "-v") == 0) vis = true; + else if (strcmp(argv[i], "-akl") == 0) akl = true; else if (strcmp(argv[i], "-stepsize") == 0) stepSize = std::stoi(argv[i + 1]); else if (strcmp(argv[i], "-f") == 0) fileRnd = argv[i + 1]; + else if (strcmp(argv[i], "-rngCount") == 0) valCount = std::stoi(argv[i + 1]); + else if (strcmp(argv[i], "-rngMode") == 0) rngMode = std::stoi(argv[i + 1]); } - int valCount = 10; - std::vector points; + std::list points; if (fileRnd.empty()) // generate random numbers { - std::cout << "generating random numbers..." << std::endl; - //srand(static_cast (time(0))); - srand(static_cast (0)); // fixed seed for testing - - // 2) rectangle - //float diff = (2.f * HEIGHT / valCount); - - // 3) circle - //float rad = HEIGHT / 2; //8.0f; - //float deg = (float)(2 * 3.14159 / valCount); - - float x = 0; - float y = 0; - for (int i = 0; i < valCount; ++i) + std::cout << "generating " << valCount << " random numbers for mode " << rngMode << "..." << std::endl; + if (rngMode == 1) { - // 1) random generation - //x = OFFSET + static_cast (rand()) / (static_cast (RAND_MAX / (WIDTH - OFFSET))); - //y = OFFSET + static_cast (rand()) / (static_cast (RAND_MAX / (HEIGHT - OFFSET))); - x = OFFSET + static_cast (rand()) / (static_cast (RAND_MAX / (WIDTH - 2*OFFSET))); - y = OFFSET + static_cast (rand()) / (static_cast (RAND_MAX / (HEIGHT - 2*OFFSET))); - - // 2) rectangle - //x = (i%2 == 0) ? OFFSET : WIDTH - OFFSET; - //y = diff/2 + (i/2) * diff; - - // 3) position in circle around center, x/y plane - //x = WIDTH/2 + rad * cosf(i * deg); - //y = HEIGHT/2 + rad * sinf(i * deg); - - points.push_back(Point(x, y)); + points = NumberGenerator::get_random_numbers(valCount); } + else if (rngMode == 2) + { + points = NumberGenerator::get_rectangle_numbers(valCount); + } + else if (rngMode == 3) + { + points = NumberGenerator::get_circle_numbers(valCount); + } + else throw "unspecified rng Mode"; // TODO: could handle in parse args } + // TODO: move into NumberGenerator? else // read random numbers { std::cout << "reading random numbers from file: " << fileRnd << "..." << std::endl; @@ -102,22 +90,32 @@ int main (int argc, char **argv) } } - // debug print points - for (Point& pt : points) +#ifdef _DEBUG + /*for (Point& pt : points) { std::cout << "pt: " << pt.x() << ", " << pt.y() << std::endl; - } + }*/ +#endif + + // TEST to check SFML coordinate system + //points.push_back(Point(0, 0)); if (vis) { - // TEST to check SFML coordinate system - //points.push_back(Point(0, 0)); + // TODO: replace implementation to use list instead of vector + std::vector v_points; + for (Point const& pt : points) + { + v_points.push_back(pt); + } - Display display(points, stepSize); + Display display(v_points, stepSize, akl); display.show(); } - - std::cout << "any key to exit..."; - std::cin.get(); + else + { + std::list hull; + Quickhull::run(points, hull, akl); + } return 0; } \ No newline at end of file