graph_region.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. // RAVEN STANDARD TEMPLATE LIBRARY
  3. // (c) 2002 Activision
  4. //
  5. //
  6. // Graph Region
  7. // ------------
  8. //
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////////////
  11. #if !defined(RATL_GRAPH_REGION_INC)
  12. #define RATL_GRAPH_REGION_INC
  13. ////////////////////////////////////////////////////////////////////////////////////////
  14. // Includes
  15. ////////////////////////////////////////////////////////////////////////////////////////
  16. #if defined(RA_DEBUG_LINKING)
  17. #pragma message("...including graph_region.h")
  18. #endif
  19. #if !defined(RAGL_COMMON_INC)
  20. #include "ragl_common.h"
  21. #endif
  22. #if !defined(RAGL_GRAPH_VS_INC)
  23. #include "graph_vs.h"
  24. #endif
  25. namespace ragl
  26. {
  27. ////////////////////////////////////////////////////////////////////////////////////////
  28. // The Graph Region Class
  29. ////////////////////////////////////////////////////////////////////////////////////////
  30. template <class TNODE, int MAXNODES, class TEDGE, int MAXEDGES, int NUM_EDGES_PER_NODE, int MAXREGIONS, int MAXREGIONEDGES>
  31. class graph_region : public ratl::ratl_base
  32. {
  33. public:
  34. ////////////////////////////////////////////////////////////////////////////////////
  35. // Capacity Enum
  36. ////////////////////////////////////////////////////////////////////////////////////
  37. enum
  38. {
  39. NULL_REGION = -1,
  40. NULL_EDGE = -1,
  41. CAPACITY = MAXREGIONS
  42. };
  43. ////////////////////////////////////////////////////////////////////////////////////
  44. // Some Public Type Defines
  45. ////////////////////////////////////////////////////////////////////////////////////
  46. typedef ragl::graph_vs<TNODE, MAXNODES, TEDGE, MAXEDGES, NUM_EDGES_PER_NODE> TGraph;
  47. typedef ratl::vector_vs<int, MAXNODES> TRegions;
  48. typedef ratl::vector_vs<short, MAXREGIONS> TRegionEdge; // List Of All Edges Which Connect RegionA<->RegionB
  49. typedef ratl::pool_vs<TRegionEdge, MAXREGIONEDGES> TEdges; // Pool Of All RegionEdges
  50. typedef ratl::grid2_vs<short, MAXREGIONS, MAXREGIONS> TLinks; // Graph Of Links From Region To Region, Each Points To A RegionEdge
  51. typedef ratl::bits_vs<MAXREGIONS> TClosed;
  52. ////////////////////////////////////////////////////////////////////////////////////
  53. // Constructor
  54. ////////////////////////////////////////////////////////////////////////////////////
  55. graph_region(TGraph& Graph) : mGraph(Graph)
  56. {
  57. clear();
  58. }
  59. ~graph_region()
  60. {
  61. }
  62. ////////////////////////////////////////////////////////////////////////////////////
  63. // Clear Out All Temp Data So We Can Recalculate Regions
  64. ////////////////////////////////////////////////////////////////////////////////////
  65. void clear()
  66. {
  67. mRegions.resize(0, (int)NULL_REGION);
  68. mRegions.resize(MAXNODES, (int)NULL_REGION);
  69. mRegionCount = 0;
  70. mReservedRegionCount = 0;
  71. mLinks.init(NULL_EDGE);
  72. for (int i=0; i<MAXREGIONEDGES; i++)
  73. {
  74. if (mEdges.is_used(i))
  75. {
  76. mEdges[i].resize(0, NULL_EDGE);
  77. }
  78. }
  79. mEdges.clear();
  80. }
  81. ////////////////////////////////////////////////////////////////////////////////////
  82. // How Many Regions Have Been Created
  83. ////////////////////////////////////////////////////////////////////////////////////
  84. int size()
  85. {
  86. return mRegionCount;
  87. }
  88. ////////////////////////////////////////////////////////////////////////////////////
  89. // Get The Region For A Given Node
  90. ////////////////////////////////////////////////////////////////////////////////////
  91. int get_node_region(int Node)
  92. {
  93. return mRegions[mGraph.node_index(Node)];
  94. }
  95. ////////////////////////////////////////////////////////////////////////////////////
  96. // Call this function to find out if it is at all possible to get from nodeA to
  97. // nodeB. If there is no possible connection, or there is one, but the connection
  98. // is not valid at the current time, this routine will return false. Use it as
  99. // a quick cull routine before a search.
  100. //
  101. // In order to use this function, you must have an EdgeQuery class (use the default
  102. // above, or derive your own for more specialized behavior).
  103. ////////////////////////////////////////////////////////////////////////////////////
  104. bool has_valid_edge(int NodeA, int NodeB, const typename TGraph::user& user)
  105. {
  106. int RegionA = mRegions[NodeA];
  107. int RegionB = mRegions[NodeB];
  108. if (RegionA==RegionB)
  109. {
  110. return true;
  111. }
  112. mClosed.clear();
  113. return has_valid_region_edge(RegionA, RegionB, user);
  114. }
  115. ////////////////////////////////////////////////////////////////////////////////////
  116. // Reserve Region
  117. //
  118. // Allows a user to pre-allocate a special region for a group of points
  119. ////////////////////////////////////////////////////////////////////////////////////
  120. int reserve()
  121. {
  122. assert(mRegionCount < (MAXREGIONS-1));
  123. if (mRegionCount >= (MAXREGIONS-1) )
  124. {//stop adding points, we're full, you MUST increase MAXREGIONS for this to work
  125. return NULL_REGION;
  126. }
  127. mReservedRegionCount ++;
  128. mRegionCount ++;
  129. return (mRegionCount);
  130. }
  131. ////////////////////////////////////////////////////////////////////////////////////
  132. // assign_region
  133. //
  134. // Allows a user to pre-allocate a special region for a group of points
  135. ////////////////////////////////////////////////////////////////////////////////////
  136. void assign_region(int NodeIndex, int RegionIndex)
  137. {
  138. mRegions[NodeIndex] = RegionIndex;
  139. }
  140. ////////////////////////////////////////////////////////////////////////////////////
  141. // Define Regions
  142. //
  143. // Scan through all the nodes (calling the depth first recursive traversal below),
  144. // and mark regions of nodes which can traverse to one another without needing to check
  145. // for valid edges.
  146. //
  147. ////////////////////////////////////////////////////////////////////////////////////
  148. bool find_regions(const typename TGraph::user& user)
  149. {
  150. int CurNodeIndex;
  151. for (TGraph::TNodes::iterator i=mGraph.nodes_begin(); i!=mGraph.nodes_end(); i++)
  152. {
  153. CurNodeIndex = i.index();
  154. if (mRegions[CurNodeIndex] == NULL_REGION)
  155. {
  156. assert(mRegionCount < (MAXREGIONS-1));
  157. if (mRegionCount >= (MAXREGIONS-1) )
  158. {//stop adding points, we're full, you MUST increase MAXREGIONS for this to work
  159. return false;
  160. }
  161. mRegionCount ++; // Allocate The New Region
  162. assign(CurNodeIndex, user); // Assign All Points To It
  163. }
  164. }
  165. mRegionCount ++; // Size is actually 1 greater than the number of regions
  166. return true;
  167. }
  168. ////////////////////////////////////////////////////////////////////////////////////
  169. // Search For All Possible Edges Which Connect Regions
  170. //
  171. // Once called, this class will have reference data for how to get from one region
  172. // to another.
  173. ////////////////////////////////////////////////////////////////////////////////////
  174. bool find_region_edges()
  175. {
  176. int RegionA;
  177. int RegionB;
  178. int RegionLink;
  179. bool Success = true;
  180. bool ReservedRegionLink;
  181. for (int indexA=0; indexA<MAXNODES; indexA++)
  182. {
  183. RegionA = mRegions[indexA];
  184. if (RegionA!=NULL_REGION)
  185. {
  186. for (int indexB=0; indexB<MAXNODES; indexB++)
  187. {
  188. RegionB = mRegions[indexB];
  189. ReservedRegionLink = (RegionA<=mReservedRegionCount || RegionB<=mReservedRegionCount);
  190. if (RegionB!=NULL_REGION && RegionB!=RegionA && mGraph.get_edge_across(indexA, indexB))
  191. {
  192. RegionLink = mLinks.get(RegionA, RegionB);
  193. // Do We Need To Allocate A New Region Link Vector?
  194. //--------------------------------------------------
  195. if (RegionLink==-1)
  196. {
  197. if (ReservedRegionLink)
  198. {
  199. mLinks.get(RegionA, RegionB) = -2; // Special Flag For Reserved Regions - they have no edges
  200. mLinks.get(RegionB, RegionA) = -2;
  201. }
  202. else
  203. {
  204. if (mEdges.full())
  205. {
  206. assert("graph_region: Too Many Region Edges"==0);
  207. Success = false;
  208. }
  209. else
  210. {
  211. RegionLink = mEdges.alloc();
  212. mEdges[RegionLink].resize(0, NULL_EDGE);
  213. mEdges[RegionLink].push_back(mGraph.get_edge_across(indexA, indexB));
  214. mLinks.get(RegionA, RegionB) = RegionLink;
  215. mLinks.get(RegionB, RegionA) = RegionLink;
  216. }
  217. }
  218. }
  219. // Add This Edge To The Other Region Links
  220. //-----------------------------------------
  221. else if (!ReservedRegionLink)
  222. {
  223. mEdges[RegionLink].push_back(mGraph.get_edge_across(indexA, indexB));
  224. }
  225. }
  226. }
  227. }
  228. }
  229. return Success;
  230. }
  231. private:
  232. ////////////////////////////////////////////////////////////////////////////////////
  233. // This Routine Is A Depth First Recursive Traversal
  234. //
  235. // It will visit all neighbors for each node which have not already been visited
  236. // and assigned to a region. Neighbors must always be valid.
  237. ////////////////////////////////////////////////////////////////////////////////////
  238. void assign(int Node, const typename TGraph::user& user)
  239. {
  240. mRegions[Node] = mRegionCount;
  241. for (int i=0; i<MAXNODES; i++)
  242. {
  243. if (mRegions[i]==-1)
  244. {
  245. int edgeNum = mGraph.get_edge_across(Node, i);
  246. if (edgeNum && !user.can_be_invalid(mGraph.get_edge(edgeNum)))
  247. {
  248. assign(i, user);
  249. }
  250. }
  251. }
  252. }
  253. ////////////////////////////////////////////////////////////////////////////////////
  254. // This Routine Is A Depth First Recursive Search For Target Region
  255. //
  256. // Visited regions are makred on the "closed" bit field.
  257. ////////////////////////////////////////////////////////////////////////////////////
  258. bool has_valid_region_edge(int CurRegion, int TargetRegion, const typename TGraph::user& user)
  259. {
  260. // Mark The Cur Region As Visited, So We Don't Try To Return To It
  261. //-----------------------------------------------------------------
  262. mClosed.set_bit(CurRegion);
  263. // If The Two Nodes Are In The Same Region, Then This Is Valid
  264. //-------------------------------------------------------------
  265. if (CurRegion==TargetRegion)
  266. {
  267. return true;
  268. }
  269. // Scan Through The Cur Region's Neighbors With Currently Valid Region Edges
  270. //---------------------------------------------------------------------------
  271. int CurRegionEdge;
  272. for (int NextRegion=0; NextRegion<mRegionCount; NextRegion++)
  273. {
  274. // Check If The Link Exists And We Have Not Already Visited The Next Region
  275. //--------------------------------------------------------------------------
  276. CurRegionEdge = mLinks.get(CurRegion, NextRegion);
  277. if (CurRegionEdge!=NULL_EDGE && !mClosed.get_bit(NextRegion))
  278. {
  279. if (CurRegion<=mReservedRegionCount)
  280. {
  281. // Great, So We Have Found A Valid Neighboring Region, Search There
  282. //------------------------------------------------------------------
  283. if (has_valid_region_edge(NextRegion, TargetRegion, user))
  284. {
  285. return true; // HEY! Somehow, Going To Next Region Got Us To The Target Region!
  286. }
  287. }
  288. else
  289. {
  290. // Scan Through This Region Edge List Of Graph Edges For Any Valid One
  291. //---------------------------------------------------------------------
  292. assert(mEdges[CurRegionEdge].size()>0);
  293. for (int j=0; j<mEdges[CurRegionEdge].size(); j++)
  294. {
  295. if (user.is_valid(
  296. mGraph.get_edge(mEdges[CurRegionEdge][j]),
  297. (NextRegion==TargetRegion)?(-1):(0)
  298. )
  299. )
  300. {
  301. // Great, So We Have Found A Valid Neighboring Region, Search There
  302. //------------------------------------------------------------------
  303. if (has_valid_region_edge(NextRegion, TargetRegion, user))
  304. {
  305. return true; // HEY! Somehow, Going To Next Region Got Us To The Target Region!
  306. }
  307. // Ok, The Target Region Turned Out To Be A Dead End, We Can Stop Trying To Get There
  308. //------------------------------------------------------------------------------------
  309. break;
  310. }
  311. }
  312. }
  313. }
  314. }
  315. // Nope, We Failed To Find Any Valid Region Edges Which Lead To The Target Region
  316. //--------------------------------------------------------------------------------
  317. return false;
  318. }
  319. private:
  320. ////////////////////////////////////////////////////////////////////////////////////
  321. //
  322. ////////////////////////////////////////////////////////////////////////////////////
  323. TGraph& mGraph;
  324. TRegions mRegions;
  325. int mRegionCount;
  326. int mReservedRegionCount;
  327. TLinks mLinks;
  328. TEdges mEdges;
  329. TClosed mClosed;
  330. public:
  331. #if !defined(FINAL_BUILD)
  332. void ProfileSpew()
  333. {
  334. ProfilePrint("");
  335. ProfilePrint("");
  336. ProfilePrint("--------------------------------------------------------");
  337. ProfilePrint("RAVEN STANDARD LIBRARY - COMPUTATIONAL GEOMETRY MODULE");
  338. ProfilePrint(" Region Profile Results ");
  339. ProfilePrint("--------------------------------------------------------");
  340. ProfilePrint("");
  341. ProfilePrint("REGION SIZE (Bytes): (%d) (KiloBytes): (%5.3f)", sizeof(*this), ((float)(sizeof(*this))/1024.0f));
  342. ProfilePrint("REGION COUNT: (%d) Regions (%d) Edges", mRegionCount, mEdges.size());
  343. if (mRegionCount)
  344. {
  345. int RegionEdges = 0;
  346. for (TEdges::iterator it=mEdges.begin(); it!=mEdges.end(); it++)
  347. {
  348. RegionEdges += (*it).size();
  349. }
  350. ProfilePrint("REGION COUNT: (%f) Ave Edges Size", (float)RegionEdges / (float)mRegionCount);
  351. }
  352. ProfilePrint("");
  353. };
  354. #endif
  355. };
  356. }
  357. #endif