gwnavruntime/queries/utils/bestfirstsearchtraversal.h Source File

bestfirstsearchtraversal.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 #pragma once
8 
15 
16 namespace Kaim
17 {
18 
19 class NavMeshElementBlob;
20 
21 /*
22 TVisitor is a class that must have following methods :
23 
24  void ComputeTriangleCost(const NavTrianglePtr& trianglePtr, KyFloat32& cost);
25 
26  Visit(const NavTrianglePtr& trianglePtr, KyFloat32 cost, const TriangleStatusInGrid& triangleStatus)
27 
28  bool IsSearchFinished();
29 
30  bool ShouldVisitTriangle(const NavTrianglePtr& trianglePtr);
31 
32  bool ShouldVisitNeighborTriangle(const NavTrianglePtr& trianglePtr, KyUInt32 indexOfNeighborTriangle);
33 
34  NavTrianglePtr GetNeighborTriangle(const NavTrianglePtr& trianglePtr, KyUInt32 indexOfNeighborTriangle);
35 */
36 template <class Visitor>
37 class BestFirstSearchTraversal
38 {
39  KY_DEFINE_NEW_DELETE_OPERATORS(MemStat_Query)
40 
41 public:
42  BestFirstSearchTraversal(QueryUtils& queryUtils, const CellBox& cellBox, Visitor& visitor) :
43  m_activeData(queryUtils.m_database->GetActiveData()),
44  m_visitor(&visitor),
45  m_openNodes(queryUtils.GetWorkingMemory()),
46  m_triangleStatus(queryUtils.GetWorkingMemory(), cellBox),
47  m_visitedNodes(nullptr) {}
48 
49  void Clear()
50  {
51  m_openNodes.Clear();
52  m_triangleStatus.MakeEmpty();
53  }
54 
55  bool IsInitialized() const { return m_openNodes.IsInitialized() && m_triangleStatus.IsInitialized(); }
56 
57  TraversalResult SetStartTriangle(const NavTriangleRawPtr& trianglePtr); // TODO AddStartTriangle() is a better function name
58  TraversalResult Search();
59 
60  void SetVisitedNodeContainer(WorkingMemArray<NavTriangleRawPtr>* visitedNodes) { m_visitedNodes = visitedNodes; }
61 
62 private:
63  TraversalResult AddTriangleIfNeverEncountered(const NavTriangleRawPtr& node);
64  PropagationNode createNode(const NavTriangleRawPtr& node);
65 
66 public:
67  ActiveData* m_activeData;
68 
69  Visitor* m_visitor; //< the visitor (= the "node analyzer")
70 
71  WorkingMemBinaryHeap<PropagationNode> m_openNodes; //< open nodes = nodes that are about to be analyzed
72 
73  TriangleStatusInGrid m_triangleStatus; //< closed nodes = nodes that have been analyzed
74  WorkingMemArray<NavTriangleRawPtr>* m_visitedNodes; //< nodes that have been visited
75 };
76 
77 
78 template <class Visitor>
79 TraversalResult BestFirstSearchTraversal<Visitor>::SetStartTriangle(const NavTriangleRawPtr& triangleRawPtr)
80 {
81  if (m_visitor->ShouldVisitTriangle(triangleRawPtr) == false)
82  return TraversalResult_DONE;
83 
84  if (m_openNodes.IsFull() == false)
85  {
86  m_openNodes.Insert(PropagationNode(triangleRawPtr));
87 
88  bool unused;
89  if (m_triangleStatus.IsInitialized() == false)
90  return TraversalResult_LACK_OF_MEMORY_FOR_CLOSED_NODES;
91 
92  return m_triangleStatus.OpenNodeIfNew(*m_activeData, triangleRawPtr, unused);
93  }
94 
95  return TraversalResult_LACK_OF_MEMORY_FOR_OPEN_NODES;
96 }
97 
98 template <class Visitor>
99 TraversalResult BestFirstSearchTraversal<Visitor>::Search()
100 {
101  bool doesStoreVisited = m_visitedNodes != nullptr;
102 
103  //const KyUInt32 numberOfStartsNodes = m_openNodes.m_currentSize;
104  //KyUInt32 currentNumberNode = 0;
105  PropagationNode currentNode;
106 
107  while (!m_openNodes.IsEmpty())
108  {
109  m_openNodes.ExtractFirst(currentNode);
110 
111  m_visitor->Visit(currentNode.m_triangleRawPtr, currentNode.m_cost, m_triangleStatus);
112 
113  if (doesStoreVisited)
114  {
115  if (m_visitedNodes->PushBack(currentNode.m_triangleRawPtr) == KY_ERROR)
116  return TraversalResult_LACK_OF_MEMORY_FOR_VISITED_NODES;
117  }
118 
119  if (m_visitor->IsSearchFinished())
120  return TraversalResult_DONE;
121 
122  if (m_visitor->ShouldVisitNeighborTriangle(currentNode.m_triangleRawPtr, 0))
123  {
124  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentNode.m_triangleRawPtr, 0));
125  if (rc != TraversalResult_DONE)
126  return rc;
127  }
128 
129  if (m_visitor->ShouldVisitNeighborTriangle(currentNode.m_triangleRawPtr, 1))
130  {
131  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentNode.m_triangleRawPtr, 1));
132  if (rc != TraversalResult_DONE)
133  return rc;
134  }
135 
136  if (m_visitor->ShouldVisitNeighborTriangle(currentNode.m_triangleRawPtr, 2))
137  {
138  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentNode.m_triangleRawPtr, 2));
139  if (rc != TraversalResult_DONE)
140  return rc;
141  }
142  }
143 
144  return TraversalResult_DONE;
145 }
146 
147 template <class Visitor>
148 TraversalResult BestFirstSearchTraversal<Visitor>::AddTriangleIfNeverEncountered(const NavTriangleRawPtr& triangleRawPtr)
149 {
150  bool nodeIsNew;
151  TraversalResult result = m_triangleStatus.OpenNodeIfNew(*m_activeData, triangleRawPtr, nodeIsNew);
152  if (result != TraversalResult_DONE)
153  return result;
154 
155  if (nodeIsNew)
156  {
157  if (m_openNodes.IsFull())
158  return TraversalResult_LACK_OF_MEMORY_FOR_OPEN_NODES;
159 
160  m_openNodes.Insert(createNode(triangleRawPtr));
161  }
162 
163  return TraversalResult_DONE;
164 }
165 
166 template <class Visitor>
167 PropagationNode BestFirstSearchTraversal<Visitor>::createNode(const NavTriangleRawPtr& triangleRawPtr)
168 {
169  PropagationNode node(triangleRawPtr);
170  m_visitor->ComputeTriangleCost(triangleRawPtr, node.m_cost);
171  return node;
172 }
173 
174 
175 
176 }
177 
178 
Box2i CellBox
A type that represents a bounding box around cells in a 2D grid.
Definition: navmeshtypes.h:31
#define KY_DEFINE_NEW_DELETE_OPERATORS(MemStat)
This macro defines new and delete operators.
Definition: memory.h:132
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
#define KY_ERROR
use result == KY_ERROR to test for error
Definition: types.h:132