diff --git a/Display.cpp b/Display.cpp index 3596edb..f18b702 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,16 +1,67 @@ -// make sure sfml is installed: -// linux - sudo apt-get install libsfml-dev -// windows - manual dl from https://www.sfml-dev.org/download.php -#include #include +#include +#include #include "Display.h" #include "Point.h" +#include "Utility.h" +#define RADIUS 10.f + +Display::Display() +{ + if (!m_font.loadFromFile("arial.ttf")) + { + std::cerr << "font arial.ttf could not be loaded!" << std::endl; + } + + m_textStatus.setPosition(OFFSET, HEIGHT - 2*OFFSET); + m_textStatus.setFont(m_font); + m_textStatus.setString("initializing..."); + m_textStatus.setCharacterSize(12); + m_textStatus.setFillColor(sf::Color::Black); +} + +void Display::drawPoint(sf::RenderWindow& window, size_t index) +{ + Point &pt = m_points[index]; + sf::CircleShape shape(RADIUS); + //shape.setOrigin(RADIUS, RADIUS); // handle with origin or manually calc position + shape.setPosition(pt.x() - RADIUS, pt.y() - RADIUS); + shape.setFillColor(sf::Color::Green); + shape.setOutlineThickness(1.f); + shape.setOutlineColor(sf::Color::Black); + window.draw(shape); + + sf::Text label; + label.setPosition(pt.x() - RADIUS/2, pt.y() - RADIUS/2 - 3); + label.setFont(m_font); + label.setString(std::to_string(index)); + label.setCharacterSize(12); + label.setFillColor(sf::Color::Black); + window.draw(label); +} + +// multiple options possible: +// a) draw every frame, using elapsed time for updates +// --> not really needed because we have no animations... also uses a lot of performance +// b) checking every frame if elapsed time since last tick is larger than a specified offset, then draw the field +// --> mostly doing nothing but still uses a lot of performance O_o +// c) just start a simple (c++11 <3) non-busy sleep +// --> may delay user input / events but don't care atm :p void Display::show() { - sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "SFML works!"); + sf::ContextSettings settings; + settings.antialiasingLevel = 4; + + sf::RenderWindow window(sf::VideoMode(WIDTH, HEIGHT), "ALGO Prog2: Quickhull - visualization", sf::Style::Default, settings); + // b) + //window.setFramerateLimit(0.2); + + //sf::Clock clock; + //sf::Time timeSinceLastUpdate = sf::Time::Zero; + //sf::Time frameTime = sf::seconds(2); //sf::seconds(1.f / 60.f) while (window.isOpen()) { sf::Event event; @@ -20,18 +71,95 @@ void Display::show() window.close(); } - window.clear(); - for (auto &pt : m_points) + std::cout << "entering gameloop" << std::endl; + + /* b) + timeSinceLastUpdate += clock.restart(); + // only handle every few seconds because we need no animations + if (timeSinceLastUpdate > frameTime) { - sf::CircleShape shape(10.f); - shape.setPosition(pt.x(), pt.y()); - shape.setFillColor(sf::Color::Green); - window.draw(shape); + // start by getting the most left and right point + timeSinceLastUpdate -= frameTime; + }*/ + + // a) + //update(elapsed); + update(); + + window.clear(sf::Color::White); + + // TODO: refactor -> parse into sf::Vertices or Shapes + // always print remaining points + size_t points = m_points.size(); + for (size_t i = 0; i < points; ++i) + { + drawPoint(window, i); } + + // draw already calculated hull + //if (step >= 1) + { + //window.draw(&m_hull[0], m_hull.size(), sf::Lines); + window.draw(&m_hull[0], m_hull.getVertexCount(), m_hull.getPrimitiveType()); + } + + window.draw(m_textStatus); + window.display(); + + // c) + // choose a simple sleep + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); } } +void Display::update() +{ + // TODO: maybe include Akl–Toussaint heuristic first? + // https://en.wikipedia.org/wiki/Convex_hull_algorithms#Akl%E2%80%93Toussaint_heuristic + if (m_curStep == 1) + { + // first step: select min - max x coordinates + m_textStatus.setString("step " + std::to_string(m_curStep) + ": select min - max x coordinates..."); + std::pair minmax = getMinMaxX(m_points); + std::cout << "min: " << minmax.first.x() << ", " << minmax.first.y() << + ", max: " << minmax.second.x() << ", " << minmax.second.y() << std::endl; + + m_hull.setPrimitiveType(sf::Lines); + m_hull.append(sf::Vertex(sf::Vector2f(minmax.first.x(), minmax.first.y()), sf::Color::Blue)); + m_hull.append(sf::Vertex(sf::Vector2f(minmax.second.x(), minmax.second.y()), sf::Color::Blue)); + } + else if (m_curStep == 2) + { + // second step: split board and find furthest point + m_textStatus.setString("step " + std::to_string(m_curStep) + ": split board and find furthest point..."); + } + else if (m_curStep == 3) + { + // third step: draw triangle, remove inner points + m_textStatus.setString("step " + std::to_string(m_curStep) + ": draw triangle, remove inner points..."); + } + else if (m_curStep == 4) + { + // fourth step: remove inner points + m_textStatus.setString("step " + std::to_string(m_curStep) + ": remove inner points..."); + } + else if (m_curStep == 5) + { + // fourth step: remove inner points + m_textStatus.setString("step " + std::to_string(m_curStep) + ": finished calculating convex hull"); + } + + m_curStep++; + // if finished removing inner points and there are still points left -> repeat from step 2 + // TODO: + if (m_curStep == 5 && m_points.size() > 0) + { + m_curStep = 2; + } + +} + void Display::setData(std::vector pts) { m_points = pts; diff --git a/Display.h b/Display.h index 9ab88ca..a4cb5d4 100644 --- a/Display.h +++ b/Display.h @@ -1,17 +1,37 @@ #pragma once +#ifndef DISPLAY_H + +// make sure sfml is installed: +// linux - sudo apt-get install libsfml-dev +// windows - manual dl from https://www.sfml-dev.org/download.php +#include class Point; +#define OFFSET 10 #define WIDTH 800 #define HEIGHT 600 class Display { private: + sf::Font m_font; + sf::Text m_textStatus; + std::vector m_points; + //std::vector m_hull; + sf::VertexArray m_hull; + + void drawPoint(sf::RenderWindow &, size_t); + + int m_curStep = 0; + void update(); public: + Display(); + void show(); void setData (std::vector); -}; \ No newline at end of file +}; +#endif // DISPLAY_H \ No newline at end of file diff --git a/README.md b/README.md index 1d99016..98f163f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # quickhull +## TODO: + +- Point class + + - adding "features" such as "IsInTriangle", ... ? + + - direct member access instead of getters? + diff --git a/arial.ttf b/arial.ttf new file mode 100644 index 0000000..ff0815c Binary files /dev/null and b/arial.ttf differ