DynamicTree.cpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2009 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 
25 #include <PlayRho/Common/Math.hpp>
27 
28 #include <cstring>
29 #include <algorithm>
30 #include <numeric>
31 #include <utility>
32 
33 namespace playrho {
34 namespace d2 {
35 
36 namespace {
37 
38 inline DynamicTree::TreeNode
39 MakeNode(DynamicTree::Size c1, const AABB& aabb1, DynamicTree::Height h1,
40  DynamicTree::Size c2, const AABB& aabb2, DynamicTree::Height h2,
41  DynamicTree::Size parent) noexcept
42 {
43  return DynamicTree::TreeNode{
44  DynamicTree::BranchData{c1, c2}, GetEnclosingAABB(aabb1, aabb2), 1 + std::max(h1, h2), parent
45  };
46 }
47 
48 std::pair<DynamicTree::Size, DynamicTree::Size>
49 MakeMoveStay(const DynamicTree::TreeNode& nodeA, DynamicTree::Size indexA,
50  const DynamicTree::TreeNode& nodeB, DynamicTree::Size indexB,
51  const AABB& toBox) noexcept
52 {
53  if (nodeA.GetHeight() < nodeB.GetHeight())
54  {
55  return std::make_pair(indexA, indexB);
56  }
57  if (nodeB.GetHeight() < nodeA.GetHeight())
58  {
59  return std::make_pair(indexB, indexA);
60  }
61  const auto perimA = GetPerimeter(GetEnclosingAABB(toBox, nodeA.GetAABB()));
62  const auto perimB = GetPerimeter(GetEnclosingAABB(toBox, nodeB.GetAABB()));
63  if (perimA < perimB)
64  {
65  return std::make_pair(indexA, indexB);
66  }
67  if (perimB < perimA)
68  {
69  return std::make_pair(indexB, indexA);
70  }
71  return std::make_pair(indexA, indexB);
72 }
73 
74 DynamicTree::Size RebalanceAt(DynamicTree::TreeNode nodes[], DynamicTree::Size i) noexcept
75 {
76  //assert(index < GetNodeCapacity());
77  assert(DynamicTree::IsBranch(nodes[i].GetHeight()));
78 
79  // o
80  // |
81  // i
82  // / \
83  // *-c1 c2-*
84  // / | | \
85  // c1c1 c1c2 c2c1 c2c2
86  const auto oldNodeI = nodes[i];
87  const auto o = oldNodeI.GetOther();
88  const auto c1 = oldNodeI.AsBranch().child1;
89  const auto c2 = oldNodeI.AsBranch().child2;
90  auto c1Node = nodes[c1];
91  auto c2Node = nodes[c2];
92  const auto c1Height = c1Node.GetHeight();
93  const auto c2Height = c2Node.GetHeight();
94 
95  if (c2Height > (c1Height + 1))
96  {
97  // child 2 heavier than child 1, child 2 must be branch, rotate it up.
98  const auto c2c1 = c2Node.AsBranch().child1;
99  const auto c2c2 = c2Node.AsBranch().child2;
100  const auto c2c1Node = nodes[c2c1];
101  const auto c2c2Node = nodes[c2c2];
102 
103  // From:
104  // *i*
105  // / \
106  // c1 c2*
107  // / \
108  // c2c1 c2c2
109  // where c2c1 or c2c2 is also a branch node
110  //
111  // To:
112  // c2*
113  // / \
114  // *i* c2cY
115  // / \
116  // c1 c2cX
117  //
118  // Rotate left and pick the taller of c2c1 or c2c2 or the better fitting to move to the new i node.
119  const auto ms = MakeMoveStay(c2c1Node, c2c1, c2c2Node, c2c2, c1Node.GetAABB());
120  const auto newNodeI = MakeNode(c1, c1Node.GetAABB(), c1Height,
121  ms.first, nodes[ms.first].GetAABB(), nodes[ms.first].GetHeight(),
122  c2);
123  c2Node = MakeNode(i, newNodeI.GetAABB(), newNodeI.GetHeight(),
124  ms.second, nodes[ms.second].GetAABB(), nodes[ms.second].GetHeight(),
125  o);
126  nodes[ms.first].SetOther(i);
127  nodes[i] = newNodeI;
128  nodes[c2] = c2Node;
129  if (o != DynamicTree::GetInvalidSize())
130  {
131  const auto oNode = nodes[o];
132  const auto oNodeBD = oNode.AsBranch();
133  assert(oNodeBD.child1 == i || oNodeBD.child2 == i);
134  nodes[o] = (oNodeBD.child1 == i)?
135  MakeNode(c2, c2Node.GetAABB(), c2Node.GetHeight(),
136  oNodeBD.child2, nodes[oNodeBD.child2].GetAABB(), nodes[oNodeBD.child2].GetHeight(),
137  oNode.GetOther()):
138  MakeNode(oNodeBD.child1, nodes[oNodeBD.child1].GetAABB(), nodes[oNodeBD.child1].GetHeight(),
139  c2, c2Node.GetAABB(), c2Node.GetHeight(),
140  oNode.GetOther());
141  }
142  return c2;
143  }
144 
145  if (c1Height > (c2Height + 1))
146  {
147  // child1 must be a branch, rotate it up.
148  const auto c1c1 = c1Node.AsBranch().child1;
149  const auto c1c2 = c1Node.AsBranch().child2;
150  const auto c1c1Node = nodes[c1c1];
151  const auto c1c2Node = nodes[c1c2];
152 
153  // From:
154  // *i*
155  // / \
156  // *c1 c2*
157  // / \
158  // c1c1 c1c2
159  // where c1c1 or c1c2 is also a branch node
160  //
161  // To:
162  // c1*
163  // / \
164  // c1cX *i*
165  // / \
166  // c1cY c2
167  //
168  // Rotate right and pick the taller of c1c1 or c1c2 or the better fitting to move to the new i node.
169  const auto ms = MakeMoveStay(c1c1Node, c1c1, c1c2Node, c1c2, c2Node.GetAABB());
170  const auto newNodeI = MakeNode(ms.first, nodes[ms.first].GetAABB(), nodes[ms.first].GetHeight(),
171  c2, c2Node.GetAABB(), c2Height,
172  c1);
173  c1Node = MakeNode(ms.second, nodes[ms.second].GetAABB(), nodes[ms.second].GetHeight(),
174  i, newNodeI.GetAABB(), newNodeI.GetHeight(),
175  o);
176  nodes[ms.first].SetOther(i);
177  nodes[i] = newNodeI;
178  nodes[c1] = c1Node;
179  if (o != DynamicTree::GetInvalidSize())
180  {
181  const auto oNode = nodes[o];
182  const auto oNodeBD = oNode.AsBranch();
183  assert(oNodeBD.child1 == i || oNodeBD.child2 == i);
184  nodes[o] = (oNodeBD.child1 == i)?
185  MakeNode(c1, c1Node.GetAABB(), c1Node.GetHeight(),
186  oNodeBD.child2, nodes[oNodeBD.child2].GetAABB(), nodes[oNodeBD.child2].GetHeight(),
187  oNode.GetOther()):
188  MakeNode(oNodeBD.child1, nodes[oNodeBD.child1].GetAABB(), nodes[oNodeBD.child1].GetHeight(),
189  c1, c1Node.GetAABB(), c1Node.GetHeight(),
190  oNode.GetOther());
191  }
192  return c1;
193  }
194 
195  nodes[i] = MakeNode(c1, c1Node.GetAABB(), c1Node.GetHeight(), c2, c2Node.GetAABB(), c2Height, o);
196  return i;
197 }
198 
202 DynamicTree::Size UpdateUpwardFrom(DynamicTree::TreeNode nodes[], DynamicTree::Size start) noexcept
203 {
204  assert(DynamicTree::IsBranch(nodes[start].GetHeight()));
205  auto rootIndex = DynamicTree::GetInvalidSize();
206  for (auto index = start; index != DynamicTree::GetInvalidSize(); index = nodes[index].GetOther())
207  {
208  assert(DynamicTree::IsBranch(nodes[index].GetHeight()));
209  assert(nodes[nodes[index].AsBranch().child1].GetOther() == index);
210  assert(nodes[nodes[index].AsBranch().child2].GetOther() == index);
211  if (nodes[index].GetHeight() >= 2)
212  {
213  index = RebalanceAt(nodes, index);
214  }
215  rootIndex = index;
216  }
217  return rootIndex;
218 }
219 
225 DynamicTree::Size FindLowestCostNode(const DynamicTree::TreeNode nodes[],
226  AABB leafAABB, DynamicTree::Size index) noexcept
227 {
228  assert(IsValid(leafAABB));
229  assert(index != DynamicTree::GetInvalidSize());
230  assert(!playrho::d2::IsUnused(nodes[index]));
231 
232  // Cost function to calculate cost of descending into specified child
233  const auto costFunc = [leafAABB](const DynamicTree::TreeNode& childNode, Length inheritCost) {
234  const auto childAabb = playrho::d2::GetAABB(childNode);
235  const auto isLeaf = playrho::d2::IsLeaf(childNode);
236  const auto leafCost = GetPerimeter(GetEnclosingAABB(leafAABB, childAabb)) + inheritCost;
237  return isLeaf? leafCost: (leafCost - GetPerimeter(childAabb));
238  };
239 
240  while (playrho::d2::IsBranch(nodes[index]))
241  {
242  const auto& node = nodes[index];
243  const auto branch = node.AsBranch();
244  const auto child1 = branch.child1;
245  const auto child2 = branch.child2;
246  assert(nodes[child1].GetOther() == index);
247  assert(nodes[child2].GetOther() == index);
248  const auto aabb = node.GetAABB();
249  const auto perimeter = GetPerimeter(aabb);
250  const auto combinedPerimeter = GetPerimeter(GetEnclosingAABB(aabb, leafAABB));
251 
252  assert(combinedPerimeter >= perimeter);
253  assert(child1 != DynamicTree::GetInvalidSize());
254  assert(child2 != DynamicTree::GetInvalidSize());
255 
256  // Cost of creating a new parent for this node and the new leaf
257  const auto cost = combinedPerimeter * 2;
258 
259  // Minimum cost of pushing the leaf further down the tree
260  const auto inheritanceCost = (combinedPerimeter - perimeter) * 2;
261 
262  const auto cost1 = costFunc(nodes[child1], inheritanceCost);
263  const auto cost2 = costFunc(nodes[child2], inheritanceCost);
264 
265  if ((cost < cost1) && (cost < cost2))
266  {
267  // Cheaper to create a new parent for this node and the new leaf
268  break;
269  }
270 
271  // Descend into child with least cost.
272  index = (cost1 < cost2)? child1: child2;
273  }
274  return index;
275 }
276 
277 std::pair<DynamicTree::Size, DynamicTree::Size>
278 RemoveParent(DynamicTree::TreeNode nodes[], DynamicTree::Size index) noexcept
279 {
280  const auto parent = nodes[index].GetOther();
281  const auto grandParent = nodes[parent].GetOther();
282  const auto parentBD = nodes[parent].AsBranch();
283  const auto sibling = (parentBD.child1 == index)? parentBD.child2: parentBD.child1;
284 
285  nodes[index].SetOther(DynamicTree::GetInvalidSize());
286  nodes[sibling].SetOther(grandParent);
287  if (grandParent != DynamicTree::GetInvalidSize())
288  {
289  const auto newBD = ReplaceChild(nodes[grandParent].AsBranch(), parent, sibling);
290  const auto newAabb = GetEnclosingAABB(nodes[newBD.child1].GetAABB(), nodes[newBD.child2].GetAABB());
291  const auto newHeight = 1 + std::max(nodes[newBD.child1].GetHeight(), nodes[newBD.child2].GetHeight());
292  nodes[grandParent].Assign(newBD, newAabb, newHeight);
293  nodes[parent].SetOther(DynamicTree::GetInvalidSize());
294  return std::make_pair(UpdateUpwardFrom(nodes, grandParent), parent);
295  }
296  return std::make_pair(sibling, parent);
297 }
298 
299 DynamicTree::Size InsertParent(DynamicTree::TreeNode nodes[],
300  DynamicTree::Size newParent,
301  const AABB& aabb,
302  DynamicTree::Size index,
303  DynamicTree::Size rootIndex) noexcept
304 {
305  const auto sibling = FindLowestCostNode(nodes, aabb, rootIndex);
306  const auto oldParent = nodes[sibling].GetOther();
307 
308  // std::max of leaf height and sibling height + 1 = sibling height + 1
309  nodes[newParent] = DynamicTree::TreeNode{DynamicTree::BranchData{sibling, index},
310  GetEnclosingAABB(aabb, nodes[sibling].GetAABB()), 1 + nodes[sibling].GetHeight(), oldParent};
311  nodes[sibling].SetOther(newParent);
312  nodes[index].SetOther(newParent);
313  if (oldParent != DynamicTree::GetInvalidSize())
314  {
315  const auto newBD = ReplaceChild(nodes[oldParent].AsBranch(), sibling, newParent);
316  const auto newAabb = GetEnclosingAABB(nodes[newBD.child1].GetAABB(), nodes[newBD.child2].GetAABB());
317  const auto newHeight = 1 + std::max(nodes[newBD.child1].GetHeight(), nodes[newBD.child2].GetHeight());
318  nodes[oldParent].Assign(newBD, newAabb, newHeight);
319  assert(nodes[nodes[oldParent].AsBranch().child1].GetOther() == oldParent);
320  assert(nodes[nodes[oldParent].AsBranch().child2].GetOther() == oldParent);
321  return UpdateUpwardFrom(nodes, oldParent);
322  }
323  return newParent;
324 }
325 
326 DynamicTree::Size UpdateNonRoot(DynamicTree::TreeNode nodes[],
327  DynamicTree::Size index, const AABB& aabb) noexcept
328 {
329  assert(nodes[index].GetOther() != DynamicTree::GetInvalidSize());
330 
331  const auto parent = nodes[index].GetOther();
332  const auto grandParent = nodes[parent].GetOther();
333  const auto parentBD = nodes[parent].AsBranch();
334  assert(parentBD.child1 == index || parentBD.child2 == index);
335  const auto sibling = (parentBD.child1 == index)? parentBD.child2: parentBD.child1;
336 
337  nodes[sibling].SetOther(grandParent);
338  nodes[index].SetAABB(aabb);
339  auto rootIndex = DynamicTree::GetInvalidSize();
340  if (grandParent != DynamicTree::GetInvalidSize())
341  {
342  assert(nodes[grandParent].AsBranch().child1 == parent || nodes[grandParent].AsBranch().child2 == parent);
343  const auto newBD = ReplaceChild(nodes[grandParent].AsBranch(), parent, sibling);
344  const auto newAabb = GetEnclosingAABB(nodes[newBD.child1].GetAABB(), nodes[newBD.child2].GetAABB());
345  const auto newHeight = 1 + std::max(nodes[newBD.child1].GetHeight(), nodes[newBD.child2].GetHeight());
346  nodes[grandParent].Assign(newBD, newAabb, newHeight);
347  nodes[parent].SetOther(DynamicTree::GetInvalidSize());
348  assert(nodes[nodes[grandParent].AsBranch().child1].GetOther() == grandParent);
349  assert(nodes[nodes[grandParent].AsBranch().child2].GetOther() == grandParent);
350  rootIndex = UpdateUpwardFrom(nodes, grandParent);
351  }
352  else // grandParent == GetInvalidSize()
353  {
354  rootIndex = sibling;
355  }
356 
357  const auto cheapest = FindLowestCostNode(nodes, aabb, rootIndex);
358  const auto cheapestParent = nodes[cheapest].GetOther();
359 
360  // std::max of leaf height and cheapest height + 1 = cheapest height + 1
361  nodes[parent] = DynamicTree::TreeNode{
362  DynamicTree::BranchData{cheapest, index},
363  GetEnclosingAABB(aabb, nodes[cheapest].GetAABB()),
364  1 + nodes[cheapest].GetHeight(), cheapestParent
365  };
366  if (cheapestParent != DynamicTree::GetInvalidSize())
367  {
368  const auto newBD = ReplaceChild(nodes[cheapestParent].AsBranch(), cheapest, parent);
369  const auto newAabb = GetEnclosingAABB(nodes[newBD.child1].GetAABB(), nodes[newBD.child2].GetAABB());
370  const auto newHeight = 1 + std::max(nodes[newBD.child1].GetHeight(), nodes[newBD.child2].GetHeight());
371  nodes[cheapestParent].Assign(newBD, newAabb, newHeight);
372  }
373  nodes[cheapest].SetOther(parent);
374  return UpdateUpwardFrom(nodes, parent);
375 }
376 
377 } // anonymous namespace
378 
379 DynamicTree::DynamicTree() noexcept = default;
380 
381 DynamicTree::DynamicTree(Size nodeCapacity):
382  m_nodes{nodeCapacity? Alloc<TreeNode>(nodeCapacity): nullptr},
383  m_freeIndex{nodeCapacity? 0: GetInvalidSize()},
384  m_nodeCapacity{nodeCapacity}
385 {
386  if (nodeCapacity)
387  {
388  // Build a linked list for the free list.
389  const auto endCapacity = nodeCapacity - Size{1};
390  for (auto i = decltype(nodeCapacity){0}; i < endCapacity; ++i)
391  {
392  new (&m_nodes[i]) TreeNode{i + 1};
393  }
394  new (&m_nodes[endCapacity]) TreeNode{};
395  }
396 }
397 
399  m_nodes{Alloc<TreeNode>(other.m_nodeCapacity)},
400  m_rootIndex{other.m_rootIndex},
401  m_freeIndex{other.m_freeIndex},
402  m_nodeCount{other.m_nodeCount},
403  m_nodeCapacity{other.m_nodeCapacity},
404  m_leafCount{other.m_leafCount}
405 {
406  std::copy(&other.m_nodes[0], &other.m_nodes[other.m_nodeCapacity], &m_nodes[0]);
407 }
408 
410  DynamicTree{}
411 {
412  swap(*this, other);
413 }
414 
416 {
417  // Leverages the "copy-and-swap" idiom.
418  // For details, see https://stackoverflow.com/a/3279550/7410358
419  swap(*this, other);
420  return *this;
421 }
422 
424 {
425  // This frees the entire tree in one shot.
426  Free(m_nodes);
427 }
428 
429 void DynamicTree::SetNodeCapacity(Size value) noexcept
430 {
431  assert(value > m_nodeCapacity);
432 
433  // The free list is empty. Rebuild a bigger pool.
434  m_nodeCapacity = value;
435  m_nodes = Realloc<TreeNode>(m_nodes, m_nodeCapacity);
436 
437  // Build a linked list for the free list. The parent
438  // pointer becomes the "next" pointer.
439  const auto endCapacity = m_nodeCapacity - 1;
440  for (auto i = m_nodeCount; i < endCapacity; ++i)
441  {
442  new (m_nodes + i) TreeNode{i + 1};
443  }
444  new (m_nodes + endCapacity) TreeNode{};
445  m_freeIndex = m_nodeCount;
446 }
447 
448 DynamicTree::Size DynamicTree::AllocateNode(const LeafData& data, AABB aabb) noexcept
449 {
450  const auto index = AllocateNode();
451  m_nodes[index] = TreeNode{data, aabb};
452  return index;
453 }
454 
455 DynamicTree::Size DynamicTree::AllocateNode(const BranchData& data, AABB aabb,
456  Height height, Size parent) noexcept
457 {
458  assert(height > 0);
459  const auto index = AllocateNode();
460  m_nodes[index] = TreeNode{data, aabb, height, parent};
461  return index;
462 }
463 
464 DynamicTree::Size DynamicTree::AllocateNode() noexcept
465 {
466  // Expand the node pool as needed.
467  if (m_freeIndex == GetInvalidSize())
468  {
469  assert(m_nodeCount == m_nodeCapacity);
470 
471  // The free list is empty. Rebuild a bigger pool.
472  SetNodeCapacity(m_nodeCapacity? m_nodeCapacity * 2: GetDefaultInitialNodeCapacity());
473  }
474 
475  // Peel a node off the free list.
476  const auto index = m_freeIndex;
477  m_freeIndex = m_nodes[index].GetOther();
478  ++m_nodeCount;
479  return index;
480 }
481 
482 void DynamicTree::FreeNode(Size index) noexcept
483 {
484  assert(index != GetInvalidSize());
485  assert(index < GetNodeCapacity());
486  assert(index != GetFreeIndex());
487  assert(m_nodeCount > 0); // index is not necessarily less than m_nodeCount.
488  assert(!IsUnused(m_nodes[index].GetHeight()));
489  assert(m_nodes[index].GetOther() == GetInvalidSize());
490 
491  m_nodes[index] = TreeNode{m_freeIndex};
492  m_freeIndex = index;
493  --m_nodeCount;
494 }
495 
497 {
498  const auto it = std::find_if(m_nodes, m_nodes + m_nodeCapacity, [&](TreeNode& node) {
499  if (node.GetOther() == index)
500  {
501  return true;
502  }
503  if (IsBranch(node.GetHeight()))
504  {
505  const auto bd = node.AsBranch();
506  if (bd.child1 == index || bd.child2 == index)
507  {
508  return true;
509  }
510  }
511  return false;
512  });
513  return (it != m_nodes + m_nodeCapacity)? static_cast<Size>(it - m_nodes): GetInvalidSize();
514 }
515 
516 DynamicTree::Size DynamicTree::CreateLeaf(const AABB& aabb, const LeafData& data)
517 {
518  assert(IsValid(aabb));
519  const auto index = AllocateNode(data, aabb);
520  if (m_rootIndex != GetInvalidSize())
521  {
522  const auto newParent = AllocateNode(); // Note: may change m_nodes!
523  m_rootIndex = InsertParent(m_nodes, newParent, aabb, index, m_rootIndex);
524  }
525  else
526  {
527  m_rootIndex = index;
528  }
529  ++m_leafCount;
530  return index;
531 }
532 
533 void DynamicTree::DestroyLeaf(Size index) noexcept
534 {
535  assert(index != GetInvalidSize());
536  assert(index < m_nodeCapacity);
537  assert(IsLeaf(m_nodes[index].GetHeight()));
538  assert(m_leafCount > 0);
539 
540  --m_leafCount;
541 
542  if (m_rootIndex != index)
543  {
544  const auto result = RemoveParent(m_nodes, index);
545  m_rootIndex = std::get<0>(result);
546  const auto parent = std::get<1>(result);
547 #ifndef NDEBUG
548  const auto found = FindReference(parent);
549  assert(found == GetInvalidSize());
550 #endif
551  FreeNode(parent);
552  }
553  else
554  {
555  assert(m_nodes[index].GetOther() == GetInvalidSize());
556  m_rootIndex = GetInvalidSize();
557  }
558 
559 #ifndef NDEBUG
560  const auto found = FindReference(index);
561  assert(found == GetInvalidSize());
562 #endif
563  FreeNode(index);
564 }
565 
566 void DynamicTree::UpdateLeaf(Size index, const AABB& aabb)
567 {
568  assert(index != GetInvalidSize());
569  assert(index < m_nodeCapacity);
570  assert(IsLeaf(m_nodes[index].GetHeight()));
571 
572  if (m_rootIndex != index)
573  {
574  m_rootIndex = UpdateNonRoot(m_nodes, index, aabb);
575  }
576  else
577  {
578  assert(m_nodes[index].GetOther() == GetInvalidSize());
579  m_nodes[index].SetAABB(aabb);
580  }
581 }
582 
583 void DynamicTree::RebuildBottomUp()
584 {
585  const auto nodes = Alloc<Size>(m_nodeCount);
586  auto count = Size{0};
587 
588  // Build array of leaves. Free the rest.
589  for (auto i = decltype(m_nodeCapacity){0}; i < m_nodeCapacity; ++i)
590  {
591  const auto height = m_nodes[i].GetHeight();
592  if (IsLeaf(height))
593  {
594  m_nodes[i].SetOther(GetInvalidSize());
595  nodes[count] = i;
596  ++count;
597  }
598  else if (IsBranch(height))
599  {
600  m_nodes[i].SetOther(GetInvalidSize());
601  FreeNode(i);
602  }
603  }
604 
605  while (count > 1)
606  {
607  auto minCost = std::numeric_limits<Length>::infinity();
608  auto iMin = GetInvalidSize();
609  auto jMin = GetInvalidSize();
610  for (auto i = decltype(count){0}; i < count; ++i)
611  {
612  const auto& aabbi = m_nodes[nodes[i]].GetAABB();
613 
614  for (auto j = i + 1; j < count; ++j)
615  {
616  const auto& aabbj = m_nodes[nodes[j]].GetAABB();
617  const auto b = GetEnclosingAABB(aabbi, aabbj);
618  const auto cost = GetPerimeter(b);
619  if (minCost > cost)
620  {
621  iMin = i;
622  jMin = j;
623  minCost = cost;
624  }
625  }
626  }
627 
628  assert((iMin < m_nodeCount) && (jMin < m_nodeCount));
629 
630  const auto index1 = nodes[iMin];
631  const auto index2 = nodes[jMin];
632  assert(!IsUnused(m_nodes[index1].GetHeight()));
633  assert(!IsUnused(m_nodes[index2].GetHeight()));
634 
635  const auto aabb = GetEnclosingAABB(m_nodes[index1].GetAABB(), m_nodes[index2].GetAABB());
636  const auto height = 1 + std::max(m_nodes[index1].GetHeight(), m_nodes[index2].GetHeight());
637 
638  // Warning: the following may change value of m_nodes!
639  const auto parent = AllocateNode(BranchData{index1, index2}, aabb, height);
640  m_nodes[index1].SetOther(parent);
641  m_nodes[index2].SetOther(parent);
642 
643  nodes[jMin] = nodes[count-1];
644  nodes[iMin] = parent;
645  --count;
646  }
647 
648  m_rootIndex = nodes[0];
649  Free(nodes);
650 }
651 
652 void DynamicTree::ShiftOrigin(Length2 newOrigin)
653 {
654  // Build array of leaves. Free the rest.
655  for (auto i = decltype(m_nodeCapacity){0}; i < m_nodeCapacity; ++i)
656  {
657  if (!IsUnused(m_nodes[i].GetHeight()))
658  {
659  m_nodes[i].SetAABB(GetMovedAABB(m_nodes[i].GetAABB(), -newOrigin));
660  }
661  }
662 }
663 
664 // Free functions...
665 
666 void swap(DynamicTree& lhs, DynamicTree& rhs) noexcept
667 {
668  using playrho::swap;
669  swap(lhs.m_nodes, rhs.m_nodes);
670  swap(lhs.m_rootIndex, rhs.m_rootIndex);
671  swap(lhs.m_freeIndex, rhs.m_freeIndex);
672  swap(lhs.m_nodeCount, rhs.m_nodeCount);
673  swap(lhs.m_nodeCapacity, rhs.m_nodeCapacity);
674  swap(lhs.m_leafCount, rhs.m_leafCount);
675 }
676 
677 void Query(const DynamicTree& tree, const AABB& aabb, const DynamicTreeSizeCB& callback)
678 {
680  stack.push(tree.GetRootIndex());
681 
682  while (!empty(stack))
683  {
684  const auto index = stack.top();
685  stack.pop();
686  if (index != DynamicTree::GetInvalidSize())
687  {
688  if (TestOverlap(tree.GetAABB(index), aabb))
689  {
690  const auto height = tree.GetHeight(index);
691  if (DynamicTree::IsBranch(height))
692  {
693  const auto branchData = tree.GetBranchData(index);
694  stack.push(branchData.child1);
695  stack.push(branchData.child2);
696  }
697  else
698  {
699  assert(DynamicTree::IsLeaf(height));
700  const auto sc = callback(index);
701  if (sc == DynamicTreeOpcode::End)
702  {
703  return;
704  }
705  }
706  }
707  }
708  }
709 }
710 
711 void Query(const DynamicTree& tree, const AABB& aabb, QueryFixtureCallback callback)
712 {
713  Query(tree, aabb, [&](DynamicTree::Size treeId) {
714  const auto leafData = tree.GetLeafData(treeId);
715  return callback(leafData.fixture, leafData.childIndex)?
716  DynamicTreeOpcode::Continue: DynamicTreeOpcode::End;
717  });
718 }
719 
721 {
722  auto total = 0_m;
723  const auto nodeCapacity = tree.GetNodeCapacity();
724  for (auto i = decltype(nodeCapacity){0}; i < nodeCapacity; ++i)
725  {
726  if (!DynamicTree::IsUnused(tree.GetHeight(i)))
727  {
728  total += GetPerimeter(tree.GetAABB(i));
729  }
730  }
731  return total;
732 }
733 
735 {
736  const auto root = tree.GetRootIndex();
737  if (root != DynamicTree::GetInvalidSize())
738  {
739  const auto rootPerimeter = GetPerimeter(tree.GetAABB(root));
740  const auto total = ComputeTotalPerimeter(tree);
741  return total / rootPerimeter;
742  }
743  return 0;
744 }
745 
747 {
748  assert(index < tree.GetNodeCapacity());
749  if (DynamicTree::IsBranch(tree.GetHeight(index)))
750  {
751  const auto bd = tree.GetBranchData(index);
752  const auto height1 = ComputeHeight(tree, bd.child1);
753  const auto height2 = ComputeHeight(tree, bd.child2);
754  return 1 + std::max(height1, height2);
755  }
756  return 0;
757 }
758 
760 {
761  auto maxImbalance = DynamicTree::Height{0};
762  const auto nodeCapacity = tree.GetNodeCapacity();
763  for (auto i = decltype(nodeCapacity){0}; i < nodeCapacity; ++i)
764  {
765  if (DynamicTree::IsBranch(tree.GetHeight(i)))
766  {
767  const auto bd = tree.GetBranchData(i);
768  const auto height1 = tree.GetHeight(bd.child1);
769  const auto height2 = tree.GetHeight(bd.child2);
770  const auto imbalance = (height2 >= height1)? height2 - height1: height1 - height2;
771  maxImbalance = std::max(maxImbalance, imbalance);
772  }
773  }
774  return maxImbalance;
775 }
776 
777 bool ValidateStructure(const DynamicTree& tree, DynamicTree::Size index) noexcept
778 {
779  if (index == DynamicTree::GetInvalidSize())
780  {
781  return true;
782  }
783 
784  // DynamicTree enforces this invariant, so can't setup instance in this state to runtime test.
785  assert((index != tree.GetRootIndex()) || (tree.GetOther(index) == DynamicTree::GetInvalidSize()));
786 
787  const auto nodeCapacity = tree.GetNodeCapacity();
788  if (index >= nodeCapacity)
789  {
790  return false;
791  }
792 
793  const auto height = tree.GetHeight(index);
794 
795  if (DynamicTree::IsLeaf(height))
796  {
797  return true;
798  }
799 
800  if (DynamicTree::IsBranch(height))
801  {
802  const auto bd = tree.GetBranchData(index);
803  const auto child1 = bd.child1;
804  const auto child2 = bd.child2;
805  assert(tree.GetOther(child1) == index);
806  assert(tree.GetOther(child2) == index);
807  return ValidateStructure(tree, child1) && ValidateStructure(tree, child2);
808  }
809 
810  assert(DynamicTree::IsUnused(height));
811  return ValidateStructure(tree, tree.GetOther(index));
812 }
813 
814 bool ValidateMetrics(const DynamicTree& tree, DynamicTree::Size index) noexcept
815 {
816  if (index == DynamicTree::GetInvalidSize())
817  {
818  return true;
819  }
820 
821  const auto nodeCapacity = tree.GetNodeCapacity();
822  if (index >= nodeCapacity)
823  {
824  return false;
825  }
826 
827  const auto height = tree.GetHeight(index);
828  if (!DynamicTree::IsBranch(height))
829  {
830  return true;
831  }
832 
833  const auto bd = tree.GetBranchData(index);
834  const auto child1 = bd.child1;
835  const auto child2 = bd.child2;
836 
837  // DynamicTree doesn't provide way to set up the following states so only assertable...
838  assert(tree.GetOther(child1) == index);
839  assert(tree.GetOther(child2) == index);
840  assert(height == (1 + std::max(tree.GetHeight(child1), tree.GetHeight(child2))));
841  assert(tree.GetAABB(index) == GetEnclosingAABB(tree.GetAABB(child1), tree.GetAABB(child2)));
842 
843  return ValidateMetrics(tree, child1) && ValidateMetrics(tree, child2);
844 }
845 
846 } // namespace d2
847 } // namespace playrho