Advertisement
Guest User

Untitled

a guest
Sep 27th, 2016
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.40 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include <f2.h>
  4.  
  5. #include <unordered_map>
  6. #include <unordered_set>
  7.  
  8. #include <Rect.h>
  9.  
  10. #include <queue>
  11.  
  12. #include <algorithm>
  13.  
  14. #include <functional>
  15.  
  16. using std::unordered_map;
  17. using std::pair;
  18. using std::vector;
  19. using std::make_tuple;
  20. using std::cout;
  21. using std::endl;
  22. using std::unordered_set;
  23.  
  24. using namespace std::placeholders;
  25.  
  26. template<typename T, typename Number=float>
  27. struct PriorityQueue
  28. {
  29.   typedef pair<Number, T> PQElement;
  30.   std::priority_queue<PQElement, vector<PQElement>, std::greater<PQElement>> elements;
  31.  
  32.   inline bool empty() const { return elements.empty(); }
  33.  
  34.   inline void put(T item, Number priority)
  35.   {
  36.     elements.emplace(priority, item);
  37.   }
  38.  
  39.   inline T get()
  40.   {
  41.     T best_item = elements.top().second;
  42.     elements.pop();
  43.     return best_item;
  44.   }
  45. };
  46.  
  47. inline float heuristic(f2 a, f2 b)
  48. {
  49.   return std::abs(a.x - b.x) + std::abs(a.y - b.y);
  50. }
  51.  
  52. class Node
  53. {
  54. public:
  55.     Node(){}
  56.  
  57.     Node(const f2& position, vector<Node*> links = vector<Node*>(0))
  58.     {
  59.         position_ = position;
  60.         links_ = links;
  61.     }
  62.  
  63. f2 position_;
  64. vector<Node*> links_;
  65. };
  66.  
  67. inline float nodeDistanceSquared(f2 position, Node* node)
  68. {
  69.     return (position - node->position_).lengthSquared();
  70. }
  71.  
  72. inline bool distanceCompare(f2 position, Node* node1, Node* node2)
  73. {
  74.     return nodeDistanceSquared(position, node1) < nodeDistanceSquared(position, node2);
  75. }
  76.  
  77.  
  78. class Pathfinding
  79. {
  80. public:
  81.     Pathfinding(){}
  82.  
  83.     Pathfinding(const f2& gridSize, const f2& nodeSize, const vector<Rect>& staticObstacles = vector<Rect>(0))
  84.     {
  85.         obstacles_ = staticObstacles;
  86.         gridSize_ = gridSize;
  87.         nodeSize_ = nodeSize;
  88.         halfNodeSize_ = nodeSize / 2;
  89.         generateNodes(obstacles_);
  90.     }
  91.    
  92.     inline vector<Node*> neighbors(f2 position)
  93.     {
  94.         vector<Node*> results;
  95.         if (nodes_.count(position))
  96.         {
  97.             Node* node = nodes_[position];
  98.  
  99.             for (int i = 0; i < node->links_.size(); ++i)
  100.             {
  101.                 results.push_back(node->links_[i]);
  102.             }
  103.         }
  104.         else
  105.         {
  106.             bool bottomRight = false;
  107.             bool bottomLeft = false;
  108.             bool topLeft = false;
  109.             bool topRight = false;
  110.            
  111.             for (int i = 0; i < nodesV_.size(); ++i)
  112.             {
  113.                 Node* otherNode = nodesV_[i];
  114.                 f2 vec = position - otherNode->position_;
  115.                 if (vec.x <= 0 && vec.y < 0 && !bottomLeft)
  116.                 {
  117.                     if (straightPath(position, otherNode->position_))
  118.                     {
  119.                         bottomLeft = true;
  120.                         results.push_back(otherNode);
  121.                     }
  122.                 }
  123.                 else if (vec.x > 0 && vec.y <= 0 && !bottomRight)
  124.                 {
  125.                     if (straightPath(position, otherNode->position_))
  126.                     {
  127.                         bottomRight = true;
  128.                         results.push_back(otherNode);
  129.                     }
  130.                 }
  131.                 else if (vec.x > 0 && vec.y >= 0 && !topRight)
  132.                 {
  133.                     if (straightPath(position, otherNode->position_))
  134.                     {
  135.                         topRight = true;
  136.                         results.push_back(otherNode);
  137.                     }
  138.                 }
  139.                 else if (vec.x < 0 && vec.y >= 0 && !topLeft)
  140.                 {
  141.                     if (straightPath(position, otherNode->position_))
  142.                     {
  143.                         topLeft = true;
  144.                         results.push_back(otherNode);
  145.                     }
  146.                 }
  147.                 if (topLeft && topRight && bottomRight && bottomLeft)
  148.                 {
  149.                     return results;
  150.                 }
  151.             }
  152.         }
  153.         return results;
  154.     }
  155.  
  156.     inline bool straightPath(f2 start, f2 goal)
  157.     {
  158.         return straightPath(start, goal, halfNodeSize_);
  159.     }
  160.  
  161.     static bool straightPath(f2 start, f2 goal, vector<Rect>* obstacles)
  162.     {
  163.         f2 originalStart = start;
  164.         f2 originalGoal = goal;
  165.         f2 dir = goal - start;
  166.  
  167.         if (dir.x >= 0)
  168.         {
  169.             if (dir.y >= 0)
  170.             {
  171.                 // direction is bottomRight
  172.                 for (int i = 0; i < obstacles->size(); ++i)
  173.                 {
  174.                     f2 dir2 = (*obstacles)[i].bottomRight();
  175.                     f2 corner = (*obstacles)[i].topLeft();
  176.                     if (start.x <= dir2.x && start.y <= dir2.y && goal.x >= corner.x && goal.y >= corner.y)
  177.                     {
  178.                         if (linesIntersect(originalStart, originalGoal, (*obstacles)[i].topRight(), (*obstacles)[i].bottomLeft()))
  179.                         {
  180.                             return false;
  181.                         }
  182.                     }
  183.                 }
  184.             }
  185.             else
  186.             {
  187.                 // direction is topright
  188.                 for (int i = 0; i < obstacles->size(); ++i)
  189.                 {
  190.                     f2 dir2 = (*obstacles)[i].topRight();
  191.                     f2 corner = (*obstacles)[i].bottomLeft();
  192.                     if (start.x <= dir2.x && start.y >= dir2.y && goal.x >= corner.x && goal.y <= corner.y)
  193.                     {
  194.                         if (linesIntersect(originalStart, originalGoal, (*obstacles)[i].bottomRight(), (*obstacles)[i].topLeft()))
  195.                         {
  196.                             return false;
  197.                         }
  198.                     }
  199.                 }
  200.             }
  201.         }
  202.         else
  203.         {
  204.             if (dir.y >= 0)
  205.             {
  206.                 // direction is bottomLeft
  207.                 for (int i = 0; i < obstacles->size(); ++i)
  208.                 {
  209.                     f2 dir2 = (*obstacles)[i].bottomLeft();
  210.                     f2 corner = (*obstacles)[i].topRight();
  211.                     if (start.x > dir2.x && start.y <= dir2.y && goal.x <= corner.x && goal.y >= corner.y)
  212.                     {
  213.                         if (linesIntersect(originalStart, originalGoal, (*obstacles)[i].bottomRight(), (*obstacles)[i].topLeft()))
  214.                         {
  215.                             return false;
  216.                         }
  217.                     }
  218.                 }
  219.             }
  220.             else
  221.             {
  222.                 // direction is topLeft
  223.                 for (int i = 0; i < obstacles->size(); ++i)
  224.                 {
  225.                     f2 dir2 = (*obstacles)[i].topLeft();
  226.                     f2 corner = (*obstacles)[i].bottomRight();
  227.                     if (start.x > dir2.x && start.y > dir2.y && goal.x <= corner.x && goal.y <= corner.y)
  228.                     {
  229.                         if (linesIntersect(originalStart, originalGoal, (*obstacles)[i].topRight(), (*obstacles)[i].bottomLeft()))
  230.                         {
  231.                             return false;
  232.                         }
  233.                     }
  234.                 }
  235.             }
  236.         }
  237.         return true;
  238.     }  
  239.  
  240.     inline bool straightPath(f2 start, f2 goal, const f2& halfSize)
  241.     {
  242.         f2 originalStart = start;
  243.         f2 originalGoal = goal;
  244.         f2 dir = goal - start;
  245.         f2 topLeftCorner = start - halfSize;
  246.         f2 bottomRightCorner = start + halfSize;
  247.         f2 topLeftCornerGoal = goal - halfSize;
  248.         f2 bottomRightCornerGoal = goal + halfSize;    
  249.  
  250.         if (dir.x >= 0)
  251.         {
  252.             if (dir.y >= 0)
  253.             {
  254.                 // direction is bottomRight
  255.                 start -= halfSize;
  256.                 goal += halfSize;
  257.  
  258.                 f2 start1 = start + 2 * f2(halfSize.x, 0);
  259.                 f2 start2 = start + 2 * f2(0, halfSize.y);
  260.                 f2 goal2  = goal - 2  * f2(halfSize.x, 0);
  261.                 f2 goal1  = goal - 2  * f2(0, halfSize.y);
  262.  
  263.                 for (int i = 0; i < obstacles_.size(); ++i)
  264.                 {
  265.                     f2 dir2 = obstacles_[i].bottomRight();
  266.                     f2 corner = obstacles_[i].topLeft();
  267.                     if (start.x <= dir2.x && start.y <= dir2.y && goal.x >= corner.x && goal.y >= corner.y)
  268.                     {
  269.                         if (linesIntersect(start1, goal1, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  270.                             linesIntersect(start2, goal2, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  271.                             linesIntersect(originalStart, originalGoal, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  272.                             (obstacles_[i].topLeft().x < bottomRightCorner.x && obstacles_[i].topLeft().y < bottomRightCorner.y &&
  273.                              obstacles_[i].bottomRight().x > topLeftCorner.x && obstacles_[i].bottomRight().y > topLeftCorner.y) ||
  274.                             (obstacles_[i].topLeft().x < bottomRightCornerGoal.x &&
  275.                             obstacles_[i].topLeft().y < bottomRightCornerGoal.y &&
  276.                             obstacles_[i].bottomRight().x > topLeftCornerGoal.x &&
  277.                             obstacles_[i].bottomRight().y > topLeftCornerGoal.y))
  278.                         {
  279.                             return false;
  280.                         }
  281.                     }
  282.                 }
  283.             }
  284.             else
  285.             {
  286.                 // direction is topright
  287.  
  288.                 start += f2( - halfSize.x, halfSize.y);
  289.                 goal += f2(halfSize.x, - halfSize.y);
  290.  
  291.                 f2 start1 = start + 2 * f2(halfSize.x, 0);
  292.                 f2 start2 = start - 2 * f2(0, halfSize.y);
  293.                 f2 goal2 = goal - 2 * f2(halfSize.x, 0);
  294.                 f2 goal1 = goal + 2 * f2(0, halfSize.y);
  295.  
  296.                 for (int i = 0; i < obstacles_.size(); ++i)
  297.                 {
  298.                     f2 dir2 = obstacles_[i].topRight();
  299.                     f2 corner = obstacles_[i].bottomLeft();
  300.                     if (start.x <= dir2.x && start.y >= dir2.y && goal.x >= corner.x && goal.y <= corner.y)
  301.                     {
  302.                         if (linesIntersect(start1, goal1, obstacles_[i].bottomRight(), obstacles_[i].topLeft()) ||
  303.                             linesIntersect(start2, goal2, obstacles_[i].bottomRight(), obstacles_[i].topLeft()) ||
  304.                             linesIntersect(originalStart, originalGoal, obstacles_[i].bottomRight(), obstacles_[i].topLeft()) ||
  305.                             (obstacles_[i].topLeft().x < bottomRightCorner.x && obstacles_[i].topLeft().y < bottomRightCorner.y &&
  306.                              obstacles_[i].bottomRight().x > topLeftCorner.x && obstacles_[i].bottomRight().y > topLeftCorner.y) ||
  307.                             (obstacles_[i].topLeft().x < bottomRightCornerGoal.x &&
  308.                             obstacles_[i].topLeft().y < bottomRightCornerGoal.y &&
  309.                             obstacles_[i].bottomRight().x > topLeftCornerGoal.x &&
  310.                             obstacles_[i].bottomRight().y > topLeftCornerGoal.y))
  311.                         {
  312.                             return false;
  313.                         }
  314.                     }
  315.                 }
  316.             }
  317.         }
  318.         else
  319.         {
  320.             if (dir.y >= 0)
  321.             {
  322.                 // direction is bottomLeft
  323.  
  324.                 start -= f2( - halfSize.x, halfSize.y);
  325.                 goal -= f2(halfSize.x, - halfSize.y);
  326.  
  327.                 f2 start1 = start - 2 * f2(halfSize.x, 0);
  328.                 f2 start2 = start + 2 * f2(0, halfSize.y);
  329.                 f2 goal2 = goal + 2 * f2(halfSize.x, 0);
  330.                 f2 goal1 = goal - 2 * f2(0, halfSize.y);
  331.  
  332.                 for (int i = 0; i < obstacles_.size(); ++i)
  333.                 {
  334.                     f2 dir2 = obstacles_[i].bottomLeft();
  335.                     f2 corner = obstacles_[i].topRight();
  336.                     if (start.x > dir2.x && start.y <= dir2.y && goal.x <= corner.x && goal.y >= corner.y)
  337.                     {
  338.                         if (linesIntersect(start1, goal1, obstacles_[i].bottomRight(), obstacles_[i].topLeft()) ||
  339.                             linesIntersect(start2, goal2, obstacles_[i].bottomRight(), obstacles_[i].topLeft())  ||
  340.                             linesIntersect(originalStart, originalGoal, obstacles_[i].bottomRight(), obstacles_[i].topLeft())  ||
  341.                             (obstacles_[i].topLeft().x < bottomRightCorner.x && obstacles_[i].topLeft().y < bottomRightCorner.y &&
  342.                              obstacles_[i].bottomRight().x > topLeftCorner.x && obstacles_[i].bottomRight().y > topLeftCorner.y) ||
  343.                             (obstacles_[i].topLeft().x < bottomRightCornerGoal.x &&
  344.                             obstacles_[i].topLeft().y < bottomRightCornerGoal.y &&
  345.                             obstacles_[i].bottomRight().x > topLeftCornerGoal.x &&
  346.                             obstacles_[i].bottomRight().y > topLeftCornerGoal.y))
  347.                         {
  348.                             return false;
  349.                         }
  350.                     }
  351.                 }
  352.             }
  353.             else
  354.             {
  355.                 // direction is topLeft
  356.                 start += halfSize;
  357.                 goal -= halfSize;
  358.  
  359.                 f2 start1 = start - 2 * f2(halfSize.x, 0);
  360.                 f2 start2 = start - 2 * f2(0, halfSize.y);
  361.                 f2 goal2 = goal + 2 * f2(halfSize.x, 0);
  362.                 f2 goal1 = goal + 2 * f2(0, halfSize.y);
  363.  
  364.                 for (int i = 0; i < obstacles_.size(); ++i)
  365.                 {
  366.                     f2 dir2 = obstacles_[i].topLeft();
  367.                     f2 corner = obstacles_[i].bottomRight();
  368.                     if (start.x > dir2.x && start.y > dir2.y && goal.x <= corner.x && goal.y <= corner.y)
  369.                     {
  370.                         if (linesIntersect(start1, goal1, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  371.                             linesIntersect(start2, goal2, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  372.                             linesIntersect(originalStart, originalGoal, obstacles_[i].topRight(), obstacles_[i].bottomLeft()) ||
  373.                             (obstacles_[i].topLeft().x < bottomRightCorner.x && obstacles_[i].topLeft().y < bottomRightCorner.y &&
  374.                              obstacles_[i].bottomRight().x > topLeftCorner.x && obstacles_[i].bottomRight().y > topLeftCorner.y) ||
  375.                             (obstacles_[i].topLeft().x < bottomRightCornerGoal.x &&
  376.                             obstacles_[i].topLeft().y < bottomRightCornerGoal.y &&
  377.                             obstacles_[i].bottomRight().x > topLeftCornerGoal.x &&
  378.                             obstacles_[i].bottomRight().y > topLeftCornerGoal.y))
  379.                         {
  380.                             return false;
  381.                         }
  382.                     }
  383.                 }
  384.             }
  385.         }
  386.         return true;
  387.     }
  388.  
  389.     // standard A* search algorithm for finding a single point
  390.     inline vector<f2> aStarSearch(const f2& start, f2 goal)
  391.     {
  392.         if (straightPath(start, goal))
  393.         {
  394.             return {start, goal};
  395.         }
  396.  
  397.         addNode(goal);
  398.         for (int i = 0; i < nodesV_.size(); ++i)
  399.         {
  400.             if (nodes_.count(goal) > 0 && straightPath(nodesV_[i]->position_, goal))
  401.             {
  402.                 nodesV_[i]->links_.push_back(nodes_[goal]);
  403.             }
  404.         }
  405.  
  406.         addNode(start);
  407.         for (int i = 0; i < nodesV_.size(); ++i)
  408.         {
  409.             if (nodes_.count(start) > 0 && straightPath(nodesV_[i]->position_, start))
  410.             {
  411.                 nodes_[start]->links_.push_back(nodesV_[i]);
  412.             }
  413.         }
  414.  
  415.  
  416.         // i don't think this does what i wanted it to do
  417.         if (nodes_.count(goal) > 0 && nodes_[goal]->links_.size())
  418.         {
  419.             float distance = - 1;
  420.             f2 pos;
  421.  
  422.             for(int i = 0; i < nodesV_.size(); ++i)
  423.             {
  424.                 float newLength = (nodesV_[i]->position_ - goal).lengthSquared();
  425.                 if (distance == - 1 || distance > newLength)
  426.                 {
  427.                     distance = newLength;
  428.                     pos = nodesV_[i]->position_;
  429.                 }
  430.             }
  431.             goal = pos;
  432.         }
  433.  
  434.         PriorityQueue<f2> frontier;
  435.         unordered_map<f2, float> costSoFar;
  436.         unordered_map<f2, f2> cameFrom;
  437.  
  438.         frontier.put(start, 0);
  439.  
  440.         cameFrom[start] = start;
  441.         costSoFar[start] = 0;
  442.  
  443.         int counter = 0;
  444.  
  445.         while(!frontier.empty())
  446.         {
  447.             counter++;
  448.  
  449.         f2 current = frontier.get();
  450.  
  451.             if (current == goal)
  452.             {
  453.                 return reconstructPath(cameFrom, start, goal);
  454.             }
  455.  
  456.             vector<Node*> nb;
  457.             if (nodes_.count(current))
  458.             {
  459.                 nb = nodes_[current]->links_;
  460.             }
  461.             else
  462.             {
  463.                 nb = neighbors(current);
  464.             }
  465.             for (int i = 0; i < nb.size(); ++i)
  466.             {
  467.                 f2 next = nb[i]->position_;
  468.  
  469.                 float newCost = costSoFar[current] + (current - next).length();
  470.                 if (!costSoFar.count(next) || newCost < costSoFar[next])
  471.                 {
  472.                     costSoFar[next] = newCost;
  473.                     float priority = newCost + heuristic(next, goal);
  474.                     frontier.put(next, priority);
  475.                     cameFrom[next] = current;
  476.                 }  
  477.         }
  478.         }
  479.  
  480.         float distance = - 1;
  481.         f2 pos;
  482.  
  483.         for(auto i : cameFrom)
  484.         {
  485.             float newLength = (i.second - goal).lengthSquared();
  486.             if (distance == - 1 || distance > newLength)
  487.             {
  488.                 distance = newLength;
  489.                 pos = i.second;
  490.             }
  491.         }
  492.         if (start == pos)
  493.         {
  494.             return {};
  495.         }
  496.         else
  497.         {
  498.             return reconstructPath(cameFrom, start, pos);
  499.         }
  500.     }
  501.  
  502.     // A* search algorithm modified to search for a path to any of the given goals
  503.     inline vector<f2> aStarSearch(const f2& start, vector<Rect> goals)
  504.     {
  505.         int startingNodeCount = nodesV_.size();
  506.        
  507.         generateNodes(goals);
  508.  
  509.         addNode(start);
  510.         for (int i = 0; i < nodesV_.size(); ++i)
  511.         {
  512.             if (nodes_.count(start) > 0 && straightPath(nodesV_[i]->position_, start))
  513.             {
  514.                 nodes_[start]->links_.push_back(nodesV_[i]);
  515.             }
  516.         }      
  517.  
  518.         PriorityQueue<f2> frontier;
  519.         unordered_map<f2, float> costSoFar;
  520.         unordered_map<f2, f2> cameFrom;
  521.  
  522.         frontier.put(start, 0);
  523.  
  524.         cameFrom[start] = start;
  525.         costSoFar[start] = 0;
  526.  
  527.         int counter = 0;
  528.  
  529.         while(!frontier.empty())
  530.         {
  531.             counter++;
  532.  
  533.         f2 current = frontier.get();
  534.  
  535.         for (int i = startingNodeCount; i < nodesV_.size(); ++i)
  536.         {
  537.             if (current == nodesV_[i]->position_)
  538.             {
  539.                 return reconstructPath(cameFrom, start, nodesV_[i]->position_);
  540.             }
  541.         }
  542.  
  543.             vector<Node*> nb;
  544.             if (nodes_.count(current))
  545.             {
  546.                 nb = nodes_[current]->links_;
  547.             }
  548.             else
  549.             {
  550.                 nb = neighbors(current);
  551.             }
  552.             for (int i = 0; i < nb.size(); ++i)
  553.             {
  554.                 f2 next = nb[i]->position_;
  555.  
  556.                 float newCost = costSoFar[current];
  557.                 if (!costSoFar.count(next) || newCost < costSoFar[next])
  558.                 {
  559.                     costSoFar[next] = newCost;
  560.                     float priority = newCost;
  561.                     frontier.put(next, priority);
  562.                     cameFrom[next] = current;
  563.                 }  
  564.         }
  565.         }
  566.         return vector<f2>(0);
  567.     }
  568.  
  569.     // Create the path from the cameFrom map
  570.     inline vector<f2> reconstructPath(unordered_map<f2, f2> cameFrom, f2 start, f2 goal)
  571.     {
  572.         vector<f2> path;
  573.  
  574.         path.push_back(goal);
  575.  
  576.         f2 next = goal;
  577.         for (int i = 0; i < cameFrom.size(); ++i)
  578.         {
  579.             next = cameFrom[next];
  580.             path.push_back(next);
  581.             if (next == start)
  582.             {
  583.                 std::reverse(path.begin(), path.end());
  584.                 return path;
  585.             }
  586.         }
  587.         return path;
  588.     }
  589.  
  590.     inline void addLink(Node* node1, Node* node2)
  591.     {
  592.         if (straightPath(node1->position_, node2->position_, halfNodeSize_))
  593.         {
  594.             node1->links_.push_back(node2);
  595.             node2->links_.push_back(node1);
  596.         }
  597.     }
  598.  
  599.     inline Node* addNode(const f2& position)
  600.     {
  601.         f2 topLeftCorner = position - halfNodeSize_;
  602.         f2 bottomRightCorner = position + halfNodeSize_;
  603.         // no node is created if the node is inside an obstacle
  604.         for (int i = 0; i < obstacles_.size(); ++i)
  605.         {
  606.             if (obstacles_[i].topLeft().x < bottomRightCorner.x && obstacles_[i].topLeft().y < bottomRightCorner.y &&
  607.                     obstacles_[i].bottomRight().x > topLeftCorner.x && obstacles_[i].bottomRight().y > topLeftCorner.y)
  608.             {
  609.                 return NULL;
  610.             }
  611.         }
  612.  
  613.         Node* node = new Node(position);
  614.         bool bottomRight = false;
  615.         bool bottomLeft = false;
  616.         bool topLeft = false;
  617.         bool topRight = false;
  618.  
  619.         // sorts the nodes based on their distance
  620.         // this makes sure the nodes are connected to the closest possible nodes
  621.         // hurts performance quite a bit       
  622.         //std::sort(nodesV_.begin(), nodesV_.end(), std::bind(distanceCompare, position, _1, _2));
  623.  
  624.         for (int i = 0; i < nodesV_.size(); ++i)
  625.         {
  626.             Node* otherNode = nodesV_[i];
  627.  
  628.             // this first if statement controls the amount of links a node can have
  629.             // though each node will still only generate 4 links
  630.             if (otherNode->links_.size() < 9)
  631.             {
  632.                 f2 vec = position - otherNode->position_;
  633.  
  634.                 if (vec.x >= 0)
  635.                 {
  636.                     if (vec.y > 0)
  637.                     {
  638.                         if (!topRight)
  639.                         {
  640.                             if (straightPath(position, otherNode->position_, halfNodeSize_))
  641.                             {
  642.                                 topRight = true;
  643.                                 node->links_.push_back(otherNode);
  644.                                 otherNode->links_.push_back(node);
  645.                             }
  646.                         }
  647.                     }
  648.                     else
  649.                     {
  650.                         if (!bottomRight)
  651.                         {
  652.                             if (straightPath(position, otherNode->position_))
  653.                             {
  654.                                 bottomRight = true;
  655.                                 node->links_.push_back(otherNode);
  656.                                 otherNode->links_.push_back(node);
  657.                             }
  658.                         }
  659.                     }
  660.                 }
  661.                 else
  662.                 {
  663.                     if (vec.y >= 0)
  664.                     {
  665.                         if (!topLeft)
  666.                         {
  667.                             if (straightPath(position, otherNode->position_, halfNodeSize_))
  668.                             {
  669.                                 topLeft = true;
  670.                                 node->links_.push_back(otherNode);
  671.                                 otherNode->links_.push_back(node);
  672.                             }
  673.                         }
  674.                     }
  675.                     else
  676.                     {
  677.                         if (!bottomLeft)
  678.                         {
  679.                             if (straightPath(position, otherNode->position_, halfNodeSize_))
  680.                             {
  681.                                 bottomLeft = true;
  682.                                 node->links_.push_back(otherNode);
  683.                                 otherNode->links_.push_back(node);
  684.                             }
  685.                         }
  686.                     }
  687.                 }
  688.             }
  689.             if (topLeft && topRight && bottomRight && bottomLeft)
  690.             {
  691.                 break;
  692.             }
  693.         }
  694.         nodesV_.push_back(node);
  695.         nodes_[position] = node;
  696.         return node;
  697.     }
  698.  
  699.     inline void removeNode(Node* node)
  700.     {
  701.         for (int i = 0; i < node->links_.size(); ++i)
  702.         {
  703.             for (int j = 0; j < node->links_[i]->links_.size(); ++j)
  704.             {
  705.                 if (node->links_[i]->links_[j] == node)
  706.                 {
  707.                     node->links_[i]->links_.erase(node->links_[i]->links_.begin() + j);
  708.                     break;
  709.                 }
  710.             }
  711.         }
  712.  
  713.         nodesV_.erase(std::remove(nodesV_.begin(), nodesV_.end(), node), nodesV_.end());
  714.  
  715.         nodes_.erase(node->position_);
  716.  
  717.         delete(node);
  718.     }
  719.  
  720.     inline void generateNodes(const vector<Rect>& obstacles)
  721.     {
  722.         for (int i = 0; i < obstacles.size(); ++i)
  723.         {
  724.             for (int x = - 1; x < 2; x += 2)
  725.             {
  726.                 for (int y = - 1; y < 2; y += 2)
  727.                 {
  728.                     addNode(obstacles[i].center() + f2(x * ((obstacles[i].width / 2) + (halfNodeSize_.x + 1)),
  729.                                             y * ((obstacles[i].height / 2) + (halfNodeSize_.y + 1))));
  730.                 }
  731.             }
  732.         }
  733.     }
  734.  
  735.     inline void update()
  736.     {
  737.         nodesV_.clear();
  738.         nodes_.clear();
  739.         // std::sort(obstacles_.begin(), obstacles_.end(), );
  740.         generateNodes(obstacles_);
  741.     }
  742.  
  743.     bool checkPath(vector<f2> path)
  744.     {
  745.         for (int i = 1; i < path.size(); ++i)
  746.         {
  747.             if (!straightPath(path[i - 1], path[i]))
  748.             {
  749.                 return false;
  750.             }
  751.         }
  752.         return true;
  753.     }
  754.  
  755. f2 position_;
  756. f2 gridSize_;
  757. f2 nodeSize_;
  758. f2 halfNodeSize_;
  759. vector<Rect> obstacles_;
  760. unordered_map<f2, Node*> nodes_;
  761. vector<Node*> nodesV_;
  762. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement