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

581 lines
12 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2008, University in Hagen,
Faculty of Mathematics and Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
1 The BBTree class
The BBTree is a data structure which can be used to determine the bounding box
of a moving point for a determines time interval.
*/
#ifndef BBTREE_H
#define BBTREE_H
#include "DateTime.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "Algebras/Rectangle/RectangleAlgebra.h"
#include <iostream>
template<class timeType>
class BBTreeNode;
template<class timeType>
class BBTree{
public:
/*
~Constructor~
This constructor creates a BBTree for a given temporalalgebra::MPoint;
*/
BBTree(const temporalalgebra::MPoint& p);
/*
~Copy constructor~
*/
BBTree(const BBTree& t);
/*
~Assignment Operator~
*/
BBTree& operator=(const BBTree& src);
/*
~Destructor~
*/
~BBTree();
/*
~getBox~
This Operator returns the bounding box of the mpoint
from which created it this tree when it is restricted to the
given time interval.
*/
Rectangle<2> getBox(
const temporalalgebra::Interval<timeType>& interval)const;
/*
~noLeafs~
Returns the number of leaves within that tree
*/
int noLeaves()const;
/*
~noNodes~
Returns the number of nodes within this tree.
*/
int noNodes() const;
/*
~height~
Returns the height of the tree.
*/
int height() const;
/*
~print~
Writes the tree to o;
*/
std::ostream& print(std::ostream& o) const;
private:
/*
~root~
Represents the root of this tree.
*/
BBTreeNode<timeType>* root;
/*
~createFromMPoint~
Builds the tree for a given mpoint.
*/
void createFromMPoint(const temporalalgebra::MPoint& p);
};
/*
Class BBTreeNode
An instance of that class represents a single node within a BBTree.
*/
template<class timeType>
static temporalalgebra::Interval<timeType> tottInterval(
const temporalalgebra::Interval<Instant>& iv){
temporalalgebra::Interval<timeType> result(iv.start.ToDouble(),
iv.end.ToDouble(),
iv.lc, iv.rc);
return result;
}
inline void toMinimum(double& s){
s = std::numeric_limits<double>::min();
}
inline void toMaximum(double& s){
s = std::numeric_limits<double>::max();
}
inline void toMinimum(datetime::DateTime& s){
s.ToMinimum();
}
inline void toMaximum(datetime::DateTime& s){
s.ToMaximum();
}
template<class timeType>
class BBTreeNode{
public:
/*
2.1 Constructors
2.1.1 Constructor for a leaf
*/
BBTreeNode(const temporalalgebra::UPoint& unit):
unit(new temporalalgebra::UPoint(unit)),
box(unit.BoundingBoxSpatial()),
left(0), right(0),
interval(tottInterval<timeType>(unit.timeInterval))
{ }
/*
2.1.2 Constructor for inner nodes
*/
BBTreeNode(BBTreeNode<timeType>* left, BBTreeNode<timeType>* right){
unit = 0;
if(left){
if(right){
box = left->box.Union(right->box);
} else {
box = left->box;
}
} else {
if(right){
box = right->box;
}
}
this->left = left;
this->right = right;
timeType min(0.0);
timeType max(0.0);
toMinimum(min);
toMaximum(max);
if(left){
min=left->interval.start;
max=left->interval.end;
}
if(right){
if(right->interval.start < min){
min = right->interval.start;
}
if(right->interval.end > max){
max = right->interval.end;
}
}
interval.start = min;
interval.end = max;
interval.lc = true;
interval.rc = true;
}
/*
2.1. Copy Constructor
performs a deepth copy
*/
BBTreeNode(const BBTreeNode<timeType>& src){
if(src.unit){
unit = new temporalalgebra::UPoint(*src.unit);
} else {
unit = 0;
}
box = src.box;
if(src.left){
left = new BBTreeNode<timeType>(*src.left);
} else {
left = 0;
}
if(src.right){
right = new BBTreeNode<timeType>(*src.right);
} else {
right = 0;
}
interval.start = src.interval.start;
interval.end = src.interval.end;
interval.lc = src.interval.lc;
interval.rc = src.interval.rc;
}
/*
2.2 Assignment Operator
performs a deep copy
*/
BBTreeNode<timeType>& operator=(const BBTreeNode<timeType>& src){
if(src.unit){
unit = new temporalalgebra::UPoint(*src.unit);
} else {
unit = 0;
}
box = src.box;
if(src.left){
left = new BBTreeNode<timeType>(*src.left);
} else {
left = 0;
}
if(src.right){
right = new BBTreeNode<timeType>(*src.right);
} else {
right = 0;
}
interval.start = src.interval.start;
interval.end = src.interval.end;
interval.lc = src.interval.lc;
interval.rc = src.interval.rc;
return *this;
}
/*
2. Destructor
*/
~BBTreeNode(){
if(unit){
delete unit;
unit=0;
}
if(left){
delete left;
left = 0;
}
if(right){
delete right;
right = 0;
}
}
/*
2.4 ~getBox~
*/
inline bool AlmostEqual(const Instant& i1, const Instant& i2)const{
return i1 == i2;
}
inline bool ivInside(const temporalalgebra::Interval<timeType>& iv1,
const temporalalgebra::Interval<timeType>& iv2) const{
const timeType& e1 = iv1.end;
const timeType& e2 = iv2.end;
return( ( (iv1.start > iv2.start) ||
(AlmostEqual(iv1.start, iv2.start) && ( !iv1.lc || iv2.lc ) ) ) &&
( (e1 < e2) ||
( AlmostEqual(iv1.end, iv2.end) && ( !iv1.rc || iv2.rc ) ) ) );
}
inline bool ivDisjoint(const temporalalgebra::Interval<timeType>& iv1,
const temporalalgebra::Interval<timeType>& iv2) const{
const timeType& e1 = iv1.end;
return( ( (e1 < iv2.start) ||
( AlmostEqual(iv1.end, iv2.start) && ( !iv1.lc || !iv2.lc ) ) ) ||
( (iv1.start > iv2.end) ||
( AlmostEqual(iv1.start, iv2.end) && ( !iv1.rc || !iv2.rc ) ) ) );
}
Rectangle<2> getBox(const temporalalgebra::Interval<timeType>& interval) const{
//disjoint intervals -> return undef
if(ivDisjoint(interval,this->interval)){
Rectangle<2> res(false);
return res;
}
if(ivInside(this->interval, interval)){
return box;
}
if(unit){ // a leaf node
timeType mind;
if(interval.start<this->interval.start){
mind = this->interval.start;
} else {
mind = interval.start;
}
timeType maxd;
const timeType& ie = interval.end;
const timeType& te = this->interval.end;
if(ie<te){
maxd = interval.end;
} else {
maxd = this->interval.end;
}
Point p0,p1;
unit->TemporalFunction(datetime::DateTime(mind),p0,true);
unit->TemporalFunction(datetime::DateTime(maxd),p1,true);
assert(p0.IsDefined());
assert(p1.IsDefined());
return p0.BoundingBox().Union(p1.BoundingBox());
} else { // an inner node
Rectangle<2> Lres(false);
if(left){
Lres = left->getBox(interval);
}
Rectangle<2> Rres(false);
if(right){
Rres = right->getBox(interval);
}
if(!Lres.IsDefined()){
return Rres;
} else {
if(!Rres.IsDefined()){
return Lres;
} else { // both are defined
return Lres.Union(Rres);
}
}
}
}
int noLeaves() const{
if(unit){
return 1;
} else {
int l = left?left->noLeaves():0;
int r = right?right->noLeaves():0;
return l+r;
}
}
int noNodes() const{
int l = left?left->noNodes():0;
int r = right?right->noNodes():0;
return l+r+1;
}
int height() const{
if(unit) return 0;
int l = left?left->height():0;
int r = right?right->height():0;
return std::max(l,r) +1;
}
std::ostream& print(std::ostream& o) const{
if(unit){
o << "\"" << "U" << "\"";
return o;
} else {
o << "(";
o << "\"" << "I" << "\"";
if(left){
left->print(o);
} else {
o << "()";
}
if(right){
right->print(o);
} else {
o << "()";
}
o << ")";
return o;
}
}
private:
temporalalgebra::UPoint* unit;
Rectangle<2> box;
BBTreeNode<timeType>* left;
BBTreeNode<timeType>* right;
temporalalgebra::Interval<timeType> interval;
};
template<class timeType>
BBTree<timeType>::BBTree(const temporalalgebra::MPoint& p):root(0){
createFromMPoint(p);
}
template<class timeType>
BBTree<timeType>::BBTree(const BBTree<timeType>& t):root(0){
if(t.root){
root = new BBTreeNode<timeType>(*t.root);
} else {
root = 0;
}
}
template<class timeType>
BBTree<timeType>& BBTree<timeType>::operator=(const BBTree<timeType>& src){
if(src.root){
root = new BBTreeNode<timeType>(*src.root);
} else {
root = 0;
}
return *this;
}
template<class timeType>
BBTree<timeType>::~BBTree(){
if(root){
delete root;
root = 0;
}
}
template<class timeType>
Rectangle<2> BBTree<timeType>::getBox(
const temporalalgebra::Interval<timeType>& interval)const{
if(root){
return root->getBox(interval);
} else {
Rectangle<2> res(false);
return res;
}
}
template<class timeType>
int BBTree<timeType>::noLeaves() const{
if(root) {
return root->noLeaves();
} else {
return 0;
}
}
template<class timeType>
int BBTree<timeType>::noNodes() const{
if(root) {
return root->noNodes();
} else {
return 0;
}
}
template<class timeType>
int BBTree<timeType>::height() const{
if(root){
return root->height();
} else {
return -1;
}
}
template<class timeType>
void BBTree<timeType>::createFromMPoint(const temporalalgebra::MPoint& p){
int size = p.GetNoComponents();
if(size==0){
root = 0;
return;
}
std::stack<std::pair<int, BBTreeNode<timeType>*> > astack;
for(int i=0; i< size; i++){
temporalalgebra::UPoint unit;
p.Get(i,unit);
BBTreeNode<timeType>* newNode = new BBTreeNode<timeType>(unit);
std::pair<int, BBTreeNode<timeType>*> entry(0, newNode);
if(astack.size()==0){ // first entry
astack.push(entry);
} else {
std::pair<int, BBTreeNode<timeType>*> top = astack.top();
bool done = false;
while(!done && (top.first == entry.first)){
BBTreeNode<timeType>* next =
new BBTreeNode<timeType>(top.second,entry.second);
astack.pop();
entry = std::pair<int, BBTreeNode<timeType>*> (top.first+1,next);
done = astack.empty();
if(!done){
top = astack.top();
}
}
astack.push(entry);
}
}
std::pair<int, BBTreeNode<timeType>*> top = astack.top();
BBTreeNode<timeType>* r = top.second;
astack.pop();
while(!astack.empty()){
top = astack.top();
astack.pop();
r = new BBTreeNode<timeType>(top.second,r);
}
root = r;
}
template<class timeType>
std::ostream& BBTree<timeType>::print(std::ostream& o) const{
if(root){
o << "( tree ";
root->print(o);
o << ")";
return o;
} else {
o << "(tree ())";
return o;
}
}
#endif