Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
6.9 KiB

  1. //================ Copyright (c) 1996-2009 Valve Corporation. All Rights Reserved. =================
  2. //
  3. //
  4. //
  5. //==================================================================================================
  6. #ifndef UTLINTERVALTREE_H
  7. #define UTLINTERVALTREE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include <stdlib.h> // qsort
  12. #include "tier0/platform.h"
  13. #include "tier1/utlstack.h"
  14. //
  15. // An interval tree is a tree of "segments" or "intervals" of type T which can be searched for overlaps with another interval.
  16. //
  17. // Usage:
  18. /*
  19. // Convenience typedef, the application data is the DataType == const void * part of it
  20. typedef CUtlIntervalTree< const void *, float > TreeType;
  21. // Build list of intervals to insert
  22. CUtlVector< TreeType::Value_t > intervals;
  23. TreeType::Value_t iv;
  24. for ( int i = 0 ; i < numtoinsert; ++i )
  25. {
  26. iv.m_Data = (const void *) [i'th user value ];
  27. iv.SetLowVal( leftEdge );
  28. iv.SetHighVal( rightEdge );
  29. intervals.AddToTail( iv );
  30. }
  31. // Then build up the tree
  32. TreeType tree;
  33. tree.BuildTree( intervals.Base(), intervals.Count() );
  34. // Now search the tree
  35. TreeType::Interval_t test;
  36. test.SetLowVal( nLowTest );
  37. test.SetHighVal( nHighTest );
  38. // Results vector:
  39. CUtlVector< TreeType::Value_t > vec;
  40. // Search for overlapping spans, return interval data (sorted by low value if passed in true as third argument)
  41. tree.FindOverlaps( test, vec, true );
  42. // Print results (sorted if third argument is set to true)
  43. for ( int i = 0; i < vec.Count(); ++i )
  44. {
  45. Msg( " [%d] overlap [%f, %f] [val %d]\n",
  46. i, vec[ i ].GetLowVal(), vec[ i ].GetHighVal(), (int)vec[ i ].m_Data );
  47. }
  48. */
  49. //
  50. template< class DataType, class T = float >
  51. class CUtlIntervalTree
  52. {
  53. public:
  54. template< class S >
  55. class Interval
  56. {
  57. public:
  58. Interval() : m_Low(0), m_High(0)
  59. {
  60. }
  61. Interval( const S &lowVal, const S &highVal ) :
  62. m_Low( lowVal ), m_High( highVal )
  63. {
  64. }
  65. inline void SetLowVal( const S &v )
  66. {
  67. m_Low = v;
  68. }
  69. inline const S &GetLowVal(void) const
  70. {
  71. return m_Low;
  72. }
  73. inline void SetHighVal( const S &v )
  74. {
  75. m_High = v;
  76. }
  77. inline const S &GetHighVal(void) const
  78. {
  79. return m_High;
  80. }
  81. inline bool IsOverlapping( const Interval< S > &other, bool bStricOverlapsOnly ) const
  82. {
  83. if ( bStricOverlapsOnly )
  84. {
  85. return ( GetLowVal() < other.GetHighVal() && GetHighVal() > other.GetLowVal() );
  86. }
  87. return ( GetLowVal() <= other.GetHighVal() && GetHighVal() >= other.GetLowVal() );
  88. }
  89. private:
  90. S m_Low;
  91. S m_High;
  92. };
  93. typedef Interval< T > Interval_t;
  94. struct Value_t : public Interval_t
  95. {
  96. DataType m_Data;
  97. };
  98. CUtlIntervalTree() : m_pRoot( NULL ) {}
  99. ~CUtlIntervalTree(void);
  100. void BuildTree( Value_t *pIntervals, unsigned int nCount );
  101. void FindOverlaps( const Interval_t &rCheck, CUtlVector< Value_t > &vecOverlappingIntervals, bool bSortResultsByLowVal, bool bStricOverlapsOnly = false ) const;
  102. private:
  103. struct TreeNode
  104. {
  105. TreeNode( const Value_t &interval ) :
  106. m_Interval(interval),
  107. m_pLeft( NULL ),
  108. m_pRight( NULL )
  109. {
  110. }
  111. Value_t m_Interval;
  112. TreeNode *m_pLeft;
  113. TreeNode *m_pRight;
  114. T m_MinVal;
  115. T m_MaxVal;
  116. };
  117. TreeNode *m_pRoot;
  118. private:
  119. void DeleteTree_R( TreeNode *pNode );
  120. TreeNode *Insert_R( const Value_t *pIntervals, unsigned int nCount );
  121. };
  122. template< class DataType, class T >
  123. inline int CompareIntervals( const void *p1, const void *p2 )
  124. {
  125. const CUtlIntervalTree<DataType,T>::Interval_t *pInterval1 = ( const CUtlIntervalTree<DataType,T>::Interval_t *)p1;
  126. const CUtlIntervalTree<DataType,T>::Interval_t *pInterval2 = ( const CUtlIntervalTree<DataType,T>::Interval_t *)p2;
  127. T lowVal1 = pInterval1->GetLowVal();
  128. T lowVal2 = pInterval2->GetLowVal();
  129. if ( lowVal1 > lowVal2 )
  130. return 1;
  131. else if ( lowVal1 < lowVal2 )
  132. return -1;
  133. return 0;
  134. }
  135. template< class DataType, class T >
  136. inline void CUtlIntervalTree< DataType, T >::BuildTree( Value_t *pIntervals, unsigned int nCount )
  137. {
  138. if ( m_pRoot )
  139. {
  140. DeleteTree_R( m_pRoot );
  141. m_pRoot = NULL;
  142. }
  143. if ( nCount > 0 )
  144. {
  145. qsort( pIntervals, nCount, sizeof( Value_t ), CompareIntervals< DataType, T > );
  146. // Recursively build tree
  147. m_pRoot = Insert_R( pIntervals, nCount );
  148. }
  149. }
  150. template< class DataType, class T >
  151. inline CUtlIntervalTree<DataType, T>::~CUtlIntervalTree(void)
  152. {
  153. if ( m_pRoot )
  154. {
  155. DeleteTree_R( m_pRoot );
  156. }
  157. }
  158. template< class DataType, class T >
  159. inline typename CUtlIntervalTree<DataType, T>::TreeNode *CUtlIntervalTree<DataType, T>::Insert_R( const Value_t *pIntervals, unsigned int nCount )
  160. {
  161. unsigned int rootIdx = nCount / 2;
  162. TreeNode *pRoot = new TreeNode( pIntervals[ rootIdx ] );
  163. switch( nCount )
  164. {
  165. case 1:
  166. {
  167. // m_pLeft, m_pRight are NULL by default
  168. pRoot->m_MinVal = pRoot->m_Interval.GetLowVal();
  169. pRoot->m_MaxVal = pRoot->m_Interval.GetHighVal();
  170. }
  171. break;
  172. case 2:
  173. {
  174. pRoot->m_pLeft = Insert_R( pIntervals, 1 );
  175. // m_pRight == NULL by default
  176. pRoot->m_MinVal = pRoot->m_pLeft->m_MinVal;
  177. pRoot->m_MaxVal = MAX( pRoot->m_pLeft->m_MaxVal, pRoot->m_Interval.GetHighVal() );
  178. }
  179. break;
  180. default: // nCount > 2
  181. {
  182. pRoot->m_pLeft = Insert_R( pIntervals, rootIdx );
  183. pRoot->m_pRight = Insert_R( &pIntervals[ rootIdx + 1 ], nCount - rootIdx - 1 );
  184. pRoot->m_MinVal = pRoot->m_pLeft->m_MinVal;
  185. // Max is greatest of this or two children...
  186. pRoot->m_MaxVal = MAX( MAX( pRoot->m_pLeft->m_MaxVal, pRoot->m_pRight->m_MaxVal ), pRoot->m_Interval.GetHighVal() );
  187. }
  188. break;
  189. }
  190. return pRoot;
  191. }
  192. template< class DataType, class T >
  193. inline void CUtlIntervalTree<DataType, T>::DeleteTree_R( TreeNode *pNode )
  194. {
  195. if ( pNode->m_pLeft )
  196. {
  197. DeleteTree_R( pNode->m_pLeft );
  198. }
  199. if ( pNode->m_pRight )
  200. {
  201. DeleteTree_R( pNode->m_pRight );
  202. }
  203. delete pNode;
  204. }
  205. template< class DataType, class T >
  206. inline void CUtlIntervalTree<DataType, T>::FindOverlaps( const Interval_t &rCheck, CUtlVector< Value_t > &vecOverlappingIntervals, bool bSortResultsByLowVal, bool bStricOverlapsOnly /*= false*/ ) const
  207. {
  208. const TreeNode *pNode = m_pRoot;
  209. if ( !pNode )
  210. return;
  211. // Work queue stack
  212. CUtlStack< const TreeNode * > stack;
  213. stack.Push( NULL );
  214. while ( pNode != NULL )
  215. {
  216. if ( rCheck.IsOverlapping( pNode->m_Interval, bStricOverlapsOnly ) )
  217. {
  218. vecOverlappingIntervals.AddToTail( pNode->m_Interval );
  219. }
  220. bool bCheckLeft = ( pNode->m_pLeft &&
  221. pNode->m_pLeft->m_MaxVal >= rCheck.GetLowVal() );
  222. bool bCheckRight = ( pNode->m_pRight &&
  223. pNode->m_pRight->m_MinVal <= rCheck.GetHighVal() );
  224. if ( bCheckRight )
  225. {
  226. if ( bCheckLeft )
  227. {
  228. // queue it up for later
  229. stack.Push( pNode->m_pLeft );
  230. }
  231. pNode = pNode->m_pRight;
  232. }
  233. else if ( bCheckLeft )
  234. {
  235. pNode = pNode->m_pLeft;
  236. }
  237. else
  238. {
  239. stack.Pop( pNode );
  240. }
  241. }
  242. if ( bSortResultsByLowVal &&
  243. vecOverlappingIntervals.Count() > 1 )
  244. {
  245. qsort( vecOverlappingIntervals.Base(), vecOverlappingIntervals.Count(), sizeof( Value_t ), CompareIntervals< DataType, T > );
  246. }
  247. }
  248. #endif // UTLINTERVALTREE_H