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

//================ Copyright (c) 1996-2009 Valve Corporation. All Rights Reserved. =================
//
//
//
//==================================================================================================
#ifndef UTLINTERVALTREE_H
#define UTLINTERVALTREE_H
#ifdef _WIN32
#pragma once
#endif
#include <stdlib.h> // qsort
#include "tier0/platform.h"
#include "tier1/utlstack.h"
//
// An interval tree is a tree of "segments" or "intervals" of type T which can be searched for overlaps with another interval.
//
// Usage:
/*
// Convenience typedef, the application data is the DataType == const void * part of it
typedef CUtlIntervalTree< const void *, float > TreeType;
// Build list of intervals to insert
CUtlVector< TreeType::Value_t > intervals;
TreeType::Value_t iv;
for ( int i = 0 ; i < numtoinsert; ++i )
{
iv.m_Data = (const void *) [i'th user value ];
iv.SetLowVal( leftEdge );
iv.SetHighVal( rightEdge );
intervals.AddToTail( iv );
}
// Then build up the tree
TreeType tree;
tree.BuildTree( intervals.Base(), intervals.Count() );
// Now search the tree
TreeType::Interval_t test;
test.SetLowVal( nLowTest );
test.SetHighVal( nHighTest );
// Results vector:
CUtlVector< TreeType::Value_t > vec;
// Search for overlapping spans, return interval data (sorted by low value if passed in true as third argument)
tree.FindOverlaps( test, vec, true );
// Print results (sorted if third argument is set to true)
for ( int i = 0; i < vec.Count(); ++i )
{
Msg( " [%d] overlap [%f, %f] [val %d]\n",
i, vec[ i ].GetLowVal(), vec[ i ].GetHighVal(), (int)vec[ i ].m_Data );
}
*/
//
template< class DataType, class T = float >
class CUtlIntervalTree
{
public:
template< class S >
class Interval
{
public:
Interval() : m_Low(0), m_High(0)
{
}
Interval( const S &lowVal, const S &highVal ) :
m_Low( lowVal ), m_High( highVal )
{
}
inline void SetLowVal( const S &v )
{
m_Low = v;
}
inline const S &GetLowVal(void) const
{
return m_Low;
}
inline void SetHighVal( const S &v )
{
m_High = v;
}
inline const S &GetHighVal(void) const
{
return m_High;
}
inline bool IsOverlapping( const Interval< S > &other, bool bStricOverlapsOnly ) const
{
if ( bStricOverlapsOnly )
{
return ( GetLowVal() < other.GetHighVal() && GetHighVal() > other.GetLowVal() );
}
return ( GetLowVal() <= other.GetHighVal() && GetHighVal() >= other.GetLowVal() );
}
private:
S m_Low;
S m_High;
};
typedef Interval< T > Interval_t;
struct Value_t : public Interval_t
{
DataType m_Data;
};
CUtlIntervalTree() : m_pRoot( NULL ) {}
~CUtlIntervalTree(void);
void BuildTree( Value_t *pIntervals, unsigned int nCount );
void FindOverlaps( const Interval_t &rCheck, CUtlVector< Value_t > &vecOverlappingIntervals, bool bSortResultsByLowVal, bool bStricOverlapsOnly = false ) const;
private:
struct TreeNode
{
TreeNode( const Value_t &interval ) :
m_Interval(interval),
m_pLeft( NULL ),
m_pRight( NULL )
{
}
Value_t m_Interval;
TreeNode *m_pLeft;
TreeNode *m_pRight;
T m_MinVal;
T m_MaxVal;
};
TreeNode *m_pRoot;
private:
void DeleteTree_R( TreeNode *pNode );
TreeNode *Insert_R( const Value_t *pIntervals, unsigned int nCount );
};
template< class DataType, class T >
inline int CompareIntervals( const void *p1, const void *p2 )
{
const CUtlIntervalTree<DataType,T>::Interval_t *pInterval1 = ( const CUtlIntervalTree<DataType,T>::Interval_t *)p1;
const CUtlIntervalTree<DataType,T>::Interval_t *pInterval2 = ( const CUtlIntervalTree<DataType,T>::Interval_t *)p2;
T lowVal1 = pInterval1->GetLowVal();
T lowVal2 = pInterval2->GetLowVal();
if ( lowVal1 > lowVal2 )
return 1;
else if ( lowVal1 < lowVal2 )
return -1;
return 0;
}
template< class DataType, class T >
inline void CUtlIntervalTree< DataType, T >::BuildTree( Value_t *pIntervals, unsigned int nCount )
{
if ( m_pRoot )
{
DeleteTree_R( m_pRoot );
m_pRoot = NULL;
}
if ( nCount > 0 )
{
qsort( pIntervals, nCount, sizeof( Value_t ), CompareIntervals< DataType, T > );
// Recursively build tree
m_pRoot = Insert_R( pIntervals, nCount );
}
}
template< class DataType, class T >
inline CUtlIntervalTree<DataType, T>::~CUtlIntervalTree(void)
{
if ( m_pRoot )
{
DeleteTree_R( m_pRoot );
}
}
template< class DataType, class T >
inline typename CUtlIntervalTree<DataType, T>::TreeNode *CUtlIntervalTree<DataType, T>::Insert_R( const Value_t *pIntervals, unsigned int nCount )
{
unsigned int rootIdx = nCount / 2;
TreeNode *pRoot = new TreeNode( pIntervals[ rootIdx ] );
switch( nCount )
{
case 1:
{
// m_pLeft, m_pRight are NULL by default
pRoot->m_MinVal = pRoot->m_Interval.GetLowVal();
pRoot->m_MaxVal = pRoot->m_Interval.GetHighVal();
}
break;
case 2:
{
pRoot->m_pLeft = Insert_R( pIntervals, 1 );
// m_pRight == NULL by default
pRoot->m_MinVal = pRoot->m_pLeft->m_MinVal;
pRoot->m_MaxVal = MAX( pRoot->m_pLeft->m_MaxVal, pRoot->m_Interval.GetHighVal() );
}
break;
default: // nCount > 2
{
pRoot->m_pLeft = Insert_R( pIntervals, rootIdx );
pRoot->m_pRight = Insert_R( &pIntervals[ rootIdx + 1 ], nCount - rootIdx - 1 );
pRoot->m_MinVal = pRoot->m_pLeft->m_MinVal;
// Max is greatest of this or two children...
pRoot->m_MaxVal = MAX( MAX( pRoot->m_pLeft->m_MaxVal, pRoot->m_pRight->m_MaxVal ), pRoot->m_Interval.GetHighVal() );
}
break;
}
return pRoot;
}
template< class DataType, class T >
inline void CUtlIntervalTree<DataType, T>::DeleteTree_R( TreeNode *pNode )
{
if ( pNode->m_pLeft )
{
DeleteTree_R( pNode->m_pLeft );
}
if ( pNode->m_pRight )
{
DeleteTree_R( pNode->m_pRight );
}
delete pNode;
}
template< class DataType, class T >
inline void CUtlIntervalTree<DataType, T>::FindOverlaps( const Interval_t &rCheck, CUtlVector< Value_t > &vecOverlappingIntervals, bool bSortResultsByLowVal, bool bStricOverlapsOnly /*= false*/ ) const
{
const TreeNode *pNode = m_pRoot;
if ( !pNode )
return;
// Work queue stack
CUtlStack< const TreeNode * > stack;
stack.Push( NULL );
while ( pNode != NULL )
{
if ( rCheck.IsOverlapping( pNode->m_Interval, bStricOverlapsOnly ) )
{
vecOverlappingIntervals.AddToTail( pNode->m_Interval );
}
bool bCheckLeft = ( pNode->m_pLeft &&
pNode->m_pLeft->m_MaxVal >= rCheck.GetLowVal() );
bool bCheckRight = ( pNode->m_pRight &&
pNode->m_pRight->m_MinVal <= rCheck.GetHighVal() );
if ( bCheckRight )
{
if ( bCheckLeft )
{
// queue it up for later
stack.Push( pNode->m_pLeft );
}
pNode = pNode->m_pRight;
}
else if ( bCheckLeft )
{
pNode = pNode->m_pLeft;
}
else
{
stack.Pop( pNode );
}
}
if ( bSortResultsByLowVal &&
vecOverlappingIntervals.Count() > 1 )
{
qsort( vecOverlappingIntervals.Base(), vecOverlappingIntervals.Count(), sizeof( Value_t ), CompareIntervals< DataType, T > );
}
}
#endif // UTLINTERVALTREE_H