merged performance into main -> now used vor vis and perf mode; adding param akl for heuristic
This commit is contained in:
parent
bda1158e7f
commit
1c73b14f24
@ -7,7 +7,7 @@
|
|||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
#include "Utility.h"
|
#include "Utility.h"
|
||||||
|
|
||||||
Display::Display (const std::vector<Point> &pts, int stepSize) : m_stepSize(stepSize)
|
Display::Display (const std::vector<Point> &pts, int stepSize, bool akl) : m_stepSize(stepSize), m_useAkl(akl)
|
||||||
{
|
{
|
||||||
if (!m_font.loadFromFile("Resources/LiberationSans-Regular.ttf"))
|
if (!m_font.loadFromFile("Resources/LiberationSans-Regular.ttf"))
|
||||||
{
|
{
|
||||||
@ -100,9 +100,6 @@ void Display::show()
|
|||||||
|
|
||||||
void Display::update ()
|
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
|
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)
|
if (m_stepSize == 0 && curStep > 0)
|
||||||
{
|
{
|
||||||
@ -117,8 +114,7 @@ void Display::update ()
|
|||||||
m_textStatus.setString(text + "select min - max x coordinates...");
|
m_textStatus.setString(text + "select min - max x coordinates...");
|
||||||
|
|
||||||
// if use Akl–Toussaint heuristic
|
// if use Akl–Toussaint heuristic
|
||||||
bool useAkl = false;
|
if (m_useAkl)
|
||||||
if (useAkl)
|
|
||||||
{
|
{
|
||||||
sf::Vector2f topLeft(WIDTH, HEIGHT);
|
sf::Vector2f topLeft(WIDTH, HEIGHT);
|
||||||
sf::Vector2f topRight(0, HEIGHT);
|
sf::Vector2f topRight(0, HEIGHT);
|
||||||
|
@ -20,6 +20,8 @@ class Display
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int m_stepSize;
|
int m_stepSize;
|
||||||
|
bool m_useAkl;
|
||||||
|
|
||||||
sf::Font m_font;
|
sf::Font m_font;
|
||||||
sf::Text m_textStatus;
|
sf::Text m_textStatus;
|
||||||
|
|
||||||
@ -46,7 +48,7 @@ private:
|
|||||||
void render(sf::RenderWindow &);
|
void render(sf::RenderWindow &);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Display(const std::vector<Point> &, int stepSize = 0);
|
Display(const std::vector<Point> &, int stepSize = 0, bool akl = false);
|
||||||
|
|
||||||
void show();
|
void show();
|
||||||
};
|
};
|
||||||
|
@ -5,11 +5,6 @@
|
|||||||
|
|
||||||
class NumberGenerator
|
class NumberGenerator
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
static const int OFFSET = 0;
|
|
||||||
static const int WIDTH = 700;
|
|
||||||
static const int HEIGHT = 700;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::list<Point> get_random_numbers(int valCount)
|
static std::list<Point> get_random_numbers(int valCount)
|
||||||
{
|
{
|
||||||
@ -35,7 +30,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::list<Point> points;
|
std::list<Point> points;
|
||||||
|
|
||||||
float diff = (2.f * HEIGHT / valCount);
|
float diff = (2.f * HEIGHT/valCount);
|
||||||
|
|
||||||
float x = 0;
|
float x = 0;
|
||||||
float y = 0;
|
float y = 0;
|
||||||
@ -54,7 +49,7 @@ public:
|
|||||||
{
|
{
|
||||||
std::list<Point> points;
|
std::list<Point> points;
|
||||||
|
|
||||||
float rad = HEIGHT / 2; //8.0f;
|
float rad = HEIGHT/2;
|
||||||
float deg = (float)(2 * 3.14159 / valCount);
|
float deg = (float)(2 * 3.14159 / valCount);
|
||||||
|
|
||||||
float x = 0;
|
float x = 0;
|
||||||
|
62
Quickhull.h
62
Quickhull.h
@ -3,16 +3,72 @@
|
|||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Display.h"
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
#include "Line.h"
|
//#include "Line.h"
|
||||||
#include "Triangle.h"
|
#include "Triangle.h"
|
||||||
|
|
||||||
class Quickhull
|
class Quickhull
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void get_hull(std::list<Point> input, std::list<Point> &output)
|
static void run(std::list<Point> points, std::list<Point>& 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<double, std::milli>(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<Point> input, std::list<Point> &output)
|
||||||
{
|
{
|
||||||
// Get leftmost and rightmost point
|
// Get leftmost and rightmost point
|
||||||
Point leftmost(INFINITY, 0.0), rightmost(-INFINITY, 0.0);
|
Point leftmost(INFINITY, 0.0), rightmost(-INFINITY, 0.0);
|
||||||
|
100
main.cpp
100
main.cpp
@ -4,74 +4,62 @@
|
|||||||
#include <ctime> // time
|
#include <ctime> // time
|
||||||
#include <cstring> // strcmp
|
#include <cstring> // strcmp
|
||||||
#include <vector> // TODO: or use arrays for maximum performance?
|
#include <vector> // TODO: or use arrays for maximum performance?
|
||||||
|
#include <list> // TODO: replace vector with list for easier insertion!
|
||||||
|
|
||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
|
#include "NumberGenerator.h"
|
||||||
#include "Point.h"
|
#include "Point.h"
|
||||||
|
#include "Quickhull.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?
|
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
// read program arguments
|
// read program arguments
|
||||||
// -v mode with enabled visualization
|
// -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 <filename> read random numbers from file
|
// -f <filename> read random numbers from file
|
||||||
|
// -rngCount <count> generates count random float values
|
||||||
|
// -rngMode <mode> 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 <size> time between autosteps; if 0 or not provided -> manual steps
|
// -stepsize <size> time between autosteps; if 0 or not provided -> manual steps
|
||||||
// TODO: care a little more <3
|
// TODO: care a little more <3
|
||||||
int stepSize = 0;
|
int stepSize = 0;
|
||||||
|
int valCount = 1000000;
|
||||||
|
int rngMode = 1;
|
||||||
std::string fileRnd = "";
|
std::string fileRnd = "";
|
||||||
bool vis = false;
|
bool vis = false;
|
||||||
|
bool akl = false;
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
{
|
{
|
||||||
if (strcmp(argv[i], "-v") == 0) vis = true;
|
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], "-stepsize") == 0) stepSize = std::stoi(argv[i + 1]);
|
||||||
else if (strcmp(argv[i], "-f") == 0) fileRnd = 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::list<Point> points;
|
||||||
std::vector<Point> points;
|
|
||||||
if (fileRnd.empty()) // generate random numbers
|
if (fileRnd.empty()) // generate random numbers
|
||||||
{
|
{
|
||||||
std::cout << "generating random numbers..." << std::endl;
|
std::cout << "generating " << valCount << " random numbers for mode " << rngMode << "..." << std::endl;
|
||||||
//srand(static_cast <unsigned> (time(0)));
|
if (rngMode == 1)
|
||||||
srand(static_cast <unsigned> (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)
|
|
||||||
{
|
{
|
||||||
// 1) random generation
|
points = NumberGenerator::get_random_numbers(valCount);
|
||||||
//x = OFFSET + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (WIDTH - OFFSET)));
|
|
||||||
//y = OFFSET + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (HEIGHT - OFFSET)));
|
|
||||||
x = OFFSET + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (WIDTH - 2*OFFSET)));
|
|
||||||
y = OFFSET + static_cast <float> (rand()) / (static_cast <float> (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));
|
|
||||||
}
|
}
|
||||||
|
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
|
else // read random numbers
|
||||||
{
|
{
|
||||||
std::cout << "reading random numbers from file: " << fileRnd << "..." << std::endl;
|
std::cout << "reading random numbers from file: " << fileRnd << "..." << std::endl;
|
||||||
@ -102,22 +90,32 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// debug print points
|
#ifdef _DEBUG
|
||||||
for (Point& pt : points)
|
/*for (Point& pt : points)
|
||||||
{
|
{
|
||||||
std::cout << "pt: " << pt.x() << ", " << pt.y() << std::endl;
|
std::cout << "pt: " << pt.x() << ", " << pt.y() << std::endl;
|
||||||
}
|
}*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TEST to check SFML coordinate system
|
||||||
|
//points.push_back(Point(0, 0));
|
||||||
|
|
||||||
if (vis)
|
if (vis)
|
||||||
{
|
{
|
||||||
// TEST to check SFML coordinate system
|
// TODO: replace implementation to use list instead of vector
|
||||||
//points.push_back(Point(0, 0));
|
std::vector<Point> v_points;
|
||||||
|
for (Point const& pt : points)
|
||||||
|
{
|
||||||
|
v_points.push_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
Display display(points, stepSize);
|
Display display(v_points, stepSize, akl);
|
||||||
display.show();
|
display.show();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
std::cout << "any key to exit...";
|
{
|
||||||
std::cin.get();
|
std::list<Point> hull;
|
||||||
|
Quickhull::run(points, hull, akl);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user