Files
secondo/Algebras/NearestNeighbor/NearestNeighborAlgebra.h
2026-01-23 17:03:45 +08:00

1333 lines
29 KiB
C++

/*
[1] Header-File of NearestNeighborAlgebra
November 2008, Angelika Braese.
This header file implements some functions which the NearestNeighborAlgebra
needs and which are defined in RTree Algebra.
The follow code must be included in the RTree Algebra:
----
#include <vector>
#include <queue>
template<class LeafInfo>
class DistanceElement
{
private:
long nodeId;
bool leaf;
LeafInfo tpId;
double distance;
int level;
public:
bool IsLeaf() const { return leaf; }
LeafInfo TupleId() const { return tpId; }
long NodeId() const { return nodeId; }
int Level() const { return level; }
struct Near : public binary_function< DistanceElement<LeafInfo>,
DistanceElement<LeafInfo>, bool >
{
bool operator()(const DistanceElement<LeafInfo> e1,
const DistanceElement<LeafInfo> e2) const
{
return e1.distance >= e2.distance;
}
};
DistanceElement():
nodeId( -1 ),
leaf( true ),
tpId( -1 ),
level( -1 )
{}
DistanceElement( long node, bool l, LeafInfo tid,
double dist, int curLevel ):
nodeId( node ),
leaf( l ),
tpId( tid ),
distance( dist ),
level( curLevel )
{}
virtual ~DistanceElement()
{}
};
typedef vector< DistanceElement<TupleId> > NNVector;
typedef priority_queue< DistanceElement<TupleId>, NNVector,
DistanceElement<TupleId>::Near > NNpriority_queue;
template <unsigned dim, class LeafInfo>
class R_Tree
{
public:
...
void FirstDistanceScan( const BBox<dim>& box );
/ *
FirstDistanceScan initializes the priority queue
* /
void LastDistanceScan( );
/ *
LastDistanceScan deletes the priority queue of the distancescan
* /
bool R_Tree<dim, LeafInfo>::NextDistanceScan( const BBox<dim>& box,
LeafInfo& result );
/ *
NextDistanceScan returns true and fills the result with the
ID of the next tuple if there is a next tuple else it returns false
* /
...
private:
...
NNpriority_queue* pq;
/ *
The priority queue for the distancescan functions
* /
bool distanceFlag;
/ *
true, after a call of FirstDistanceScan
* /
...
}
End of the definitions which had to be included into RTreeAlgebra.h
----
1 Defines and includes for the NearestNeighbor Algebra
*/
#ifndef __NEARESTNEIGHBOR_ALGEBRA_H__
#define __NEARESTNEIGHBOR_ALGEBRA_H__
#include "Algebras/Temporal/TemporalAlgebra.h"
/*
2 Definitions for the ~distancescan operator~
FirstDistanceScan initializes the priority queue
*/
template <unsigned dim, class LeafInfo>
void R_Tree<dim, LeafInfo>::FirstDistanceScan( const BBox<dim>& box )
{
distanceFlag = true;
pq = new NNpriority_queue;
R_TreeNode<dim, TupleId> tmp = Root();
if(!tmp.IsLeaf()){
pq->push( DistanceElement<TupleId>( RootRecordId(),false, -1,
tmp.BoundingBox().Distance(box), 0));
} else {
for ( int ii = 0; ii < tmp.EntryCount(); ++ii ) {
R_TreeLeafEntry<dim, LeafInfo> e =
(R_TreeLeafEntry<dim, LeafInfo>&)(tmp)[ii];
pq->push( DistanceElement<LeafInfo>( 0,
true, e.info, e.box.Distance( box ),
1));
}
}
}
/*
LastDistanceScan deletes the priority queue of the distancescan
*/
template <unsigned dim, class LeafInfo>
void R_Tree<dim, LeafInfo>::LastDistanceScan( )
{
assert(distanceFlag);
distanceFlag = false;
delete pq;
}
/*
NextDistanceScan returns true and fills the result with the
ID of the next tuple if there is a next tuple else it returns false
*/
template <unsigned dim, class LeafInfo>
bool R_Tree<dim, LeafInfo>::NextDistanceScan( const BBox<dim>& box,
LeafInfo& result )
{
assert(distanceFlag);
while ( !pq->empty() )
{
DistanceElement<LeafInfo> elem = pq->top();
pq->pop();
if ( elem.IsLeaf() )
{
result = elem.TupleId();
return true;
}
else
{
R_TreeNode<dim, LeafInfo> *tmp = GetNode( elem.NodeId(),
elem.IsLeaf(),
MinEntries( elem.Level() ),
MaxEntries( elem.Level() ) );
for ( int ii = 0; ii < tmp->EntryCount(); ++ii )
{
if ( tmp->IsLeaf() )
{
R_TreeLeafEntry<dim, LeafInfo> e =
(R_TreeLeafEntry<dim, LeafInfo>&)(*tmp)[ii];
pq->push( DistanceElement<LeafInfo>( 0,
true, e.info, e.box.Distance( box ),
elem.Level() + 1));
}
else
{
R_TreeInternalEntry<dim> e =
(R_TreeInternalEntry<dim>&)(*tmp)[ii];
pq->push( DistanceElement<LeafInfo>( e.pointer,
false, -1, e.box.Distance( box ),
elem.Level() + 1));
}
}
delete tmp;
}
}
return false;
}
/*
3. Class definitions for the ~knearest operator~
*/
enum EventType {E_RIGHT, E_INTERSECT, E_LEFT};
struct EventElem
{
EventType type;
Instant pointInTime; //x-axes, sortkey in the priority queue
Tuple* tuple;
Tuple* tuple2; //for intersection
const temporalalgebra::UPoint* up;
temporalalgebra::MReal* distance;
EventElem(EventType t, Instant i, Tuple* tu,
const temporalalgebra::UPoint* upt,
temporalalgebra::MReal* d) : type(t), pointInTime(i),
tuple(tu), tuple2(NULL),
up(upt), distance(d){}
EventElem(EventType t, Instant i, Tuple* tu, Tuple* tu2,
temporalalgebra::MReal* d)
: type(t), pointInTime(i), tuple(tu), tuple2(tu2),
up(NULL), distance(d){}
bool operator<( const EventElem& e ) const
{
if( e.pointInTime != pointInTime)
{
return e.pointInTime < pointInTime;
}
else
{
//same times
if( e.type != type )
{
return e.type < type;
}
else
{
//same types
return e.tuple < tuple || (e.tuple == tuple && e.tuple2 < tuple2);
}
}
}
};
namespace near{
class ActiveElem
{
public:
static Instant currtime;
temporalalgebra::MReal *distance;
Tuple* tuple;
Instant start; //the start time where the element is needed
Instant end;
bool lc;
bool rc;
ActiveElem(){}
ActiveElem(temporalalgebra::MReal *dist, Tuple* t, Instant s,
Instant e, bool l, bool r)
: distance(dist), tuple(t), start(s), end(e), lc(l), rc(r){}
};
}
/*
the class NNTree implements a tree with iterators
the methods to find an element or to find the position
of a new element are implemented outside of the class
in the NearestNeighborAlgebra.cpp
*/
template <class T>
class NNTree
{
private:
class NNnode
{
public:
NNnode(){}
NNnode *left;
NNnode *right;
NNnode *parent;
T elem;
};
public:
class iter
{
friend class NNTree;
public:
iter( ) : itNode(NULL){}
iter( NNnode *n) : itNode(n){}
friend bool operator==(const NNTree::iter& i,
const iter& j)
{
return i.itNode == j.itNode;
}
friend bool operator!=(const NNTree::iter& i,
const NNTree::iter& j)
{
return i.itNode != j.itNode;
}
T* operator->(){ return &itNode->elem;}
T& operator*(){ return itNode->elem;}
iter& operator++(); //prefix
iter operator++(int) //postfix
{
iter tmp = *this;
++this;
return tmp;
}
iter& operator--(); //prefix
iter operator--(int) //postfix
{
iter tmp = *this;
--this;
return tmp;
}
iter &leftItem()
{
itNode = itNode->left; return *this;
}
iter &rightItem()
{
itNode = itNode->right; return *this;
}
bool hasLeft( ){ return itNode->left != NULL; }
bool hasRight( ){ return itNode->right != NULL; }
private:
typename NNTree::NNnode *itNode;
NNnode *nextNode( NNnode *n );
NNnode *prevNode( NNnode *n );
};
NNTree();
~NNTree();
iter begin(){return iter(first);}
iter end(){return iter(NULL);}
iter root(){ return iter(rootnode);}
iter erase( iter &pos);
iter addFirst( T &e);
iter addLeft( T &e, iter &it);
iter addRight( T &e, iter &it);
iter addElem( T &e, iter &it);
unsigned int size(){ return nrelements;}
private:
NNnode *first;
NNnode *rootnode;
unsigned int nrelements;
NNnode *newNode( T &e, NNnode *p);
unsigned int nodeCount( NNnode *n );
static NNnode *maxNode( NNnode *n );
static NNnode *minNode( NNnode *n );
void deleteAll( NNnode *node);
};
/*
Konstruktor of NNTree
*/
template<class T>
NNTree<T>::NNTree() : first(NULL), rootnode(NULL),nrelements(0)
{
}
/*
destructor of NNTree delete all nodes
*/
template<class T>
NNTree<T>::~NNTree()
{
deleteAll( rootnode );
}
/*
delete the NNnode of the iterator pos und returns the element
after pos or end()
*/
template<class T>
typename NNTree<T>::iter NNTree<T>::erase( iter &pos)
{
if( pos.itNode == NULL)
{
return pos;
}
iter res(pos);
++res;
NNnode *p = pos.itNode->parent;
if( pos.itNode->left == NULL && pos.itNode->right == NULL)
{
if( p != NULL )
{
if( p->left == pos.itNode)
{
p->left = NULL;
}
else
p->right = NULL;
}
else
{
rootnode = NULL;
}
}
else if( pos.itNode->left == NULL || pos.itNode->right == NULL )
{
//only one subtree exists
if( p != NULL )
{
if( p->left == pos.itNode)
{
p->left = (pos.itNode->left != NULL) ? pos.itNode->left
: pos.itNode->right;
p->left->parent = p;
}
else
{
p->right = (pos.itNode->left != NULL) ? pos.itNode->left
: pos.itNode->right;
p->right->parent = p;
}
}
else
{
rootnode = (pos.itNode->left != NULL)
? pos.itNode->left : pos.itNode->right;
rootnode->parent = NULL;
}
}
else
{
//left and right subtree exists
if( nodeCount( pos.itNode->left) >= nodeCount( pos.itNode->right))
{
NNnode *max = maxNode( pos.itNode->left);
if( max->left != NULL )
{
max->left->parent = max->parent;
}
if( max->parent->left == max )
max->parent->left = max->left;
else
max->parent->right = max->left;
max->left = pos.itNode->left;
max->right = pos.itNode->right;
max->parent = pos.itNode->parent;
if( max->left != NULL )
max->left->parent = max;
max->right->parent = max;
if( max->parent != NULL)
{
if( max->parent->right == pos.itNode )
max->parent->right = max;
else
max->parent->left = max;
}
else
rootnode = max;
}
else
{
NNnode *min = minNode( pos.itNode->right);
if( min->right != NULL )
{
min->right->parent = min->parent;
}
if( min->parent->left == min )
min->parent->left = min->right;
else
min->parent->right = min->right;
min->left = pos.itNode->left;
min->right = pos.itNode->right;
min->parent = pos.itNode->parent;
min->left->parent = min;
if( min->right != NULL )
min->right->parent = min;
if( min->parent != NULL)
{
if( min->parent->right == pos.itNode )
min->parent->right = min;
else
min->parent->left = min;
}
else
rootnode = min;
}
}
if( first == pos.itNode )
{
first = res.itNode;
}
delete pos.itNode;
--nrelements;
return res;
}
/*
add the first rootnode
*/
template<class T>
typename NNTree<T>::iter NNTree<T>::addFirst( T &e)
{
assert( nrelements == 0 );
return iter(newNode(e, NULL));
}
/*
add a new NNnode with the element e beyond the iter it
*/
template<class T>
typename NNTree<T>::iter NNTree<T>::addLeft( T &e, iter &it)
{
assert( it.itNode->left == NULL );
NNnode *nNode = newNode(e, it.itNode);
it.itNode->left = nNode;
if( it.itNode == first )
{
first = nNode;
}
return iter(nNode);
}
template<class T>
typename NNTree<T>::iter NNTree<T>::addRight( T &e, iter &it)
{
assert( it.itNode->right == NULL );
NNnode *nNode = newNode(e, it.itNode);
it.itNode->right = nNode;
return iter(nNode);
}
/*
add elem beyond given node
*/
template<class T>
typename NNTree<T>::iter NNTree<T>::addElem( T &e, iter &it)
{
assert( it.itNode != NULL );
if( it.itNode->right == NULL)
{
NNnode *nNode = newNode(e, it.itNode);
it.itNode->right = nNode;
return iter(nNode);
}
else
{
NNnode *n = minNode(it.itNode->right);
NNnode *nNode = newNode(e, n);
n->left = nNode;
return iter(nNode);
}
}
/*
iter functions
*/
template<class T>
typename NNTree<T>::iter& NNTree<T>::iter::operator++() //prefix
{
itNode = nextNode(itNode);
return *this;
}
template<class T>
typename NNTree<T>::iter& NNTree<T>::iter::operator--() //prefix
{
itNode = prevNode(itNode);
return *this;
}
/*
private functions
*/
template<class T>
typename NNTree<T>::NNnode *NNTree<T>::newNode( T &e, NNnode *p)
{
NNnode *newNode = new NNnode;
newNode->left = NULL;
newNode->right = NULL;
newNode->elem = e;
if( !nrelements )
{
first = newNode;
rootnode = newNode;
newNode->parent = NULL;
}
else
{
newNode->parent = p;
}
++nrelements;
return newNode;
}
template<class T>
unsigned int NNTree<T>::nodeCount( NNnode *n )
{
if( n != NULL )
return 1 + nodeCount(n->left) + nodeCount(n->right);
else
return 0;
}
template<class T>
typename NNTree<T>::NNnode *NNTree<T>::maxNode( NNnode *n)
{
while(n->right){
n = n->right;
}
return n;
}
template<class T>
typename NNTree<T>::NNnode *NNTree<T>::minNode( NNnode *n)
{
while(n->left){
n = n->left;
}
return n;
}
template<class T>
typename NNTree<T>::NNnode *NNTree<T>::iter::nextNode( NNnode *n)
{
if( n->right != NULL )
return minNode( n->right );
else
{
while( n->parent != NULL && n->parent->right == n )
{
n = n->parent;
}
return n->parent;
}
}
template<class T>
typename NNTree<T>::NNnode *NNTree<T>::iter::prevNode( NNnode *n)
{
if( n->left != NULL )
return NNTree<T>::maxNode( n->left );
else
{
while( n->parent != NULL && n->parent->left == n )
{
n = n->parent;
}
return n->parent;
}
}
template<class T>
void NNTree<T>::deleteAll( NNnode *node)
{
if( node )
{
deleteAll( node->left);
deleteAll( node->right);
delete node;
}
}
/*
Definitions for the operator knearestfilter
The struct FieldEntry is needed to insert
elements into a vector. The class NNSegTree
is a special segment tree for the operator
knearestfilter
*/
template<class timeType>
struct FieldEntry
{
long nodeid;
double maxdist;
timeType start, end;
int level;
FieldEntry( long node, double maxd, const timeType &s, const timeType &e,
int l):
nodeid(node),
maxdist(maxd),
start(s),
end(e),
level(l)
{}
};
/*
extend one more attribute: mindist
*/
template<class timeType>
struct EFieldEntry:public FieldEntry<timeType>
{
double mindist; //extension
EFieldEntry( long node, double mind,double maxd,int l,
const timeType &s, const timeType &e):
FieldEntry<timeType>(node,maxd,s,e,l),mindist(mind){}
};
template<class timeType>
class SegEntry {
public:
BBox<2> xyBox;
timeType start, end;
double mindist, maxdist;
int coverage;
long nodeid;
// TupleId tpid;
long tpid;
char direction;//new entry
SegEntry():
start(), end(),
mindist(0),maxdist(0),coverage(0),
nodeid( -1 ),
tpid( -1 )
{}
SegEntry( const BBox<2> &box, const timeType &s,
const timeType &e, double mind,
double maxd, int cov,long node, TupleId tid):
xyBox(box),
start(s), end(e),
mindist(mind),maxdist(maxd),coverage(cov),
nodeid( node ),
tpid( tid )
{}
virtual ~SegEntry()
{}
friend bool operator!=(const SegEntry<timeType>& i,
const SegEntry<timeType>& j)
{
return i.nodeid != j.nodeid || i.tpid != j.tpid;
}
bool operator<( const SegEntry<timeType>& e ) const
{
if( e.start != start)
{
return start < e.start;
}
else
{
//same starttimes
if( e.end != end )
{
return end < e.end;
}
else
{
//same times
return tpid < e.tpid;
}
}
}
};
template<class timeType>
class SegNode {
public:
timeType start, end;
SegNode<timeType>* left;
SegNode<timeType>* right;
SegNode<timeType>* parent;
NNTree<SegEntry<timeType> > segEntries;
SegNode( const timeType &s, const timeType &e) :
start(s), end(e), left(NULL),
right(NULL), parent(NULL), segEntries()
{}
};
template<class timeType>
class NNSegTree{
public:
NNSegTree( const timeType &s, const timeType &e);
~NNSegTree();
void insert( SegEntry<timeType> &s, int k );
bool erase( const timeType& start, const timeType& end,
long rnodeid, double dist);
void fillMap( std::map< SegEntry<timeType>, TupleId> &m);
int calcCoverage( const timeType& t1,const timeType& t2, double distance );
typedef typename NNTree<SegEntry<timeType> >::iter ITSE;
private:
SegNode<timeType> *sroot;
void makeEmpty( SegNode<timeType> *node);
void insertNode( SegEntry<timeType> &s, SegNode<timeType> *node, int k);
void eraseEntry( const timeType& start, const timeType& end, long rnodeid,
double dist, SegNode<timeType> *node, bool &result);
void checkErase( const timeType& t1, const timeType& t2, double distance,
SegNode<timeType> *node, int k );
void mapfill( std::map< SegEntry<timeType>, TupleId> &m,
SegNode<timeType> *node);
ITSE addEntry(NNTree<SegEntry<timeType> > &t, SegEntry<timeType> &e);
ITSE findEntry(NNTree<SegEntry<timeType> > &t, long rnodeid, double dist);
ITSE findEntryMindistance(NNTree<SegEntry<timeType> > &t, double dist);
int calcCoverage( const timeType& t1,const timeType& t2, double distance,
SegNode<timeType> *node, bool hasEqual );
};
/*
constructor
*/
template<class timeType>
NNSegTree<timeType>::NNSegTree( const timeType &s, const timeType &e)
{
sroot = new SegNode<timeType>(s, e);
}
/*
destructor
*/
template<class timeType>
NNSegTree<timeType>::~NNSegTree<timeType>()
{
makeEmpty( sroot );
}
/*
insert, inserts an elements in all nodes where
it is necessary. Some childs may be created.
This function calls the private recursive function
insertNode. Some elements would be needless.
They are deleted
*/
template<class timeType>
void NNSegTree<timeType>::insert( SegEntry<timeType> &s, int k )
{
insertNode( s, sroot, k );
}
/*
erase looks for an element in the segment tree
in all possible nodes. Every appearance is deleted.
This function calls the private recursive function
eraseEntry
*/
template<class timeType>
bool NNSegTree<timeType>::erase(const timeType& start,
const timeType& end,
long rnodeid, double dist)
{
bool result = false;
eraseEntry( start, end, rnodeid, dist, sroot, result );
return result;
}
/*
calls the private recursive method mapfill
to fill the given map with all elements which
are in the segment tree
*/
template<class timeType>
void NNSegTree<timeType>::fillMap( std::map< SegEntry<timeType>, TupleId> &m)
{
mapfill( m, sroot );
}
/*
calcCoverage calculates the reached coverage in the given
time intervall until the given distance. It calls the
recursive private method calcCoverage
*/
template<class timeType>
int NNSegTree<timeType>::calcCoverage( const timeType& t1,
const timeType& t2,
double distance )
{
return calcCoverage( t1, t2, distance, sroot, false );
}
/*
private functions of NNSegTree
*/
/*
makeEmpty is the private recursive funtion
to free all nodes of the segment tree.
It is calles by the destructor of the tree.
*/
template<class timeType>
void NNSegTree<timeType>::makeEmpty( SegNode<timeType> *node)
{
if( node )
{
makeEmpty( node->left );
makeEmpty( node->right);
delete node;
}
}
/*
mapfill is a private recursive method called by
fillMap. It fills a map with all elements which
are in the segment tree
*/
template<class timeType>
void NNSegTree<timeType>::mapfill( std::map< SegEntry<timeType>, TupleId> &m,
SegNode<timeType> *node)
{
if( node )
{
if( node->left )
{
mapfill( m, node->left );
mapfill( m, node->right);
}
ITSE it = node->segEntries.begin();
while( it != node->segEntries.end() )
{
assert( it->tpid != -1);
m[ *it ] = it->tpid;
++it;
}
}
}
/*
insertNode insert an element in all nodes where
it is necessary. Some childs may be created
*/
template<class timeType>
void NNSegTree<timeType>::insertNode( SegEntry<timeType> &s,
SegNode<timeType> *node, int k)
{
if( s.start <= node->start && s.end >= node->end)
{
// insert the element, the timeintervall is o.K.
addEntry(node->segEntries, s);
checkErase(s.start, s.end, s.maxdist, node, k);
}
else if( node->left != NULL)
{
//the node has childs
if( s.start < node->left->end && s.end <= node->left->end)
{
//both times are on the left
insertNode( s, node->left, k );
}
else if( s.start >= node->right->start )
{
//both times are on the right
insertNode( s, node->right, k );
}
else /* starttime on the left, endtime on the right */
{
insertNode( s, node->left, k );
insertNode( s, node->right, k );
}
}
else /* the node has no childs, make some */
{
if( s.start > node->start )
{
SegNode<timeType> *newleft = new SegNode<timeType>(node->start, s.start);
SegNode<timeType> *newright = new SegNode<timeType>(s.start, node->end);
newleft->parent = node;
newright->parent = node;
node->left = newleft;
node->right = newright;
insertNode( s, node->right, k );
}
else
{
/* the endtime was too low */
SegNode<timeType> *newleft = new SegNode<timeType>(node->start, s.end);
SegNode<timeType> *newright = new SegNode<timeType>(s.end, node->end);
newleft->parent = node;
newright->parent = node;
node->left = newleft;
node->right = newright;
insertNode( s, node->left, k );
}
}
}
/*
eraseEntry looks for an element in the segment tree
in all possible nodes. Every appearance is deleted
in the given (partial) tree
*/
template<class timeType>
void NNSegTree<timeType>::eraseEntry(const timeType& start,
const timeType& end, long rnodeid,
double dist, SegNode<timeType> *node, bool &result)
{
if( start <= node->start && end >= node->end)
{
ITSE it = findEntry( node->segEntries, rnodeid, dist);
if( it != node->segEntries.end() )
{
node->segEntries.erase( it );
result = true;
}
}
else if( node->left )
{
// there are childs to look for the element
if( start < node->left->end && end <= node->left->end)
{
//both times are on the left
eraseEntry( start, end, rnodeid, dist, node->left, result);
}
else if( start >= node->right->start )
{
//both times are on the right
eraseEntry( start, end, rnodeid, dist, node->right, result);
}
else /* starttime on the left, endtime on the right */
{
eraseEntry( start, end, rnodeid, dist, node->left, result);
eraseEntry( start, end, rnodeid, dist, node->right, result);
}
}
}
/*
addEntry inserts a element SegEntry in the
NNTree of the attribute segEntries of a
node of the segment tree
*/
template<class timeType>
typename NNSegTree<timeType>::ITSE
NNSegTree<timeType>::addEntry(NNTree<SegEntry<timeType> > &t,
SegEntry<timeType> &e)
{
if( t.size() == 0)
{
return t.addFirst(e);
}
double dist = e.maxdist;
ITSE it = t.root();
while( true)
{
double storeDistance = it->maxdist;
if( dist < storeDistance)
{
if( it.hasLeft() )
{
it.leftItem();
}
else
{
return t.addLeft( e, it);
}
}
else if( dist > storeDistance)
{
if( it.hasRight() )
{
it.rightItem();
}
else
{
return t.addRight( e, it);
}
}
else //same distance
{
return t.addElem( e, it );
}
}
}
/*
findEntry looks for a element SegEntry in the
NNTree of the attribute segEntries of a
node of the segment tree
*/
template<class timeType>
typename NNSegTree<timeType>::ITSE
NNSegTree<timeType>::findEntry(NNTree<SegEntry<timeType> > &t,
long rnodeid, double dist)
{
ITSE it = t.root();
bool havePos = false;
while( !havePos && it != t.end())
{
double storeDistance = it->maxdist;
if( dist < storeDistance)
{
if( it.hasLeft() )
{
it.leftItem();
}
else
{
havePos = true;
}
}
else if( dist > storeDistance)
{
if( it.hasRight() )
it.rightItem();
else
{
havePos = true;
}
}
else //same distance
{
havePos = true;
}
}
if( it != t.end() && rnodeid == it->nodeid){ havePos = true; }
else { havePos = false; }
ITSE pos1 = it;
ITSE pos2 = it;
while( !havePos && (pos1 != t.begin() || pos2 != t.end()))
{
if( pos1 != t.begin() )
{
--pos1;
if( rnodeid == pos1->nodeid)
{
pos2 = pos1;
havePos = true;
};
}
if( !havePos && pos2 != t.end() )
{
++pos2;
if( pos2 != t.end() && rnodeid == pos2->nodeid)
{
havePos = true;
}
}
}
return pos2;
}
/*
findEntryMindistance looks for a element SegEntry in the
NNTree of the attribute segEntries of a
node of the segment tree which has a mindistance
higher than the given distance
*/
template<class timeType>
typename NNSegTree<timeType>::ITSE
NNSegTree<timeType>::findEntryMindistance(NNTree<SegEntry<timeType> > &t,
double dist)
{
//the function looks first for a maxdistance higher because
// this is the key for the tree and
//goes then with the operator++ to the element where
//the mindistance is also higher
ITSE it = t.root();
bool havePos = false;
while( !havePos && it != t.end())
{
double storeDistance = it->maxdist;
if( dist < storeDistance)
{
if( it.hasLeft() )
{
it.leftItem();
}
else
{
havePos = true;
}
}
else if( dist > storeDistance)
{
if( it.hasRight() )
{
it.rightItem();
}
else
{
havePos = true;
}
}
else //same distance
{
havePos = true;
}
}
while( it != t.end())
{
if( it->mindist > dist )
{
return it;
}
++it;
}
return it;
}
/*
checkErase checks, if there some elements no longer needed
after the insertion of the element s into the given node.
This function deletes the needless elements.
*/
template<class timeType>
void NNSegTree<timeType>::checkErase( const timeType& t1,
const timeType& t2, double distance,
SegNode<timeType> *node, int k )
{
int c = calcCoverage( t1, t2, distance, sroot, true );
if( c >= k )
{
ITSE it = findEntryMindistance( node->segEntries, distance);
while( it != node->segEntries.end() )
{
if( it->mindist > distance )
{
it = node->segEntries.erase( it );
}
else
{
++it;
}
}
}
if( node->left )
{
//do the same for the childs
checkErase( node->left->start, node->left->end, distance, node->left, k);
checkErase( node->right->start, node->right->end, distance, node->right, k);
}
}
/*
calculates the reached coverage in the given timeintervall
until the given distance
*/
template<class timeType>
int NNSegTree<timeType>::calcCoverage(const timeType& t1,
const timeType& t2,
double distance,
SegNode<timeType> *node, bool hasEqual)
{
int result = 0;
if( node )
{
if( node->start <= t1 && node->end >= t2)
{
ITSE it = node->segEntries.begin();
if( hasEqual )
{
//includes also the elements with equal distance
while( it != node->segEntries.end() && it->maxdist <= distance)
{
result += it->coverage;
++it;
}
}
else
{
//includes only the elements with lower distance
while( it != node->segEntries.end() && it->maxdist < distance)
{
result += it->coverage;
++it;
}
}
}
if( node->left )
{
// there are childs to look for the element
if( t2 <= node->left->end)
{
//both times are on the left
result += calcCoverage( t1, t2, distance, node->left, hasEqual);
}
else if( t1 >= node->right->start )
{
//both times are on the right
result += calcCoverage( t1, t2, distance, node->right, hasEqual);
}
else /* starttime on the left, endtime on the right */
{
int lc, rc;
lc = calcCoverage( t1, node->left->end, distance, node->left,hasEqual);
rc = calcCoverage( node->right->start, t2, distance,
node->right, hasEqual);
result += MIN( lc, rc );
}
}
}
return result;
}
#endif