#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::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; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } std::cout << "entering gameloop" << std::endl; /* b) timeSinceLastUpdate += clock.restart(); // only handle every few seconds because we need no animations if (timeSinceLastUpdate > frameTime) { // 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; }