gwnavruntime/queries/utils/breadthfirstsearchtraversal.h Source File

breadthfirstsearchtraversal.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 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 
8 
9 
10 
11 // ---------- Primary contact: JUBA - secondary contact: NOBODY
12 #ifndef Navigation_BreadthFirstSearchTraversal_H
13 #define Navigation_BreadthFirstSearchTraversal_H
14 
21 
22 
23 namespace Kaim
24 {
25 
26 class NavMeshElementBlob;
27 
28 /*
29 Visitor is a class that must have following methods :
30 
31  Visit(const NavTrianglePtr& trianglePtr, const TriangleStatusInGrid& triangleStatus)
32 
33  bool IsSearchFinished();
34  bool ShouldVisitTriangle(const NavTrianglePtr& trianglePtr);
35  bool ShouldVisitNeighborTriangle(const NavTrianglePtr& trianglePtr, KyUInt32 indexOfNeighborTriangle);
36  NavTrianglePtr GetNeighborTriangle(const NavTrianglePtr& trianglePtr, KyUInt32 indexOfNeighborTriangle);
37 
38 */
39 template <class Visitor>
40 class BreadthFirstSearchTraversal
41 {
42  KY_DEFINE_NEW_DELETE_OPERATORS(MemStat_Query)
43 
44 public :
45  BreadthFirstSearchTraversal(
46  QueryUtils& queryUtils, const CellBox& cellBox, Visitor& visitor) :
47  m_activeData(queryUtils.m_database->GetActiveData()),
48  m_visitor(&visitor),
49  m_openNodes(queryUtils.GetWorkingMemory()),
50  m_triangleStatus(queryUtils.GetWorkingMemory(), cellBox),
51  m_visitedNodes(KY_NULL) {}
52 
53  KY_INLINE void Clear()
54  {
55  m_openNodes.MakeEmpty();
56  m_triangleStatus.MakeEmpty();
57  }
58 
59  KY_INLINE bool IsInitialized() const { return m_openNodes.IsInitialized() && m_triangleStatus.IsInitialized(); }
60 
61  // the navTag of the startTriangle is not tested
62  inline TraversalResult SetStartTriangle(const NavTriangleRawPtr& triangleRawPtr);
63 
64  TraversalResult AddTriangleIfNeverEncountered(const NavTriangleRawPtr& triangleRawPtr);
65 
66  TraversalResult Search();
67 
68  KY_INLINE void SetVisitedNodeContainer(WorkingMemArray<NavTriangleRawPtr>* visitedNodes) { m_visitedNodes = visitedNodes; }
69 
70 public :
71  ActiveData* m_activeData;
72 
73  Visitor* m_visitor; //< the visitor (= the "node analyser")
74 
75  WorkingMemDeque<NavTriangleRawPtr> m_openNodes; //< open nodes = nodes that are about to be analysed
76 
77  TriangleStatusInGrid m_triangleStatus; //< closed nodes = nodes that have been analysed
78  WorkingMemArray<NavTriangleRawPtr>* m_visitedNodes; //< nodes that have been visited
79 };
80 
81 template <class Visitor>
82 TraversalResult BreadthFirstSearchTraversal<Visitor>:: SetStartTriangle(const NavTriangleRawPtr& triangleRawPtr)
83 {
84  if (m_visitor->ShouldVisitTriangle(triangleRawPtr) == false)
85  return TraversalResult_DONE;
86 
87  if (KY_FAILED(m_openNodes.PushBack(triangleRawPtr)))
88  return TraversalResult_LACK_OF_MEMORY_FOR_OPEN_NODES;
89 
90  bool unused;
91  if (m_triangleStatus.IsInitialized() == false)
92  return TraversalResult_LACK_OF_MEMORY_FOR_CLOSED_NODES;
93 
94  return m_triangleStatus.OpenNodeIfNew(*m_activeData, triangleRawPtr, unused);
95 }
96 
97 template <class Visitor>
98 TraversalResult BreadthFirstSearchTraversal<Visitor>::Search()
99 {
100  bool doesStoreVisited = m_visitedNodes != KY_NULL;
101 
102  NavTriangleRawPtr currentTrianglerRawPtr;
103 
104  while (!m_openNodes.IsEmpty())
105  {
106  m_openNodes.Front(currentTrianglerRawPtr);
107  m_openNodes.PopFront();
108 
109  m_visitor->Visit(currentTrianglerRawPtr, m_triangleStatus);
110 
111  if (doesStoreVisited)
112  {
113  if (KY_FAILED(m_visitedNodes->PushBack(currentTrianglerRawPtr)))
114  return TraversalResult_LACK_OF_MEMORY_FOR_VISITED_NODES;
115  }
116 
117  if (m_visitor->IsSearchFinished())
118  return TraversalResult_DONE;
119 
120  if (m_visitor->ShouldVisitNeighborTriangle(currentTrianglerRawPtr, 0))
121  {
122  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentTrianglerRawPtr, 0));
123  if (rc != TraversalResult_DONE)
124  return rc;
125  }
126 
127  if (m_visitor->ShouldVisitNeighborTriangle(currentTrianglerRawPtr, 1))
128  {
129  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentTrianglerRawPtr, 1));
130  if (rc != TraversalResult_DONE)
131  return rc;
132  }
133 
134  if (m_visitor->ShouldVisitNeighborTriangle(currentTrianglerRawPtr, 2))
135  {
136  const TraversalResult rc = AddTriangleIfNeverEncountered(m_visitor->GetNeighborTriangle(currentTrianglerRawPtr, 2));
137  if (rc != TraversalResult_DONE)
138  return rc;
139  }
140  }
141 
142  return TraversalResult_DONE;
143 }
144 
145 template <class Visitor>
146 TraversalResult BreadthFirstSearchTraversal<Visitor>::AddTriangleIfNeverEncountered(const NavTriangleRawPtr& triangleRawPtr)
147 {
148  bool nodeIsNew;
149  TraversalResult result = m_triangleStatus.OpenNodeIfNew(*m_activeData, triangleRawPtr, nodeIsNew);
150  if (result != TraversalResult_DONE)
151  return result;
152 
153  if (nodeIsNew && KY_FAILED(m_openNodes.PushBack(triangleRawPtr)))
154  return TraversalResult_LACK_OF_MEMORY_FOR_OPEN_NODES;
155 
156  return TraversalResult_DONE;
157 }
158 
159 }
160 
161 #endif // Navigation_BreadthFirstSearchTraversal_H
162 
Box2i CellBox
A type that represents a bounding box around cells in a 2D grid.
Definition: navmeshtypes.h:34
#define KY_FAILED(expression)
Shorthand for Kaim::Result::Fail().
Definition: types.h:274
#define KY_NULL
Null value.
Definition: types.h:247
Definition: gamekitcrowddispersion.h:20
#define KY_DEFINE_NEW_DELETE_OPERATORS(MemStat)
This macro defines new and delete operators.
Definition: memory.h:137