/********************************************************************* * * * Copyright (c) 1997,1998, 1999 * * Multimedia DB Group and DEIS - CSITE-CNR, * * University of Bologna, Bologna, ITALY. * * * * All Rights Reserved. * * * * Permission to use, copy, and distribute this software and its * * documentation for NON-COMMERCIAL purposes and without fee is * * hereby granted provided that this copyright notice appears in * * all copies. * * * * THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE * * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR * * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A * * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * * DERIVATIVES. * * * *********************************************************************/ #include "MTcursor.h" #include "MT.h" #include "MTpredicate.h" class MTnode; int sign(double x) { if(x>0) return 1; if(x<0) return -1; return 0; } int comparedst(dst *a, dst *b) { return sign(a->Bound()-b->Bound()); } int comparedst(dst& a, dst& b) { return sign(a.Bound()-b.Bound()); } int compareentry(MTentry *a, MTentry *b) { return sign(a->maxradius()-b->maxradius()); } MTcursor::MTcursor(const MT& tree, const MTpred& query): queue(comparedst), results(compareentry), tree(tree) { GiSTpath path; dst *d; path.MakeRoot(); d=new dst(path, 0, MAXDOUBLE); this->query=(MTpred *)query.Copy(); queue.Insert(d); } BOOL MTcursor::IsReady() const { if(queue.IsEmpty()) return (!results.IsEmpty()); else if(results.IsEmpty()) return FALSE; else return (queue.First()->Bound()>=results.First()->maxradius()); } double MTcursor::Bound() const { if(queue.IsEmpty()) if(results.IsEmpty()) return maxDist(); else return(results.First()->maxradius()); else if(results.IsEmpty()) return(queue.First()->Bound()); else return MIN(queue.First()->Bound(), results.First()->maxradius()); } void MTcursor::FetchNode() { if(queue.IsEmpty()) return; int i, iprev, inext; // these are the previous and the next entries to be examined dst *d=queue.RemoveFirst(); MTnode *node=(MTnode *)tree.ReadNode(d->Path()); // retrieve next node to be examined // cout << "Read node " << node->Path() << ": " << d->Bound() << endl; // search the first children to be examined for(unsigned int i=0; iNumEntries(); i++) { // for each entry in the current node MTentry *e=(MTentry *)((*node)[i].Ptr()); double dist=query->distance(e->object()); if(!e->IsLeaf()) { // insert the child node in the priority queue dst *dnew; GiSTpath path=node->Path(); double dmin=dist-e->maxradius(), dmax=dist+e->maxradius(); // these are lower- and upper-bounds on the distances of the descendants of the entry from the query object if(dmin<0) dmin=0; path.MakeChild(e->Ptr()); dnew=new dst(path, dmin, dist); queue.Insert(dnew); } else { // insert the entry in the result list MTentry *key=(MTentry *)e->Copy(); key->setminradius(0); key->setmaxradius(dist); // we insert the actual distance from the query object as the key radius results.Insert(key); // cout << "Inserted (" << dist << ") into list in " << j <<"-th place\n"; } } delete node; // delete examined node delete d; } MTentry * MTcursor::Next() { while(!IsReady()) FetchNode(); if(!results.IsEmpty()) return results.RemoveFirst(); else return NULL; } MTcursor::~MTcursor() { delete query; while(!results.IsEmpty()) delete results.RemoveFirst(); while(!queue.IsEmpty()) delete queue.RemoveFirst(); }