Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "application.h"
- #include "scene_laba2.h"
- #include <iostream>
- #include <GL/glew.h>
- #include "command.h"
- #include <queue>
- #include <map>
- #include <functional>
- std::stack<std::shared_ptr<ICommand>> m_command_queue;
- int m_points_to_show;
- using namespace std;
- template<typename T>
- struct ListEntry {
- ListEntry() {
- next = prev = nullptr;
- }
- T value;
- ListEntry *next;
- ListEntry *prev;
- };
- template<typename T>
- class ListEntryIterator {
- public:
- bool isNull() {
- return ptr == nullptr;
- }
- ListEntryIterator operator++(int) {
- ptr = ptr->next;
- return *this;
- }
- ListEntryIterator operator--(int) {
- ptr = ptr->prev;
- return *this;
- }
- ListEntryIterator(ListEntry<T>* p) {
- ptr = p;
- }
- ListEntryIterator() {
- ptr = nullptr;
- }
- bool operator==(ListEntryIterator<T> b) {
- return this->ptr == b.ptr;
- }
- bool operator!=(ListEntryIterator<T> b) {
- return !(*this == b);
- }
- T& operator*() {
- if (!isNull()) {
- return ptr->value;
- } else {
- throw "Exception: error iterator to null";
- }
- }
- ListEntry<T>* ptr;
- };
- template<typename T>
- class List {
- public:
- ListEntryIterator<T> find(T value) {
- if (!front) {
- return ListEntryIterator<T>(nullptr);
- }
- auto i = getFront();
- do {
- if ((*i) == value) {
- return i;
- }
- i++;
- } while(i != getFront());
- return ListEntryIterator<T>(nullptr);
- }
- /* void erase(T value) {
- if (!front) {
- return;
- }
- auto i = front;
- do {
- if (i.next && i.next.value == value) {
- auto tmp = i.next;
- i = tmp.next;
- tmp.next.prev = i;
- delete tmp;
- return;
- }
- i = i.next;
- } while(i != front);
- return;
- }*/
- bool push_back(T value) {
- /* if (test.find(value) != test.end()) {
- return false;
- }
- */
- ListEntry<T>* elem = new ListEntry<T>;
- elem->value = value;
- elem->next = elem->prev = nullptr;
- if (front == nullptr) {
- front = elem;
- back = elem;
- elem->next = elem->prev = elem;
- } else {
- back->next = elem;
- elem->prev = back;
- elem->next = front;
- front->prev = elem;
- back = elem;
- }
- size++;
- return true;
- }
- bool push_after(T after, T value) {
- auto it = front;
- if (!it) {
- return false;
- }
- do {
- if (it->value == after) {
- ListEntry<T>* elem = new ListEntry<T>;
- elem->value = value;
- elem->next = elem->prev = nullptr;
- auto tmp = it->next;
- it->next = elem;
- elem->prev = it;
- tmp->prev = it;
- elem->next = tmp;
- size++;
- return true;
- }
- it = it->next;
- } while (it != back);
- return false;
- }
- bool push_after(ListEntryIterator<T> after, T value) {
- if (after.isNull()) {
- return false;
- }
- auto it = after.ptr;
- ListEntry<T>* elem = new ListEntry<T>;
- elem->value = value;
- elem->next = elem->prev = nullptr;
- auto tmp = it->next;
- it->next = elem;
- elem->prev = it;
- tmp->prev = it;
- elem->next = tmp;
- size++;
- return true;
- }
- bool push_prev(ListEntryIterator<T> prev, T value) {
- if (prev.isNull()) {
- return false;
- }
- prev--;
- return push_after(prev, value);
- }
- vector<T> to_vector() {
- vector<T> res;
- auto it = getFront();
- do {
- res.push_back(*it);
- it++;
- } while(it != getFront());
- return res;
- }
- ListEntryIterator<T> getFront() {
- return {front};
- }
- ListEntryIterator<T> getBack() {
- return {back};
- }
- List() {
- front = back = nullptr;
- size = 0;
- }
- size_t getSize() { return size; }
- private:
- ListEntry<T>* front;
- ListEntry<T>* back;
- size_t size;
- //map<T, bool> test;
- };
- void Application::init() {
- m_running = false;
- m_fps = 0;
- m_window.open("Application", 1280, 720);
- m_window.onKeyboardKeyPress = delegate<void(Keyboard::Key)>(this, &Application::onKeyboardKeyPress);
- m_window.onWindowResize = delegate<void(int, int)>(this, &Application::onWindowResize);
- m_window.onMouseKeyPress = delegate<void(Mouse::Key)>(this, &Application::onMouseKeyPress);
- m_window.onMouseMove = delegate<void(int, int)>(this, &Application::onMouseMove);
- m_window.mouse.setMousePos(m_window.getWidth() / 2, m_window.getHeight() / 2);
- draw_insection = 0;
- m_points_to_show = 1;
- m_hole_it = m_hole_it2 = 0;
- m_polygon_swap = false;
- }
- void Application::deinit() {
- m_running = false;
- m_fps = 0;
- m_window.close();
- LibResouces::deinit();
- }
- typedef enum {
- SIMPLE, IN, OUT
- } Type;
- struct Connection {
- math::vec2 point;
- ListEntryIterator<Connection> to_list;
- Type type;
- Connection(math::vec2 p, Type t) {
- point = p;
- type = t;
- to_list = ListEntryIterator<Connection>(nullptr);
- }
- Connection(){
- point = {0, 0};
- type = SIMPLE;
- to_list = ListEntryIterator<Connection>(nullptr);
- }
- bool operator==(const math::vec2 point) const {
- return this->point == point;
- }
- bool operator==(const Connection a) const {
- return point == a.point;
- }
- bool operator!=(const Connection a) const {
- return point != a.point;
- }
- };
- class Polygon_list {
- public:
- List<Connection> boundary;
- vector<List<Connection>> holes;
- Polygon_list(const Polygon &p) {
- for (auto v : p.boundary) {
- boundary.push_back({v, SIMPLE});
- }
- for (int i = 0; i < p.holes.size(); i++) {
- holes.push_back(List<Connection>());
- for (auto v : p.holes[i]) {
- holes[i].push_back({v, SIMPLE});
- }
- }
- }
- };
- std::vector<math::vec2> global_in;
- std::vector<math::vec2> global_out;
- struct Insect {
- math::vec2 l1_s, l1_e, l2_s, l2_e;
- math::vec2 point;
- Type type;
- Insect(math::vec2 a_1, math::vec2 a_2, math::vec2 b_1, math::vec2 b_2,math::vec2 p, Type t) {
- l1_s = a_1;
- l1_e = a_2;
- l2_s = b_1;
- l2_e = b_2;
- point = p;
- type = t;
- }
- };
- bool updateList(List<Connection> &polygon1, List<Connection> &polygon2, bool in) { // возращает было ли хоть 1 пересечение
- vector<Connection> pol1 = polygon1.to_vector();
- vector<Connection> pol2 = polygon2.to_vector();
- vector<Insect> insection;
- bool yes = false;
- // Находим точки пересечения, пока классифицуем их как Simple
- for (int i = 0; i < pol1.size(); i++) {
- math::LineSegment2D l1(pol1[i].point, pol1[(i + 1 != pol1.size())? i + 1 : 0].point); // построили отрезок 1
- for (int j = 0; j < pol2.size(); j++) {
- math::vec2 start;
- math::vec2 end;
- math::LineSegment2D l2(pol2[j].point, pol2[(j + 1 != pol2.size())? j + 1 : 0].point); // построили отрезок 2
- if (math::LineSegment2D::intersect(l1, l2, start, end)) {
- if (start == end) {
- insection.push_back(Insect(pol1[i].point, pol1[(i + 1 != pol1.size())? i + 1 : 0].point, \
- pol2[j].point, pol2[(j + 1 != pol2.size())? j + 1 : 0].point, \
- start, SIMPLE));
- yes = true;
- }
- }
- }
- }
- // Вставляем точки пересечения в первый контур, попутно классифицируя их
- auto it = polygon1.getFront();
- do {
- vector<Insect*> vec;
- auto p1 = it;
- auto p2 = it; p2++;
- for (int i = 0; i < insection.size(); i++) {
- if (((*p1).point == insection[i].l1_s) && ((*p2).point == insection[i].l1_e)) {
- vec.push_back(&insection[i]);
- }
- }
- sort(vec.begin(), vec.end(),
- [&p1](const Insect* a, const Insect* b) -> bool {
- return ( math::length(a->point - (*p1).point) <= math::length(b->point - (*p1).point) );
- });
- for (auto v : vec) {
- in = !in;
- v->type = (in)? IN : OUT;
- polygon1.push_after(p1, {v->point, v->type});
- p1++;
- }
- it++;
- } while(it != polygon1.getFront());
- // Вставляем во второй контр, точки уже классифицированны на пред шаге
- it = polygon2.getFront();
- do {
- vector<Connection> vec;
- auto p1 = it;
- auto p2 = it; p2++;
- for (auto v : insection) {
- if (((*p1).point == v.l2_s) && ((*p2).point == v.l2_e)) {
- vec.push_back({v.point, v.type});
- }
- }
- sort(vec.begin(), vec.end(),
- [&p1](const Connection& a, const Connection b) -> bool {
- return ( math::length(a.point - (*p1).point) <= math::length(b.point - (*p1).point) );
- });
- for (auto v : vec) {
- polygon2.push_after(p1, v);
- p1++;
- }
- it++;
- } while(it != polygon2.getFront());
- // Связи одного контура с другим
- for (auto v : insection) {
- auto v1 = polygon1.find({v.point, v.type});
- auto v2 = polygon2.find({v.point, v.type});
- (*v1).to_list = v2;
- (*v2).to_list = v1;
- }
- return yes;
- }
- void updatePolygon(const Polygon& polygon1, const Polygon& polygon2, Polygon_list& out_polygon1, Polygon_list& out_polygon2, vector<vector<math::vec2>>& result, vector<bool>& holes_insection_1, vector<bool>& holes_insection_2) {
- Polygon_list pol1(polygon1);
- Polygon_list pol2(polygon2);
- vector<bool> test1(polygon1.holes.size()); // храним есть ли пересечение дыркок 1 контура с чем-нибудь
- vector<bool> test2(polygon2.holes.size()); // храним если ли пересечение дыркок 2 контура с чем-нибудь
- std::fill(test1.begin(), test1.end(), 0);
- std::fill(test2.begin(), test2.end(), 0);
- // polygon1.boundary
- bool yes = updateList(pol1.boundary, pol2.boundary, polygon2.pointInPolygon(polygon1.boundary[0]));
- bool yes_1 = yes; // пересечение первой границы с дырками
- for (int i = 0; i < pol2.holes.size(); i++) {
- auto& hole = pol2.holes[i];
- if (hole.getSize() >= 3) {
- bool intersection = updateList(pol1.boundary, hole, polygon2.pointInPolygon(polygon1.boundary[0]));
- test2[i] = test2[i] || intersection;
- yes_1 = yes_1 || intersection;
- }
- }
- // границы не пересекаются и второй полигон содержет точку первого
- if (yes_1 == false) {
- if (polygon2.pointInPolygon(polygon1.boundary[0])) { // возращаем границу 1
- result.push_back(polygon1.boundary);
- }
- }
- bool yes_2 = yes; // пересечение второй границы с дырками
- for (int i = 0; i < pol1.holes.size(); i++) {
- if (pol1.holes[i].getSize() >= 3) {
- bool intersection = updateList(pol1.holes[i], pol2.boundary, polygon2.pointInPolygon(polygon1.holes[i][0]));
- test1[i] = test1[i] || intersection;
- yes_2 = yes_2 || intersection;
- for (int j = 0; j < pol2.holes.size(); j++) {
- if (pol2.holes[j].getSize() >= 3) {
- bool intersection = updateList(pol1.holes[i], pol2.holes[j], polygon2.pointInPolygon(polygon1.holes[i][0]));
- test1[i] = test1[i] || intersection;
- test2[j] = test2[j] || intersection;
- }
- }
- }
- }
- // границы не пересекаются и первый полигон содержет точку второго
- if (!yes_2) {
- if (polygon1.pointInPolygon(polygon2.boundary[0])) { // возращаем границу 2
- result.push_back(polygon2.boundary);
- }
- }
- out_polygon1 = pol1;
- out_polygon2 = pol2;
- holes_insection_1 = test1;
- holes_insection_2 = test2;
- }
- vector<math::vec2> DEBUG_GLOBAL_IN, DEBUG_GLOBAL_OUT;
- vector<vector<math::vec2>> Application::algorithmWeilerAtherton(const Polygon &polygon1, const Polygon &polygon2) {
- /*
- * Тут уже выделили все точки и классифицировали их
- */
- DEBUG_GLOBAL_IN.clear();
- DEBUG_GLOBAL_OUT.clear();
- if (polygon1.boundary.size() <= 3 && polygon2.boundary.size() <= 3) {
- return vector<vector<math::vec2>>();
- }
- Polygon_list list1(polygon1), list2(polygon2);
- vector<vector<math::vec2>> result;
- vector<bool> test1;
- vector<bool> test2;
- updatePolygon(polygon1, polygon2, list1, list2, result, test1, test2);
- list<ListEntryIterator<Connection>> global_in;
- auto it = list1.boundary.getFront();
- do {
- if ((*it).type == IN) {
- global_in.push_back(it);
- DEBUG_GLOBAL_IN.push_back((*it).point);
- }
- if ((*it).type == OUT) {
- DEBUG_GLOBAL_OUT.push_back((*it).point);
- }
- it++;
- } while (it != list1.boundary.getFront());
- for (auto hole : list1.holes) {
- if (hole.getSize() >= 3) {
- auto it = hole.getFront();
- do {
- if ((*it).type == IN) {
- global_in.push_back(it);
- DEBUG_GLOBAL_IN.push_back((*it).point);
- }
- if ((*it).type == OUT) {
- DEBUG_GLOBAL_OUT.push_back((*it).point);
- }
- it++;
- } while (it != hole.getFront());
- }
- }
- /*
- Определение части обрабатываемого многоугольника, попавшей в окно выполняется следующим образом:
- Если не исчерпан список входных точек пересечения, то выбираем очередную входную точку.
- Двигаемся по вершинам отсекаемого многоугольника пока не обнаружится следующая точка пересечения;
- все пройденные точки, не включая прервавшую просмотр, заносим в результат;
- используя двухстороннюю связь точек пересечения, переключаемся на просмотр списка вершин окна.
- Двигаемся по вершинам окна до обнаружения следующей точки пересечения; все пройденные точки, не включая последнюю, прервавшую просмотр, заносим в результат.
- Используя двухстороннюю связь точек пересечения, переключаемся на список вершин обрабатываемого многоугольника.
- Эти действия повторяем пока не будет достигнута исходная вершина - очередная часть отсекаемого многоугольника,
- попавшая в окно, замкнулась. Переходим на выбор следующей входной точки в списке отсекаемого многоугольника.
- */
- int iter = result.size();// смещаемся, чтобы не задеть другие контура
- Timer time;
- time.start();
- while (global_in.size() > 0 && time.elapsedSec() < 1)
- {
- auto start = global_in.front();
- global_in.pop_front();
- auto it = start;
- result.push_back(vector<math::vec2>());
- do {
- for (; (*it).type != Type::OUT; it++) {
- result[iter].push_back((*it).point);
- }
- for (it = (*it).to_list; (*it).type != Type::IN; it++) {
- result[iter].push_back((*it).point);
- }
- it = (*it).to_list;
- auto f = std::find(global_in.begin(), global_in.end(), it);
- if (f != global_in.end()) {
- global_in.erase(f);
- }
- } while(start != it);
- iter++;
- }
- if (global_in.size() > 0) {
- cout << "TIME BREAK!" << endl;
- result.clear();
- return result;
- }
- for (int i = 0; i < result.size(); i++) {
- for (int j = 0; j < test1.size(); j++) {
- cout << test1.size() << endl;
- if (test1[j] == false) { // дырка ни с чем не пересекается
- if (polygon1.holes[j].size() >= 3) {
- bool in = true;
- for (auto v : polygon1.holes[j]) {
- in = in && math::pointInPolygon(v, result[i]);
- }
- if (in) { // и все точки лежат внутри результирующего контура
- result.push_back(polygon1.holes[j]); // добавляем дырку к выходу
- test1[j] = true;
- }
- } else {
- test1[j] = true;
- }
- }
- }
- for (int j = 0; j < test2.size(); j++) {
- if (test2[j] == false) { // дырка ни с чем не пересекается
- if (polygon2.holes[j].size() >= 3) {
- bool in = true;
- for (auto v : polygon2.holes[j]) {
- in = in && math::pointInPolygon(v, result[i]);
- }
- if (in) { // и все точки лежат внутри результирующего контура
- result.push_back(polygon2.holes[j]); // добавляем дырку к выходу
- test2[j] = true;
- }
- } else {
- test2[j] = true;
- }
- }
- }
- }
- return std::move(result);
- }
- //typedef enum {
- // SIMPLE, IN, OUT
- //} Type;
- //struct Connection {
- // math::vec2 point;
- // int index;
- // int to_list;
- // Type type;
- // bool operator==(const math::vec2 point) const {
- // return this->point == point;
- // }
- // bool operator==(const Connection a) const {
- // return point == a.point;
- // }
- // bool operator!=(const Connection a) const {
- // return point != a.point;
- // }
- //};
- //std::vector<math::vec2> global_in;
- //std::vector<math::vec2> global_out;
- //std::vector<Connection> updateList(const std::vector<math::vec2> &polygon1, const std::vector<math::vec2> &polygon2,
- // std::vector<int> &in_indices, std::vector<int> &out_indices, bool swap_in_out_type = false) {
- // // определим, лежит ли первая точка в контуре
- // global_in.clear();
- // global_out.clear();
- // bool in = math::pointInPolygon(polygon1[0], polygon2);
- // if (swap_in_out_type) {
- // in = !in;
- // }
- // // нашли все пересечения и запилили их в списки вершин
- // std::vector<Connection> result;
- // int iter = 0;
- // for (int i = 0; i < polygon1.size(); i++) {
- // result.push_back({polygon1[i], iter, 0, SIMPLE});
- // iter++;
- // std::vector<math::vec2> insection;
- // math::LineSegment2D l1(polygon1[i], polygon1[(i + 1 != polygon1.size())? i + 1 : 0]); // построили отрезок 1
- // for (int j = 0; j < polygon2.size(); j++) {
- // math::vec2 start;
- // math::vec2 end;
- // math::LineSegment2D l2(polygon2[j], polygon2[(j + 1 != polygon2.size())? j + 1 : 0]); // построили отрезок 2
- // if (math::LineSegment2D::intersect(l1, l2, start, end)) {
- // if (start == end) {
- // insection.push_back(start);
- // }
- // }
- // }
- // // имеем точки пересечений, надо их в правильном порядке добавить в список вершин первого
- // // сортировка по длинам не прошла (a - v0).len <= (b - v0).len
- // // пришлось сделать по параметрическому уравнению
- // // v(t) = v0 + t*direction
- // // отсюда t = (x-x0)/direction.x
- // // сортируя по t получаем все точки в порядке движения от i до i + 1 точки
- // math::vec2 direction = math::normalize(polygon1[(i + 1 != polygon1.size())? i + 1 : 0] - polygon1[i]);
- // sort(insection.begin(), insection.end(),
- // [&polygon1, &i, &direction](const math::vec2& a, const math::vec2 b) -> bool {
- // return ( ((a.x - polygon1[i].x) / direction.x) <= ((b.x - polygon1[i].x) / direction.x) );
- // });
- // for (auto v : insection) {
- // in = !in;
- // if (in) {
- // result.push_back({v, iter, 0, IN});
- // in_indices.push_back(iter);
- // global_in.push_back(v);
- // } else {
- // result.push_back({v, iter, 0, OUT});
- // out_indices.push_back(iter);
- // global_out.push_back(v);
- // }
- // iter++;
- // }
- // }
- // return std::move(result);
- //}
- //vector<vector<math::vec2>> Application::algorithmWeilerAtherton(const std::vector<math::vec2> &polygon1, const std::vector<math::vec2> &polygon2) {
- // if (polygon1.size() < 3 && polygon2.size() < 3) {
- // return vector<vector<math::vec2>>();
- // }
- // vector<vector<math::vec2>> result;
- // std::vector<Connection> lst1, lst2;
- // std::vector<int> lst1_in_indices;
- // std::vector<int> lst1_out_indices;
- // std::vector<int> lst2_in_indices;
- // std::vector<int> lst2_out_indices;
- // lst1 = updateList(polygon1, polygon2, lst1_in_indices, lst1_out_indices);
- // lst2 = updateList(polygon2, polygon1, lst2_in_indices, lst2_out_indices, true);
- // std::list<Connection> list_in;
- // // Расставляем связь точек пересечения и списков
- // for (auto i : lst1_in_indices) {
- // for (auto j : lst2_in_indices) {
- // if (lst1[i] == lst2[j]) {
- // lst1[i].to_list = lst2[j].index;
- // lst2[j].to_list = lst1[i].index;
- // LOG("IN (%f; %f) f_index: %d; s_index: %d type: %d\n", lst1[i].point.x, lst1[i].point.y, lst1[i].index, lst2[j].index, lst1[i].type == lst2[j].type);
- // list_in.push_back(lst1[i]);
- // }
- // }
- // }
- // for (auto i : lst1_out_indices) {
- // for (auto j : lst2_out_indices) {
- // if (lst1[i] == lst2[j]) {
- // lst1[i].to_list = lst2[j].index;
- // lst2[j].to_list = lst1[i].index;
- // LOG("OUT (%f; %f) f_index: %d; s_index: %d type: %d\n", lst1[i].point.x, lst1[i].point.y, lst1[i].index, lst2[j].index, lst1[i].type == lst2[j].type);
- // }
- // }
- // }
- // // имеем 2 списка вершин и список вершин на вход и выход
- // if (lst1_in_indices.size() == 0 && lst1_out_indices.size() == 0) { // либо один вложен в другой, либо не пересекаются. Возьмём по 1 точке и определим это.
- // bool in1 = math::pointInPolygon(polygon1[0], polygon2);
- // bool in2 = math::pointInPolygon(polygon2[0], polygon1);
- // if (!in1 && !in2) { // пересечение нулевое.
- // return result;
- // }
- // if (in1) { // первый внутри второго
- // result.push_back(polygon1);
- // return result;
- // } else { // второй внутри первого
- // result.push_back(polygon2);
- // return result;
- // }
- // }
- ///*
- // Определение части обрабатываемого многоугольника, попавшей в окно выполняется следующим образом:
- // Если не исчерпан список входных точек пересечения, то выбираем очередную входную точку.
- // Двигаемся по вершинам отсекаемого многоугольника пока не обнаружится следующая точка пересечения;
- // все пройденные точки, не включая прервавшую просмотр, заносим в результат;
- // используя двухстороннюю связь точек пересечения, переключаемся на просмотр списка вершин окна.
- // Двигаемся по вершинам окна до обнаружения следующей точки пересечения; все пройденные точки, не включая последнюю, прервавшую просмотр, заносим в результат.
- // Используя двухстороннюю связь точек пересечения, переключаемся на список вершин обрабатываемого многоугольника.
- // Эти действия повторяем пока не будет достигнута исходная вершина - очередная часть отсекаемого многоугольника,
- // попавшая в окно, замкнулась. Переходим на выбор следующей входной точки в списке отсекаемого многоугольника.
- //*/
- // int iter = 0;
- // while (list_in.size() > 0) {
- // auto v1 = list_in.front().index;
- // list_in.pop_front();
- // auto v2 = v1;
- // result.push_back(vector<math::vec2>());
- // do {
- // int i = v2;
- // for (; lst1[i].type != Type::OUT; i = (i + 1) % lst1.size()) {
- // result[iter].push_back(lst1[i].point);
- // cout << lst1[i].point << endl;
- // }
- // int j = lst1[i].to_list;
- // for (; lst2[j].type != Type::IN; j = (j + 1) % lst2.size()) {
- // result[iter].push_back(lst2[j].point);
- // cout << lst1[i].point << endl;
- // }
- // auto it = std::find(list_in.begin(), list_in.end(), lst2[j]);
- // if (it != list_in.end()) {
- // list_in.erase(it);
- // }
- // v2 = lst2[j].to_list;
- // } while(v1 != v2);
- // result[iter].push_back(lst1[v1].point);
- // iter++;
- // }
- // return std::move(result);
- //}
- void Polygon::draw(math::vec4 color) {
- glBegin(GL_LINE_STRIP);
- if (this->boundary.size() > 0) {
- for (int i = 0; i < this->boundary.size(); i++) {
- glColor4fv(math::value_ptr(color - ((float)(i)/50)*color));
- glVertex2fv(math::value_ptr(this->boundary[i]));
- }
- glVertex2fv(math::value_ptr(this->boundary[0]));
- }
- glEnd();
- for (auto hole : holes) {
- glBegin(GL_LINE_STRIP);
- if (hole.size() > 0) {
- for (int i = 0; i < hole.size(); i++) {
- glColor4fv(math::value_ptr(color - ((float)(i)/50)*color));
- glVertex2fv(math::value_ptr(hole[i]));
- }
- glVertex2fv(math::value_ptr(hole[0]));
- }
- glEnd();
- }
- }
- void Application::render(float deltaTime) {
- glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- polygon1.draw({0, 1, 0, 1});
- polygon2.draw({0, 1, 1, 0});
- if (draw_insection) {
- glColor4f(0, 0, 1, 1);
- glPointSize(6);
- if (insection.size() > 0) {
- for (int j = 0; j < insection.size(); j++) {
- if (insection[j].size() > 0) {
- glBegin(GL_LINE_STRIP);
- for (int i = 0; i <= insection[j].size() && i < m_points_to_show; i++) {
- int w = i % insection[j].size();
- glVertex2fv(math::value_ptr(insection[j][w]));
- }
- glEnd();
- }
- }
- }
- glPointSize(6);
- glColor4f(1, 0, 0 ,1);
- glBegin(GL_POINTS);
- for (auto v : DEBUG_GLOBAL_IN) {
- glVertex2fv(math::value_ptr(v));
- }
- glEnd();
- glColor4f(0, 1, 0 ,1);
- glBegin(GL_POINTS);
- for (auto v : DEBUG_GLOBAL_OUT) {
- glVertex2fv(math::value_ptr(v));
- }
- glEnd();
- }
- glFlush();
- }
- void Application::run() {
- m_running = true;
- m_timer.start();
- glDisable(GL_DEPTH_TEST);
- onWindowResize(m_window.getHeight(), m_window.getWidth());
- while(m_running) {
- m_frameIntervalTimer.start();
- render(m_frameIntervalValue);
- m_window.flush();
- m_window.pullEvents();
- m_frameIntervalValue = m_frameIntervalTimer.elapsedMilliSec();
- m_fps++;
- int time = m_timer.elapsedSec();
- if (time >= 2.0) {
- m_window.setTitle(std::string("Application: FPS = ") + std::to_string(m_fps / time));
- m_fps = 0;
- m_timer.start();
- }
- }
- }
- void m_command_queue_execute(std::shared_ptr<ICommand> com) {
- com->execute();
- m_command_queue.push(std::move(com));
- }
- void m_command_queue_undo() {
- if (m_command_queue.size() > 0) {
- m_command_queue.top()->undo();
- m_command_queue.pop();
- }
- }
- void Application::onMouseKeyPress(Mouse::Key key) {
- math::vec2 pos = {m_window.mouse.getX(), m_window.mouse.getY()};
- if (m_window.mouse.isKeyPressed(Mouse::Left)) {
- LOG("polygon1.push_back (%d, %d)\n", pos.x, pos.y);
- std::shared_ptr<Command> com(new Command);
- com->m_execute = std::bind([&pos, this](){ polygon1.boundary.push_back(pos); });
- com->m_undo = std::bind([this](){ polygon1.boundary.pop_back(); });
- m_command_queue_execute(com);
- m_window.mouse.setKeyRelease(Mouse::Left);
- }
- if (m_window.mouse.isKeyPressed(Mouse::Right)) {
- LOG("polygon2.push_back (%d, %d)\n", pos.x, pos.y);
- std::shared_ptr<Command> com(new Command);
- com->m_execute = std::bind([&pos, this](){ polygon2.boundary.push_back(pos);});
- com->m_undo = std::bind([this](){ polygon2.boundary.pop_back(); });
- m_command_queue_execute(com);
- m_window.mouse.setKeyRelease(Mouse::Right);
- }
- if (m_window.mouse.isKeyPressed(Mouse::Middle)) {
- if (m_polygon_swap) {
- if (polygon2.holes.size() <= m_hole_it2) {
- polygon2.holes.push_back(vector<math::vec2>());
- }
- LOG("polygon2.holes[%d].push_back (%d, %d)\n", m_hole_it2, pos.x, pos.y);
- std::shared_ptr<Command> com(new Command);
- com->m_execute = std::bind([h = this->m_hole_it2, pos, this](){polygon2.holes[h].push_back(pos);});
- com->m_undo = std::bind([h = this->m_hole_it2, this](){polygon2.holes[h].pop_back();});
- m_command_queue_execute(com);
- } else {
- if (polygon1.holes.size() <= m_hole_it) {
- polygon1.holes.push_back(vector<math::vec2>());
- }
- LOG("polygon1.holes[%d].push_back (%d, %d)\n", m_hole_it, pos.x, pos.y);
- std::shared_ptr<Command> com(new Command);
- com->m_execute = std::bind([h = this->m_hole_it, pos, this](){polygon1.holes[h].push_back(pos);});
- com->m_undo = std::bind([h = this->m_hole_it, this](){polygon1.holes[h].pop_back();});
- m_command_queue_execute(com);
- }
- m_window.mouse.setKeyRelease(Mouse::Middle);
- }
- std::cout << Mouse::keyToString(key) << std::endl;
- }
- void Application::onKeyboardKeyPress(Keyboard::Key key) {
- switch (key) {
- case Keyboard::Escape:
- m_running = false;
- break;
- case Keyboard::Z:
- m_command_queue_undo();
- m_window.keyboard.setKeyRelease(Keyboard::Z);
- break;
- case Keyboard::X:
- draw_insection = !draw_insection;
- insection = algorithmWeilerAtherton(polygon1, polygon2);
- m_window.keyboard.setKeyRelease(Keyboard::X);
- break;
- case Keyboard::Up:
- m_points_to_show++;
- m_window.keyboard.setKeyRelease(Keyboard::Up);
- break;
- case Keyboard::Down:
- if (m_points_to_show > 1) {
- m_points_to_show--;
- }
- m_window.keyboard.setKeyRelease(Keyboard::Down);
- break;
- case Keyboard::C:
- m_polygon_swap = !m_polygon_swap;
- m_window.keyboard.setKeyRelease(Keyboard::C);
- break;
- case Keyboard::N:
- m_hole_it++;
- m_window.keyboard.setKeyRelease(Keyboard::N);
- break;
- case Keyboard::M:
- m_hole_it2++;
- m_window.keyboard.setKeyRelease(Keyboard::M);
- break;
- default:
- break;
- }
- std::cout << Keyboard::keyToString(key) << std::endl;
- }
- void Application::onWindowResize(int height, int width) {
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, width, 0, height, -1, 1);
- }
- void Application::onMouseMove(int x, int y) {
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement