KdTree2d.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * KdTree2d.cpp
  3. * RVO2 Library
  4. *
  5. * Copyright 2008 University of North Carolina at Chapel Hill
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * Please send all bug reports to <geom@cs.unc.edu>.
  20. *
  21. * The authors may be contacted via:
  22. *
  23. * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
  24. * Dept. of Computer Science
  25. * 201 S. Columbia St.
  26. * Frederick P. Brooks, Jr. Computer Science Bldg.
  27. * Chapel Hill, N.C. 27599-3175
  28. * United States of America
  29. *
  30. * <http://gamma.cs.unc.edu/RVO2/>
  31. */
  32. #include "KdTree2d.h"
  33. #include "Agent2d.h"
  34. #include "RVOSimulator2d.h"
  35. #include "Obstacle2d.h"
  36. namespace RVO2D {
  37. KdTree2D::KdTree2D(RVOSimulator2D *sim) : obstacleTree_(NULL), sim_(sim) { }
  38. KdTree2D::~KdTree2D()
  39. {
  40. deleteObstacleTree(obstacleTree_);
  41. }
  42. void KdTree2D::buildAgentTree(std::vector<Agent2D *> agents)
  43. {
  44. agents_.swap(agents);
  45. if (!agents_.empty()) {
  46. agentTree_.resize(2 * agents_.size() - 1);
  47. buildAgentTreeRecursive(0, agents_.size(), 0);
  48. }
  49. }
  50. void KdTree2D::buildAgentTreeRecursive(size_t begin, size_t end, size_t node)
  51. {
  52. agentTree_[node].begin = begin;
  53. agentTree_[node].end = end;
  54. agentTree_[node].minX = agentTree_[node].maxX = agents_[begin]->position_.x();
  55. agentTree_[node].minY = agentTree_[node].maxY = agents_[begin]->position_.y();
  56. for (size_t i = begin + 1; i < end; ++i) {
  57. agentTree_[node].maxX = std::max(agentTree_[node].maxX, agents_[i]->position_.x());
  58. agentTree_[node].minX = std::min(agentTree_[node].minX, agents_[i]->position_.x());
  59. agentTree_[node].maxY = std::max(agentTree_[node].maxY, agents_[i]->position_.y());
  60. agentTree_[node].minY = std::min(agentTree_[node].minY, agents_[i]->position_.y());
  61. }
  62. if (end - begin > MAX_LEAF_SIZE) {
  63. /* No leaf node. */
  64. const bool isVertical = (agentTree_[node].maxX - agentTree_[node].minX > agentTree_[node].maxY - agentTree_[node].minY);
  65. const float splitValue = (isVertical ? 0.5f * (agentTree_[node].maxX + agentTree_[node].minX) : 0.5f * (agentTree_[node].maxY + agentTree_[node].minY));
  66. size_t left = begin;
  67. size_t right = end;
  68. while (left < right) {
  69. while (left < right && (isVertical ? agents_[left]->position_.x() : agents_[left]->position_.y()) < splitValue) {
  70. ++left;
  71. }
  72. while (right > left && (isVertical ? agents_[right - 1]->position_.x() : agents_[right - 1]->position_.y()) >= splitValue) {
  73. --right;
  74. }
  75. if (left < right) {
  76. std::swap(agents_[left], agents_[right - 1]);
  77. ++left;
  78. --right;
  79. }
  80. }
  81. if (left == begin) {
  82. ++left;
  83. ++right;
  84. }
  85. agentTree_[node].left = node + 1;
  86. agentTree_[node].right = node + 2 * (left - begin);
  87. buildAgentTreeRecursive(begin, left, agentTree_[node].left);
  88. buildAgentTreeRecursive(left, end, agentTree_[node].right);
  89. }
  90. }
  91. void KdTree2D::buildObstacleTree(std::vector<Obstacle2D *> obstacles)
  92. {
  93. deleteObstacleTree(obstacleTree_);
  94. obstacleTree_ = buildObstacleTreeRecursive(obstacles);
  95. }
  96. KdTree2D::ObstacleTreeNode *KdTree2D::buildObstacleTreeRecursive(const std::vector<Obstacle2D *> &obstacles)
  97. {
  98. if (obstacles.empty()) {
  99. return NULL;
  100. }
  101. else {
  102. ObstacleTreeNode *const node = new ObstacleTreeNode;
  103. size_t optimalSplit = 0;
  104. size_t minLeft = obstacles.size();
  105. size_t minRight = obstacles.size();
  106. for (size_t i = 0; i < obstacles.size(); ++i) {
  107. size_t leftSize = 0;
  108. size_t rightSize = 0;
  109. const Obstacle2D *const obstacleI1 = obstacles[i];
  110. const Obstacle2D *const obstacleI2 = obstacleI1->nextObstacle_;
  111. /* Compute optimal split node. */
  112. for (size_t j = 0; j < obstacles.size(); ++j) {
  113. if (i == j) {
  114. continue;
  115. }
  116. const Obstacle2D *const obstacleJ1 = obstacles[j];
  117. const Obstacle2D *const obstacleJ2 = obstacleJ1->nextObstacle_;
  118. const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
  119. const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);
  120. if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
  121. ++leftSize;
  122. }
  123. else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
  124. ++rightSize;
  125. }
  126. else {
  127. ++leftSize;
  128. ++rightSize;
  129. }
  130. if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) >= std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
  131. break;
  132. }
  133. }
  134. if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) < std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
  135. minLeft = leftSize;
  136. minRight = rightSize;
  137. optimalSplit = i;
  138. }
  139. }
  140. /* Build split node. */
  141. std::vector<Obstacle2D *> leftObstacles(minLeft);
  142. std::vector<Obstacle2D *> rightObstacles(minRight);
  143. size_t leftCounter = 0;
  144. size_t rightCounter = 0;
  145. const size_t i = optimalSplit;
  146. const Obstacle2D *const obstacleI1 = obstacles[i];
  147. const Obstacle2D *const obstacleI2 = obstacleI1->nextObstacle_;
  148. for (size_t j = 0; j < obstacles.size(); ++j) {
  149. if (i == j) {
  150. continue;
  151. }
  152. Obstacle2D *const obstacleJ1 = obstacles[j];
  153. Obstacle2D *const obstacleJ2 = obstacleJ1->nextObstacle_;
  154. const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
  155. const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);
  156. if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
  157. leftObstacles[leftCounter++] = obstacles[j];
  158. }
  159. else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
  160. rightObstacles[rightCounter++] = obstacles[j];
  161. }
  162. else {
  163. /* Split obstacle j. */
  164. const float t = det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleI1->point_) / det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleJ2->point_);
  165. const Vector2 splitpoint = obstacleJ1->point_ + t * (obstacleJ2->point_ - obstacleJ1->point_);
  166. Obstacle2D *const newObstacle = new Obstacle2D();
  167. newObstacle->point_ = splitpoint;
  168. newObstacle->prevObstacle_ = obstacleJ1;
  169. newObstacle->nextObstacle_ = obstacleJ2;
  170. newObstacle->isConvex_ = true;
  171. newObstacle->unitDir_ = obstacleJ1->unitDir_;
  172. newObstacle->id_ = sim_->obstacles_.size();
  173. sim_->obstacles_.push_back(newObstacle);
  174. obstacleJ1->nextObstacle_ = newObstacle;
  175. obstacleJ2->prevObstacle_ = newObstacle;
  176. if (j1LeftOfI > 0.0f) {
  177. leftObstacles[leftCounter++] = obstacleJ1;
  178. rightObstacles[rightCounter++] = newObstacle;
  179. }
  180. else {
  181. rightObstacles[rightCounter++] = obstacleJ1;
  182. leftObstacles[leftCounter++] = newObstacle;
  183. }
  184. }
  185. }
  186. node->obstacle = obstacleI1;
  187. node->left = buildObstacleTreeRecursive(leftObstacles);
  188. node->right = buildObstacleTreeRecursive(rightObstacles);
  189. return node;
  190. }
  191. }
  192. void KdTree2D::computeAgentNeighbors(Agent2D *agent, float &rangeSq) const
  193. {
  194. queryAgentTreeRecursive(agent, rangeSq, 0);
  195. }
  196. void KdTree2D::computeObstacleNeighbors(Agent2D *agent, float rangeSq) const
  197. {
  198. queryObstacleTreeRecursive(agent, rangeSq, obstacleTree_);
  199. }
  200. void KdTree2D::deleteObstacleTree(ObstacleTreeNode *node)
  201. {
  202. if (node != NULL) {
  203. deleteObstacleTree(node->left);
  204. deleteObstacleTree(node->right);
  205. delete node;
  206. }
  207. }
  208. void KdTree2D::queryAgentTreeRecursive(Agent2D *agent, float &rangeSq, size_t node) const
  209. {
  210. if (agentTree_[node].end - agentTree_[node].begin <= MAX_LEAF_SIZE) {
  211. for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
  212. agent->insertAgentNeighbor(agents_[i], rangeSq);
  213. }
  214. }
  215. else {
  216. const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxY));
  217. const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxY));
  218. if (distSqLeft < distSqRight) {
  219. if (distSqLeft < rangeSq) {
  220. queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
  221. if (distSqRight < rangeSq) {
  222. queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
  223. }
  224. }
  225. }
  226. else {
  227. if (distSqRight < rangeSq) {
  228. queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
  229. if (distSqLeft < rangeSq) {
  230. queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
  231. }
  232. }
  233. }
  234. }
  235. }
  236. void KdTree2D::queryObstacleTreeRecursive(Agent2D *agent, float rangeSq, const ObstacleTreeNode *node) const
  237. {
  238. if (node == NULL) {
  239. return;
  240. }
  241. else {
  242. const Obstacle2D *const obstacle1 = node->obstacle;
  243. const Obstacle2D *const obstacle2 = obstacle1->nextObstacle_;
  244. const float agentLeftOfLine = leftOf(obstacle1->point_, obstacle2->point_, agent->position_);
  245. queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0.0f ? node->left : node->right));
  246. const float distSqLine = sqr(agentLeftOfLine) / absSq(obstacle2->point_ - obstacle1->point_);
  247. if (distSqLine < rangeSq) {
  248. if (agentLeftOfLine < 0.0f) {
  249. /*
  250. * Try obstacle at this node only if agent is on right side of
  251. * obstacle (and can see obstacle).
  252. */
  253. agent->insertObstacleNeighbor(node->obstacle, rangeSq);
  254. }
  255. /* Try other side of line. */
  256. queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0.0f ? node->right : node->left));
  257. }
  258. }
  259. }
  260. bool KdTree2D::queryVisibility(const Vector2 &q1, const Vector2 &q2, float radius) const
  261. {
  262. return queryVisibilityRecursive(q1, q2, radius, obstacleTree_);
  263. }
  264. bool KdTree2D::queryVisibilityRecursive(const Vector2 &q1, const Vector2 &q2, float radius, const ObstacleTreeNode *node) const
  265. {
  266. if (node == NULL) {
  267. return true;
  268. }
  269. else {
  270. const Obstacle2D *const obstacle1 = node->obstacle;
  271. const Obstacle2D *const obstacle2 = obstacle1->nextObstacle_;
  272. const float q1LeftOfI = leftOf(obstacle1->point_, obstacle2->point_, q1);
  273. const float q2LeftOfI = leftOf(obstacle1->point_, obstacle2->point_, q2);
  274. const float invLengthI = 1.0f / absSq(obstacle2->point_ - obstacle1->point_);
  275. if (q1LeftOfI >= 0.0f && q2LeftOfI >= 0.0f) {
  276. return queryVisibilityRecursive(q1, q2, radius, node->left) && ((sqr(q1LeftOfI) * invLengthI >= sqr(radius) && sqr(q2LeftOfI) * invLengthI >= sqr(radius)) || queryVisibilityRecursive(q1, q2, radius, node->right));
  277. }
  278. else if (q1LeftOfI <= 0.0f && q2LeftOfI <= 0.0f) {
  279. return queryVisibilityRecursive(q1, q2, radius, node->right) && ((sqr(q1LeftOfI) * invLengthI >= sqr(radius) && sqr(q2LeftOfI) * invLengthI >= sqr(radius)) || queryVisibilityRecursive(q1, q2, radius, node->left));
  280. }
  281. else if (q1LeftOfI >= 0.0f && q2LeftOfI <= 0.0f) {
  282. /* One can see through obstacle from left to right. */
  283. return queryVisibilityRecursive(q1, q2, radius, node->left) && queryVisibilityRecursive(q1, q2, radius, node->right);
  284. }
  285. else {
  286. const float point1LeftOfQ = leftOf(q1, q2, obstacle1->point_);
  287. const float point2LeftOfQ = leftOf(q1, q2, obstacle2->point_);
  288. const float invLengthQ = 1.0f / absSq(q2 - q1);
  289. return (point1LeftOfQ * point2LeftOfQ >= 0.0f && sqr(point1LeftOfQ) * invLengthQ > sqr(radius) && sqr(point2LeftOfQ) * invLengthQ > sqr(radius) && queryVisibilityRecursive(q1, q2, radius, node->left) && queryVisibilityRecursive(q1, q2, radius, node->right));
  290. }
  291. }
  292. }
  293. }