Advertisement
Guest User

Untitled

a guest
Apr 26th, 2015
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 34.89 KB | None | 0 0
  1. #include "application.h"
  2. #include "scene_laba2.h"
  3. #include <iostream>
  4. #include <GL/glew.h>
  5. #include "command.h"
  6. #include <queue>
  7. #include <map>
  8. #include <functional>
  9. std::stack<std::shared_ptr<ICommand>> m_command_queue;
  10. int    m_points_to_show;
  11.  
  12. using namespace std;
  13.  
  14. template<typename T>
  15. struct ListEntry {
  16.     ListEntry() {
  17.         next = prev = nullptr;
  18.     }
  19.  
  20.     T value;
  21.     ListEntry *next;
  22.     ListEntry *prev;
  23. };
  24.  
  25. template<typename T>
  26. class ListEntryIterator {
  27. public:
  28.     bool isNull() {
  29.         return ptr == nullptr;
  30.     }
  31.  
  32.     ListEntryIterator operator++(int) {
  33.         ptr = ptr->next;
  34.         return *this;
  35.     }
  36.  
  37.     ListEntryIterator operator--(int) {
  38.         ptr = ptr->prev;
  39.         return *this;
  40.     }
  41.  
  42.     ListEntryIterator(ListEntry<T>* p) {
  43.         ptr = p;
  44.     }
  45.     ListEntryIterator() {
  46.         ptr = nullptr;
  47.     }
  48.  
  49.     bool operator==(ListEntryIterator<T> b) {
  50.         return this->ptr == b.ptr;
  51.     }
  52.  
  53.     bool operator!=(ListEntryIterator<T> b) {
  54.         return !(*this == b);
  55.     }
  56.  
  57.     T& operator*() {
  58.         if (!isNull()) {
  59.             return ptr->value;
  60.         } else {
  61.             throw "Exception: error iterator to null";
  62.         }
  63.     }
  64.  
  65.     ListEntry<T>* ptr;
  66. };
  67.  
  68. template<typename T>
  69. class List {
  70. public:
  71.     ListEntryIterator<T> find(T value) {
  72.         if (!front) {
  73.             return ListEntryIterator<T>(nullptr);
  74.         }
  75.  
  76.         auto i = getFront();
  77.         do {
  78.             if ((*i) == value) {
  79.                 return i;
  80.             }
  81.             i++;
  82.         } while(i != getFront());
  83.  
  84.         return ListEntryIterator<T>(nullptr);
  85.     }
  86.  
  87.    /* void erase(T value) {
  88.         if (!front) {
  89.             return;
  90.         }
  91.  
  92.         auto i = front;
  93.         do {
  94.             if (i.next && i.next.value == value) {
  95.                 auto tmp = i.next;
  96.                 i = tmp.next;
  97.                 tmp.next.prev = i;
  98.                 delete tmp;
  99.                 return;
  100.             }
  101.             i = i.next;
  102.         } while(i != front);
  103.  
  104.         return;
  105.     }*/
  106.  
  107.     bool push_back(T value) {
  108.       /*  if (test.find(value) != test.end()) {
  109.             return false;
  110.         }
  111. */
  112.         ListEntry<T>* elem = new ListEntry<T>;
  113.         elem->value = value;
  114.         elem->next = elem->prev = nullptr;
  115.  
  116.         if (front == nullptr) {
  117.             front = elem;
  118.             back = elem;
  119.             elem->next = elem->prev = elem;
  120.         } else {
  121.             back->next = elem;
  122.             elem->prev = back;
  123.  
  124.             elem->next = front;
  125.             front->prev = elem;
  126.             back = elem;
  127.         }
  128.         size++;
  129.         return true;
  130.     }
  131.  
  132.     bool push_after(T after, T value) {
  133.         auto it = front;
  134.         if (!it) {
  135.             return false;
  136.         }
  137.         do {
  138.             if (it->value == after) {
  139.                 ListEntry<T>* elem = new ListEntry<T>;
  140.                 elem->value = value;
  141.                 elem->next = elem->prev = nullptr;
  142.  
  143.                 auto tmp = it->next;
  144.                 it->next = elem;
  145.                 elem->prev = it;
  146.  
  147.                 tmp->prev = it;
  148.                 elem->next = tmp;
  149.                 size++;
  150.                 return true;
  151.             }
  152.             it = it->next;
  153.         } while (it != back);
  154.         return false;
  155.     }
  156.  
  157.     bool push_after(ListEntryIterator<T> after, T value) {
  158.         if (after.isNull()) {
  159.             return false;
  160.         }
  161.         auto it = after.ptr;
  162.         ListEntry<T>* elem = new ListEntry<T>;
  163.         elem->value = value;
  164.         elem->next = elem->prev = nullptr;
  165.  
  166.         auto tmp = it->next;
  167.         it->next = elem;
  168.         elem->prev = it;
  169.  
  170.         tmp->prev = it;
  171.         elem->next = tmp;
  172.         size++;
  173.         return true;
  174.     }
  175.  
  176.     bool push_prev(ListEntryIterator<T> prev, T value) {
  177.         if (prev.isNull()) {
  178.             return false;
  179.         }
  180.         prev--;
  181.         return push_after(prev, value);
  182.     }
  183.  
  184.     vector<T> to_vector() {
  185.         vector<T> res;
  186.         auto it = getFront();
  187.         do {
  188.             res.push_back(*it);
  189.             it++;
  190.         } while(it != getFront());
  191.  
  192.         return res;
  193.     }
  194.  
  195.     ListEntryIterator<T> getFront() {
  196.         return {front};
  197.     }
  198.  
  199.     ListEntryIterator<T> getBack() {
  200.         return {back};
  201.     }
  202.     List() {
  203.         front = back = nullptr;
  204.         size = 0;
  205.     }
  206.     size_t getSize() { return size; }
  207. private:
  208.     ListEntry<T>* front;
  209.     ListEntry<T>* back;
  210.     size_t size;
  211.     //map<T, bool> test;
  212. };
  213.  
  214. void Application::init() {
  215.     m_running = false;
  216.     m_fps = 0;
  217.     m_window.open("Application", 1280, 720);
  218.     m_window.onKeyboardKeyPress = delegate<void(Keyboard::Key)>(this, &Application::onKeyboardKeyPress);
  219.     m_window.onWindowResize = delegate<void(int, int)>(this, &Application::onWindowResize);
  220.     m_window.onMouseKeyPress = delegate<void(Mouse::Key)>(this, &Application::onMouseKeyPress);
  221.     m_window.onMouseMove = delegate<void(int, int)>(this, &Application::onMouseMove);
  222.     m_window.mouse.setMousePos(m_window.getWidth() / 2, m_window.getHeight() / 2);
  223.     draw_insection = 0;
  224.     m_points_to_show = 1;
  225.     m_hole_it = m_hole_it2 = 0;
  226.     m_polygon_swap = false;
  227. }
  228.  
  229. void Application::deinit() {
  230.     m_running = false;
  231.     m_fps = 0;
  232.     m_window.close();
  233.     LibResouces::deinit();
  234. }
  235.  
  236. typedef enum {
  237.     SIMPLE, IN, OUT
  238. } Type;
  239.  
  240. struct Connection {
  241.     math::vec2 point;
  242.     ListEntryIterator<Connection> to_list;
  243.     Type type;
  244.     Connection(math::vec2 p, Type t) {
  245.         point = p;
  246.         type = t;
  247.         to_list = ListEntryIterator<Connection>(nullptr);
  248.     }
  249.  
  250.     Connection(){
  251.         point = {0, 0};
  252.         type = SIMPLE;
  253.         to_list = ListEntryIterator<Connection>(nullptr);
  254.     }
  255.  
  256.     bool operator==(const math::vec2 point) const {
  257.         return this->point == point;
  258.     }
  259.     bool operator==(const Connection a) const {
  260.         return point == a.point;
  261.     }
  262.     bool operator!=(const Connection a) const {
  263.         return point != a.point;
  264.     }
  265. };
  266.  
  267.  
  268. class Polygon_list {
  269. public:
  270.     List<Connection> boundary;
  271.     vector<List<Connection>> holes;
  272.     Polygon_list(const Polygon &p) {
  273.         for (auto v : p.boundary)    {
  274.             boundary.push_back({v, SIMPLE});
  275.         }
  276.  
  277.         for (int i = 0; i < p.holes.size(); i++) {
  278.             holes.push_back(List<Connection>());
  279.             for (auto v : p.holes[i]) {
  280.                 holes[i].push_back({v, SIMPLE});
  281.             }
  282.         }
  283.     }
  284.  
  285. };
  286.  
  287. std::vector<math::vec2> global_in;
  288. std::vector<math::vec2> global_out;
  289.  
  290. struct Insect {
  291.     math::vec2 l1_s, l1_e, l2_s, l2_e;
  292.     math::vec2 point;
  293.     Type type;
  294.     Insect(math::vec2 a_1, math::vec2 a_2, math::vec2 b_1, math::vec2 b_2,math::vec2 p, Type t) {
  295.         l1_s = a_1;
  296.         l1_e = a_2;
  297.         l2_s = b_1;
  298.         l2_e = b_2;
  299.         point = p;
  300.         type = t;
  301.     }
  302. };
  303.  
  304.  
  305.  
  306. bool updateList(List<Connection> &polygon1, List<Connection> &polygon2, bool in) { // возращает было ли хоть 1 пересечение
  307.     vector<Connection> pol1 = polygon1.to_vector();
  308.     vector<Connection> pol2 = polygon2.to_vector();
  309.     vector<Insect> insection;
  310.     bool yes = false;
  311.  
  312.     // Находим точки пересечения, пока классифицуем их как Simple
  313.     for (int i = 0; i < pol1.size(); i++) {
  314.         math::LineSegment2D l1(pol1[i].point, pol1[(i + 1 != pol1.size())? i + 1 : 0].point); // построили отрезок 1
  315.  
  316.         for (int j = 0; j < pol2.size(); j++) {
  317.             math::vec2 start;
  318.             math::vec2 end;
  319.             math::LineSegment2D l2(pol2[j].point, pol2[(j + 1 != pol2.size())? j + 1 : 0].point);  // построили отрезок 2
  320.             if (math::LineSegment2D::intersect(l1, l2, start, end)) {
  321.                 if (start == end) {
  322.                     insection.push_back(Insect(pol1[i].point, pol1[(i + 1 != pol1.size())? i + 1 : 0].point, \
  323.                                          pol2[j].point, pol2[(j + 1 != pol2.size())? j + 1 : 0].point, \
  324.                                          start, SIMPLE));
  325.                     yes = true;
  326.                 }
  327.             }
  328.         }
  329.     }
  330.  
  331.     // Вставляем точки пересечения в первый контур, попутно классифицируя их
  332.     auto it = polygon1.getFront();
  333.     do {
  334.         vector<Insect*> vec;
  335.         auto p1 = it;
  336.         auto p2 = it; p2++;
  337.  
  338.         for (int i = 0; i < insection.size(); i++) {
  339.             if (((*p1).point == insection[i].l1_s) && ((*p2).point == insection[i].l1_e)) {
  340.                 vec.push_back(&insection[i]);
  341.             }
  342.         }
  343.  
  344.         sort(vec.begin(), vec.end(),
  345.              [&p1](const Insect* a, const Insect* b) -> bool {
  346.              return ( math::length(a->point - (*p1).point) <= math::length(b->point - (*p1).point) );
  347.         });
  348.  
  349.         for (auto v : vec) {
  350.             in = !in;
  351.             v->type = (in)? IN : OUT;
  352.             polygon1.push_after(p1, {v->point, v->type});
  353.             p1++;
  354.         }
  355.         it++;
  356.     } while(it != polygon1.getFront());
  357.  
  358.     // Вставляем во второй контр, точки уже классифицированны на пред шаге
  359.     it = polygon2.getFront();
  360.     do {
  361.         vector<Connection> vec;
  362.         auto p1 = it;
  363.         auto p2 = it; p2++;
  364.  
  365.         for (auto v : insection) {
  366.             if (((*p1).point == v.l2_s) && ((*p2).point == v.l2_e)) {
  367.                 vec.push_back({v.point, v.type});
  368.             }
  369.         }
  370.         sort(vec.begin(), vec.end(),
  371.              [&p1](const Connection& a, const Connection b) -> bool {
  372.              return ( math::length(a.point - (*p1).point) <= math::length(b.point - (*p1).point) );
  373.         });
  374.         for (auto v : vec) {
  375.             polygon2.push_after(p1, v);
  376.             p1++;
  377.         }
  378.         it++;
  379.     } while(it != polygon2.getFront());
  380.  
  381.     // Связи одного контура с другим
  382.     for (auto v : insection) {
  383.         auto v1 = polygon1.find({v.point, v.type});
  384.         auto v2 = polygon2.find({v.point, v.type});
  385.         (*v1).to_list = v2;
  386.         (*v2).to_list = v1;
  387.     }
  388.     return yes;
  389. }
  390.  
  391. 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) {
  392.     Polygon_list pol1(polygon1);
  393.     Polygon_list pol2(polygon2);
  394.     vector<bool> test1(polygon1.holes.size()); // храним есть ли пересечение дыркок 1 контура с чем-нибудь
  395.     vector<bool> test2(polygon2.holes.size()); // храним если ли пересечение дыркок 2 контура с чем-нибудь
  396.     std::fill(test1.begin(), test1.end(), 0);
  397.     std::fill(test2.begin(), test2.end(), 0);
  398.     // polygon1.boundary
  399.     bool yes = updateList(pol1.boundary, pol2.boundary, polygon2.pointInPolygon(polygon1.boundary[0]));
  400.  
  401.     bool yes_1 = yes; // пересечение первой границы с дырками
  402.  
  403.     for (int i = 0; i < pol2.holes.size(); i++) {
  404.         auto& hole = pol2.holes[i];
  405.         if (hole.getSize() >= 3) {
  406.             bool intersection = updateList(pol1.boundary, hole, polygon2.pointInPolygon(polygon1.boundary[0]));
  407.             test2[i] = test2[i] || intersection;
  408.             yes_1 = yes_1 || intersection;
  409.         }
  410.     }
  411.     // границы не пересекаются и второй полигон содержет точку первого
  412.     if (yes_1 == false) {
  413.         if (polygon2.pointInPolygon(polygon1.boundary[0])) { // возращаем границу 1
  414.             result.push_back(polygon1.boundary);
  415.         }
  416.     }
  417.  
  418.     bool yes_2 = yes; // пересечение второй границы с дырками
  419.  
  420.  
  421.  
  422.     for (int i = 0; i < pol1.holes.size(); i++) {
  423.         if (pol1.holes[i].getSize() >= 3) {
  424.             bool intersection = updateList(pol1.holes[i], pol2.boundary, polygon2.pointInPolygon(polygon1.holes[i][0]));
  425.  
  426.             test1[i] = test1[i] || intersection;
  427.             yes_2 = yes_2 || intersection;
  428.             for (int j = 0; j < pol2.holes.size(); j++) {
  429.                 if (pol2.holes[j].getSize() >= 3) {
  430.                     bool intersection = updateList(pol1.holes[i], pol2.holes[j], polygon2.pointInPolygon(polygon1.holes[i][0]));
  431.  
  432.                     test1[i] = test1[i] || intersection;
  433.                     test2[j] = test2[j] || intersection;
  434.                 }
  435.             }
  436.  
  437.         }
  438.     }
  439.  
  440.     // границы не пересекаются и первый полигон содержет точку второго
  441.     if (!yes_2) {
  442.         if (polygon1.pointInPolygon(polygon2.boundary[0])) { // возращаем границу 2
  443.             result.push_back(polygon2.boundary);
  444.         }
  445.     }
  446.  
  447.     out_polygon1 = pol1;
  448.     out_polygon2 = pol2;
  449.     holes_insection_1 = test1;
  450.     holes_insection_2 = test2;
  451. }
  452. vector<math::vec2> DEBUG_GLOBAL_IN, DEBUG_GLOBAL_OUT;
  453.  
  454. vector<vector<math::vec2>> Application::algorithmWeilerAtherton(const Polygon &polygon1, const Polygon &polygon2) {
  455.  
  456.     /*
  457.      * Тут уже выделили все точки и классифицировали их
  458.      */
  459.     DEBUG_GLOBAL_IN.clear();
  460.     DEBUG_GLOBAL_OUT.clear();
  461.     if (polygon1.boundary.size() <= 3 && polygon2.boundary.size() <= 3) {
  462.         return vector<vector<math::vec2>>();
  463.     }
  464.  
  465.     Polygon_list list1(polygon1), list2(polygon2);
  466.     vector<vector<math::vec2>> result;
  467.     vector<bool> test1;
  468.     vector<bool> test2;
  469.  
  470.     updatePolygon(polygon1, polygon2, list1, list2, result, test1, test2);
  471.     list<ListEntryIterator<Connection>> global_in;
  472.  
  473.     auto it = list1.boundary.getFront();
  474.     do {
  475.         if ((*it).type == IN) {
  476.             global_in.push_back(it);
  477.             DEBUG_GLOBAL_IN.push_back((*it).point);
  478.         }
  479.         if ((*it).type == OUT) {
  480.             DEBUG_GLOBAL_OUT.push_back((*it).point);
  481.         }
  482.         it++;
  483.     } while (it != list1.boundary.getFront());
  484.  
  485.     for (auto hole : list1.holes) {
  486.         if (hole.getSize() >= 3) {
  487.             auto it = hole.getFront();
  488.             do {
  489.                 if ((*it).type == IN) {
  490.                     global_in.push_back(it);
  491.                     DEBUG_GLOBAL_IN.push_back((*it).point);
  492.                 }
  493.  
  494.                 if ((*it).type == OUT) {
  495.                     DEBUG_GLOBAL_OUT.push_back((*it).point);
  496.                 }
  497.                 it++;
  498.             } while (it != hole.getFront());
  499.         }
  500.     }
  501.  
  502.  
  503. /*
  504.     Определение части обрабатываемого многоугольника, попавшей в окно выполняется следующим образом:
  505.     Если не исчерпан список входных точек пересечения, то выбираем очередную входную точку.
  506.  
  507.     Двигаемся по вершинам отсекаемого многоугольника пока не обнаружится следующая точка пересечения;
  508.     все пройденные точки, не включая прервавшую просмотр, заносим в результат;
  509.  
  510.     используя двухстороннюю связь точек пересечения, переключаемся на просмотр списка вершин окна.
  511.     Двигаемся по вершинам окна до обнаружения следующей точки пересечения; все пройденные точки, не включая последнюю, прервавшую просмотр, заносим в результат.
  512.  
  513.     Используя двухстороннюю связь точек пересечения, переключаемся на список вершин обрабатываемого многоугольника.
  514.     Эти действия повторяем пока не будет достигнута исходная вершина - очередная часть отсекаемого многоугольника,
  515.     попавшая в окно, замкнулась. Переходим на выбор следующей входной точки в списке отсекаемого многоугольника.
  516. */
  517.  
  518.  
  519.     int iter = result.size();// смещаемся, чтобы не задеть другие контура
  520.  
  521.     Timer time;
  522.     time.start();
  523.     while (global_in.size() > 0 && time.elapsedSec() < 1)
  524.     {
  525.         auto start = global_in.front();
  526.         global_in.pop_front();
  527.         auto it = start;
  528.  
  529.         result.push_back(vector<math::vec2>());
  530.         do {
  531.             for (; (*it).type != Type::OUT; it++) {
  532.                 result[iter].push_back((*it).point);
  533.             }
  534.  
  535.             for (it = (*it).to_list; (*it).type != Type::IN; it++) {
  536.                 result[iter].push_back((*it).point);
  537.             }
  538.             it = (*it).to_list;
  539.  
  540.             auto f = std::find(global_in.begin(), global_in.end(), it);
  541.             if (f != global_in.end()) {
  542.                 global_in.erase(f);
  543.             }
  544.         } while(start != it);
  545.         iter++;
  546.     }
  547.  
  548.     if (global_in.size() > 0) {
  549.        cout << "TIME BREAK!" << endl;
  550.        result.clear();
  551.        return result;
  552.     }
  553.  
  554.     for (int i = 0; i < result.size(); i++) {
  555.             for (int j = 0; j < test1.size(); j++) {
  556.                 cout << test1.size() << endl;
  557.                 if (test1[j] == false) { // дырка ни с чем не пересекается
  558.                     if (polygon1.holes[j].size() >= 3) {
  559.                         bool in = true;
  560.                         for (auto v : polygon1.holes[j]) {
  561.                             in = in && math::pointInPolygon(v, result[i]);
  562.                         }
  563.                         if (in) { // и все точки лежат внутри результирующего контура
  564.                             result.push_back(polygon1.holes[j]); // добавляем дырку к выходу
  565.                             test1[j] = true;
  566.                         }
  567.                     } else {
  568.                         test1[j] = true;
  569.                     }
  570.                 }
  571.             }
  572.  
  573.             for (int j = 0; j < test2.size(); j++) {
  574.                 if (test2[j] == false) { // дырка ни с чем не пересекается
  575.                     if (polygon2.holes[j].size() >= 3) {
  576.                         bool in = true;
  577.                         for (auto v : polygon2.holes[j]) {
  578.                             in = in && math::pointInPolygon(v, result[i]);
  579.                         }
  580.                         if (in) { // и все точки лежат внутри результирующего контура
  581.                             result.push_back(polygon2.holes[j]); // добавляем дырку к выходу
  582.                             test2[j] = true;
  583.                         }
  584.                     } else {
  585.                         test2[j] = true;
  586.                     }
  587.                 }
  588.             }
  589.     }
  590.  
  591.     return std::move(result);
  592. }
  593.  
  594. //typedef enum {
  595. //    SIMPLE, IN, OUT
  596. //} Type;
  597.  
  598. //struct Connection {
  599. //    math::vec2 point;
  600. //    int index;
  601. //    int to_list;
  602. //    Type type;
  603. //    bool operator==(const math::vec2 point) const {
  604. //        return this->point == point;
  605. //    }
  606. //    bool operator==(const Connection a) const {
  607. //        return point == a.point;
  608. //    }
  609. //    bool operator!=(const Connection a) const {
  610. //        return point != a.point;
  611. //    }
  612. //};
  613.  
  614.  
  615. //std::vector<math::vec2> global_in;
  616. //std::vector<math::vec2> global_out;
  617.  
  618. //std::vector<Connection> updateList(const std::vector<math::vec2> &polygon1, const std::vector<math::vec2> &polygon2,
  619. //                                   std::vector<int> &in_indices, std::vector<int> &out_indices, bool swap_in_out_type = false) {
  620. //    // определим, лежит ли первая точка в контуре
  621. //    global_in.clear();
  622. //    global_out.clear();
  623. //    bool in = math::pointInPolygon(polygon1[0], polygon2);
  624. //    if (swap_in_out_type) {
  625. //        in = !in;
  626. //    }
  627. //    // нашли все пересечения и запилили их в списки вершин
  628. //    std::vector<Connection> result;
  629. //    int iter = 0;
  630. //    for (int i = 0; i < polygon1.size(); i++) {
  631. //        result.push_back({polygon1[i], iter, 0, SIMPLE});
  632. //        iter++;
  633. //        std::vector<math::vec2> insection;
  634. //        math::LineSegment2D l1(polygon1[i], polygon1[(i + 1 != polygon1.size())? i + 1 : 0]); // построили отрезок 1
  635.  
  636. //        for (int j = 0; j < polygon2.size(); j++) {
  637. //            math::vec2 start;
  638. //            math::vec2 end;
  639. //            math::LineSegment2D l2(polygon2[j], polygon2[(j + 1 != polygon2.size())? j + 1 : 0]);  // построили отрезок 2
  640. //            if (math::LineSegment2D::intersect(l1, l2, start, end)) {
  641. //                if (start == end) {
  642. //                    insection.push_back(start);
  643. //                }
  644. //            }
  645. //        }
  646.  
  647. //        // имеем точки пересечений, надо их в правильном порядке добавить в список вершин первого
  648. //        // сортировка по длинам не прошла (a - v0).len <= (b - v0).len
  649. //        // пришлось сделать по параметрическому уравнению
  650. //        // v(t) = v0 + t*direction
  651. //        // отсюда t = (x-x0)/direction.x
  652. //        // сортируя по t получаем все точки в порядке движения от i до i + 1 точки
  653. //        math::vec2 direction = math::normalize(polygon1[(i + 1 != polygon1.size())? i + 1 : 0] - polygon1[i]);
  654. //        sort(insection.begin(), insection.end(),
  655. //             [&polygon1, &i, &direction](const math::vec2& a, const math::vec2 b) -> bool {
  656. //             return ( ((a.x - polygon1[i].x) / direction.x) <= ((b.x - polygon1[i].x) / direction.x) );
  657. //        });
  658.  
  659. //        for (auto v : insection) {
  660. //            in = !in;
  661. //            if (in) {
  662. //                result.push_back({v, iter, 0, IN});
  663. //                in_indices.push_back(iter);
  664. //                global_in.push_back(v);
  665. //            } else {
  666. //                result.push_back({v, iter, 0, OUT});
  667. //                out_indices.push_back(iter);
  668. //                global_out.push_back(v);
  669. //            }
  670. //            iter++;
  671. //        }
  672. //    }
  673. //    return std::move(result);
  674. //}
  675.  
  676. //vector<vector<math::vec2>> Application::algorithmWeilerAtherton(const std::vector<math::vec2> &polygon1, const std::vector<math::vec2> &polygon2) {
  677. //    if (polygon1.size() < 3 && polygon2.size() < 3) {
  678. //        return vector<vector<math::vec2>>();
  679. //    }
  680. //    vector<vector<math::vec2>> result;
  681. //    std::vector<Connection> lst1, lst2;
  682. //    std::vector<int> lst1_in_indices;
  683. //    std::vector<int> lst1_out_indices;
  684. //    std::vector<int> lst2_in_indices;
  685. //    std::vector<int> lst2_out_indices;
  686.  
  687. //    lst1 = updateList(polygon1, polygon2, lst1_in_indices, lst1_out_indices);
  688. //    lst2 = updateList(polygon2, polygon1, lst2_in_indices, lst2_out_indices, true);
  689.  
  690. //    std::list<Connection>  list_in;
  691. //    // Расставляем связь точек пересечения и списков
  692. //    for (auto i : lst1_in_indices) {
  693. //        for (auto j : lst2_in_indices) {
  694. //            if (lst1[i] == lst2[j]) {
  695. //                lst1[i].to_list = lst2[j].index;
  696. //                lst2[j].to_list = lst1[i].index;
  697. //                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);
  698. //                list_in.push_back(lst1[i]);
  699. //            }
  700. //        }
  701. //    }
  702.  
  703. //    for (auto i : lst1_out_indices) {
  704. //        for (auto j : lst2_out_indices) {
  705. //            if (lst1[i] == lst2[j]) {
  706. //                lst1[i].to_list = lst2[j].index;
  707. //                lst2[j].to_list = lst1[i].index;
  708. //                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);
  709. //            }
  710. //        }
  711. //    }
  712.  
  713. //    // имеем 2 списка вершин и список вершин на вход и выход
  714. //    if (lst1_in_indices.size() == 0 && lst1_out_indices.size() == 0) { // либо один вложен в другой, либо не пересекаются. Возьмём по 1 точке и определим это.
  715. //        bool in1 = math::pointInPolygon(polygon1[0], polygon2);
  716. //        bool in2 = math::pointInPolygon(polygon2[0], polygon1);
  717. //        if (!in1 && !in2) { // пересечение нулевое.
  718. //            return result;
  719. //        }
  720.  
  721. //        if (in1)  { // первый внутри второго
  722. //            result.push_back(polygon1);
  723. //            return result;
  724. //        } else { // второй внутри первого
  725. //            result.push_back(polygon2);
  726. //            return result;
  727. //        }
  728. //    }
  729. ///*
  730. //    Определение части обрабатываемого многоугольника, попавшей в окно выполняется следующим образом:
  731. //    Если не исчерпан список входных точек пересечения, то выбираем очередную входную точку.
  732.  
  733. //    Двигаемся по вершинам отсекаемого многоугольника пока не обнаружится следующая точка пересечения;
  734. //    все пройденные точки, не включая прервавшую просмотр, заносим в результат;
  735.  
  736. //    используя двухстороннюю связь точек пересечения, переключаемся на просмотр списка вершин окна.
  737. //    Двигаемся по вершинам окна до обнаружения следующей точки пересечения; все пройденные точки, не включая последнюю, прервавшую просмотр, заносим в результат.
  738.  
  739. //    Используя двухстороннюю связь точек пересечения, переключаемся на список вершин обрабатываемого многоугольника.
  740. //    Эти действия повторяем пока не будет достигнута исходная вершина - очередная часть отсекаемого многоугольника,
  741. //    попавшая в окно, замкнулась. Переходим на выбор следующей входной точки в списке отсекаемого многоугольника.
  742. //*/
  743.  
  744. //   int iter = 0;
  745. //   while (list_in.size() > 0) {
  746. //        auto v1 = list_in.front().index;
  747. //        list_in.pop_front();
  748. //        auto v2 = v1;
  749. //        result.push_back(vector<math::vec2>());
  750. //        do {
  751. //            int i = v2;
  752. //            for (; lst1[i].type != Type::OUT; i = (i + 1) % lst1.size()) {
  753. //                result[iter].push_back(lst1[i].point);
  754. //                cout << lst1[i].point << endl;
  755. //            }
  756.  
  757. //            int j = lst1[i].to_list;
  758. //            for (; lst2[j].type != Type::IN; j = (j + 1) % lst2.size()) {
  759. //                result[iter].push_back(lst2[j].point);
  760. //                cout << lst1[i].point << endl;
  761. //            }
  762.  
  763. //            auto it = std::find(list_in.begin(), list_in.end(), lst2[j]);
  764. //            if (it != list_in.end()) {
  765. //                list_in.erase(it);
  766. //            }
  767.  
  768. //            v2 = lst2[j].to_list;
  769. //        } while(v1 != v2);
  770. //        result[iter].push_back(lst1[v1].point);
  771. //        iter++;
  772. //    }
  773.  
  774. //    return std::move(result);
  775. //}
  776.  
  777. void Polygon::draw(math::vec4 color) {
  778.  
  779.     glBegin(GL_LINE_STRIP);
  780.     if (this->boundary.size() > 0) {
  781.  
  782.         for (int i = 0; i < this->boundary.size(); i++) {
  783.             glColor4fv(math::value_ptr(color - ((float)(i)/50)*color));
  784.             glVertex2fv(math::value_ptr(this->boundary[i]));
  785.         }
  786.         glVertex2fv(math::value_ptr(this->boundary[0]));
  787.     }
  788.     glEnd();
  789.  
  790.     for (auto hole : holes) {
  791.         glBegin(GL_LINE_STRIP);
  792.         if (hole.size() > 0) {
  793.             for (int i = 0; i < hole.size(); i++) {
  794.                 glColor4fv(math::value_ptr(color - ((float)(i)/50)*color));
  795.                 glVertex2fv(math::value_ptr(hole[i]));
  796.             }
  797.             glVertex2fv(math::value_ptr(hole[0]));
  798.         }
  799.         glEnd();
  800.     }
  801. }
  802.  
  803. void Application::render(float deltaTime) {
  804.     glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  805.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  806.     glMatrixMode(GL_MODELVIEW);
  807.     glLoadIdentity();
  808.  
  809.  
  810.     polygon1.draw({0, 1, 0, 1});
  811.     polygon2.draw({0, 1, 1, 0});
  812.  
  813.     if (draw_insection) {
  814.         glColor4f(0, 0, 1, 1);
  815.         glPointSize(6);
  816.  
  817.         if (insection.size() > 0) {
  818.             for (int j = 0; j < insection.size(); j++) {
  819.                 if (insection[j].size() > 0) {
  820.                     glBegin(GL_LINE_STRIP);
  821.                     for (int i = 0; i <= insection[j].size() && i < m_points_to_show; i++) {
  822.                         int w = i % insection[j].size();
  823.                         glVertex2fv(math::value_ptr(insection[j][w]));
  824.                     }
  825.                     glEnd();
  826.                 }
  827.  
  828.             }
  829.         }
  830.         glPointSize(6);
  831.         glColor4f(1, 0, 0 ,1);
  832.         glBegin(GL_POINTS);
  833.             for (auto v : DEBUG_GLOBAL_IN) {
  834.                 glVertex2fv(math::value_ptr(v));
  835.             }
  836.         glEnd();
  837.  
  838.         glColor4f(0, 1, 0 ,1);
  839.         glBegin(GL_POINTS);
  840.             for (auto v : DEBUG_GLOBAL_OUT) {
  841.                 glVertex2fv(math::value_ptr(v));
  842.             }
  843.         glEnd();
  844.     }
  845.  
  846.     glFlush();
  847. }
  848.  
  849. void Application::run() {
  850.     m_running = true;
  851.     m_timer.start();
  852.     glDisable(GL_DEPTH_TEST);
  853.     onWindowResize(m_window.getHeight(), m_window.getWidth());
  854.     while(m_running) {
  855.         m_frameIntervalTimer.start();
  856.         render(m_frameIntervalValue);
  857.         m_window.flush();
  858.         m_window.pullEvents();
  859.         m_frameIntervalValue = m_frameIntervalTimer.elapsedMilliSec();
  860.         m_fps++;
  861.         int time = m_timer.elapsedSec();
  862.         if (time >= 2.0) {
  863.             m_window.setTitle(std::string("Application: FPS = ") + std::to_string(m_fps / time));
  864.             m_fps = 0;
  865.             m_timer.start();
  866.         }
  867.     }
  868. }
  869.  
  870. void m_command_queue_execute(std::shared_ptr<ICommand> com) {
  871.     com->execute();
  872.     m_command_queue.push(std::move(com));
  873. }
  874.  
  875. void m_command_queue_undo() {
  876.     if (m_command_queue.size() > 0) {
  877.         m_command_queue.top()->undo();
  878.         m_command_queue.pop();
  879.     }
  880. }
  881.  
  882. void Application::onMouseKeyPress(Mouse::Key key) {
  883.     math::vec2 pos = {m_window.mouse.getX(), m_window.mouse.getY()};
  884.     if (m_window.mouse.isKeyPressed(Mouse::Left)) {
  885.         LOG("polygon1.push_back (%d, %d)\n", pos.x, pos.y);
  886.         std::shared_ptr<Command> com(new Command);
  887.         com->m_execute = std::bind([&pos, this](){ polygon1.boundary.push_back(pos); });
  888.         com->m_undo = std::bind([this](){ polygon1.boundary.pop_back(); });
  889.         m_command_queue_execute(com);
  890.         m_window.mouse.setKeyRelease(Mouse::Left);
  891.     }
  892.  
  893.     if (m_window.mouse.isKeyPressed(Mouse::Right)) {
  894.         LOG("polygon2.push_back (%d, %d)\n", pos.x, pos.y);
  895.         std::shared_ptr<Command> com(new Command);
  896.         com->m_execute = std::bind([&pos, this](){ polygon2.boundary.push_back(pos);});
  897.         com->m_undo = std::bind([this](){ polygon2.boundary.pop_back(); });
  898.         m_command_queue_execute(com);
  899.         m_window.mouse.setKeyRelease(Mouse::Right);
  900.     }
  901.     if (m_window.mouse.isKeyPressed(Mouse::Middle)) {
  902.         if (m_polygon_swap) {
  903.                 if (polygon2.holes.size() <= m_hole_it2) {
  904.                     polygon2.holes.push_back(vector<math::vec2>());
  905.                 }
  906.                 LOG("polygon2.holes[%d].push_back (%d, %d)\n", m_hole_it2, pos.x, pos.y);
  907.                 std::shared_ptr<Command> com(new Command);
  908.                 com->m_execute = std::bind([h = this->m_hole_it2, pos, this](){polygon2.holes[h].push_back(pos);});
  909.                 com->m_undo = std::bind([h = this->m_hole_it2, this](){polygon2.holes[h].pop_back();});
  910.                 m_command_queue_execute(com);
  911.         } else {
  912.             if (polygon1.holes.size() <= m_hole_it) {
  913.                 polygon1.holes.push_back(vector<math::vec2>());
  914.             }
  915.             LOG("polygon1.holes[%d].push_back (%d, %d)\n", m_hole_it, pos.x, pos.y);
  916.             std::shared_ptr<Command> com(new Command);
  917.             com->m_execute = std::bind([h = this->m_hole_it, pos, this](){polygon1.holes[h].push_back(pos);});
  918.             com->m_undo = std::bind([h = this->m_hole_it, this](){polygon1.holes[h].pop_back();});
  919.             m_command_queue_execute(com);
  920.  
  921.         }
  922.         m_window.mouse.setKeyRelease(Mouse::Middle);
  923.     }
  924.     std::cout << Mouse::keyToString(key) << std::endl;
  925. }
  926.  
  927. void Application::onKeyboardKeyPress(Keyboard::Key key) {
  928.     switch (key) {
  929.         case Keyboard::Escape:
  930.             m_running = false;
  931.             break;
  932.         case Keyboard::Z:
  933.             m_command_queue_undo();
  934.             m_window.keyboard.setKeyRelease(Keyboard::Z);
  935.             break;
  936.         case Keyboard::X:
  937.             draw_insection = !draw_insection;
  938.             insection = algorithmWeilerAtherton(polygon1, polygon2);
  939.             m_window.keyboard.setKeyRelease(Keyboard::X);
  940.             break;
  941.         case Keyboard::Up:
  942.             m_points_to_show++;
  943.             m_window.keyboard.setKeyRelease(Keyboard::Up);
  944.             break;
  945.         case Keyboard::Down:
  946.             if (m_points_to_show > 1) {
  947.                 m_points_to_show--;
  948.             }
  949.             m_window.keyboard.setKeyRelease(Keyboard::Down);
  950.             break;
  951.         case Keyboard::C:
  952.             m_polygon_swap = !m_polygon_swap;
  953.             m_window.keyboard.setKeyRelease(Keyboard::C);
  954.             break;
  955.         case Keyboard::N:
  956.             m_hole_it++;
  957.             m_window.keyboard.setKeyRelease(Keyboard::N);
  958.             break;
  959.         case Keyboard::M:
  960.             m_hole_it2++;
  961.             m_window.keyboard.setKeyRelease(Keyboard::M);
  962.             break;
  963.         default:
  964.             break;
  965.     }
  966.  
  967.     std::cout << Keyboard::keyToString(key) << std::endl;
  968. }
  969.  
  970. void Application::onWindowResize(int height, int width) {
  971.     glViewport(0, 0, width, height);
  972.     glMatrixMode(GL_PROJECTION);
  973.     glLoadIdentity();
  974.     glOrtho(0, width, 0, height, -1, 1);
  975. }
  976.  
  977. void Application::onMouseMove(int x, int y) {
  978.  
  979. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement