RTree.h

Go to the documentation of this file.
00001 // $Id: RTree.h 264 2006-08-02 08:14:39Z bingmann $
00002 
00003 #ifndef VGS_RTree_H
00004 #define VGS_RTree_H
00005 
00006 #include <assert.h>
00007 
00008 #include <vector>
00009 #include <stack>
00010 #include <queue>
00011 #include <algorithm>
00012 #include <limits>
00013 #include <fstream>
00014 #include <iostream>
00015 #include <ostream>
00016 
00017 #include "GraphTypes.h"
00018 
00019 namespace VGServer {
00020 
00021 //#define R_TREE_LINEAR
00022 //#define R_TREE_QUADRATIC
00023 #define R_STAR_TREE
00024 
00028 //template <typename _CoordType, typename _AreaType>
00029 class RTree
00030 {
00031 public:
00032     // public typedefs of the template parameters
00033     //typedef _CoordType        CoordType;
00034     //typedef _AreaType AreaType;
00035     typedef coord_t     CoordType;
00036     typedef long long   AreaType;
00037 
00038     // *** Structures used in the the R-Tree
00039 
00040     // forward declarations
00041     class Point;
00042     class Rect;
00043 
00045     class Point
00046     {
00047     public:
00048         CoordType       x, y;
00049 
00051         inline Point()
00052         { }
00053 
00055         inline Point(CoordType _x, CoordType _y)
00056             : x(_x), y(_y)
00057         { }
00058 
00060         static inline AreaType square(AreaType a)
00061         { return a * a; }
00062 
00064         inline AreaType getDistanceSquare(const Point &p) const
00065         {
00066             return square( p.x - x ) 
00067                  + square( p.y - y );
00068         }
00069 
00071         inline AreaType getDistanceSquare(CoordType px, CoordType py) const
00072         {
00073             return square( px - x ) 
00074                  + square( py - y );
00075         }
00076 
00078         inline AreaType getMinimumDistanceSquare(const class Rect &r) const
00079         {
00080             AreaType a = 0;
00081 
00082             if (x < r.x1 || r.x2 < x)
00083                 a += square( std::min(x - r.x1, x - r.x2) );
00084 
00085             if (y < r.y1 || r.y2 < y)
00086                 a += square( std::min(y - r.y1, y - r.y2) );
00087 
00088             return a;
00089         }
00090 
00092         inline AreaType getDistanceLineSquare(CoordType x1, CoordType y1, CoordType x2, CoordType y2) const
00093         {
00094             // Based on comp.graphics.algorithms' FAQ
00095 
00096             double l = square(x1 - x2) + square(y1 - y2); // square length of line (x1,y1)-(x2,y2)
00097 
00098             // scalar product of this point on the line.
00099             double r = static_cast<double>((x - x1) * (x2 - x1) + (y - y1) * (y2 - y1)) / l;
00100 
00101             if (r <= 0)
00102             {
00103                 // projection point is beyond the line, so we can use the simple distance
00104                 return square(x1 - x) + square(y1 - y);
00105             }
00106             else if (r >= 1)
00107             {
00108                 // projection point is beyond the line, so we can use the simple distance
00109                 return square(x2 - x) + square(y2 - y);
00110             }
00111             else
00112             {
00113                 // dunno how this works
00114                 double s = static_cast<double>(square( (y1 - y) * (x2 - x1) - (x1 - x) * (y2 - y1) )) / l;
00115                 
00116                 return static_cast<AreaType>(s);
00117             }
00118         }
00119     };
00120 
00122     class Rect
00123     {
00124     public:
00125         CoordType       x1, y1, x2, y2;
00126 
00128         inline Rect()
00129         { }
00130 
00132         inline Rect(CoordType _x1, CoordType _y1, CoordType _x2, CoordType _y2)
00133             : x1(_x1), y1(_y1), x2(_x2), y2(_y2)
00134         {
00135             assert(x1 <= x2);
00136             assert(y1 <= y2);
00137         }
00138 
00140         inline bool valid() const
00141         {
00142             return (x1 <= x2) && (y1 <= y2);
00143         }
00144 
00146         inline bool operator==(const Rect &o) const
00147         {
00148             return (x1 == o.x1) && (y1 == o.y1) && (x2 == o.x2) && (y2 == o.y2);
00149         }
00150 
00153         inline void setInfinite()
00154         {
00155             x1 = y1 = std::numeric_limits<CoordType>::max();
00156             x2 = y2 = std::numeric_limits<CoordType>::min();
00157         }
00158 
00160         inline void combineRect(const Rect &r)
00161         {
00162             x1 = std::min(x1, r.x1);
00163             y1 = std::min(y1, r.y1);
00164             x2 = std::max(x2, r.x2);
00165             y2 = std::max(y2, r.y2);
00166         }
00167 
00169         inline void combineRects(const Rect &a, const Rect &b)
00170         {
00171             x1 = std::min(a.x1, b.x1);
00172             y1 = std::min(a.y1, b.y1);
00173             x2 = std::max(a.x2, b.x2);
00174             y2 = std::max(a.y2, b.y2);
00175         }
00176 
00178         inline void intersectRect(const Rect &a)
00179         {
00180             x1 = std::max(a.x1, x1);
00181             y1 = std::max(a.y1, y1);
00182             x2 = std::min(a.x2, x2);
00183             y2 = std::min(a.y2, y2);
00184         }
00185 
00187         inline void intersectRects(const Rect &a, const Rect &b)
00188         {
00189             x1 = std::max(a.x1, b.x1);
00190             y1 = std::max(a.y1, b.y1);
00191             x2 = std::min(a.x2, b.x2);
00192             y2 = std::min(a.y2, b.y2);
00193         }
00194 
00196         inline AreaType getArea() const
00197         {
00198             return static_cast<AreaType>(x2 - x1) * static_cast<AreaType>(y2 - y1);
00199         }
00200 
00202         inline AreaType getIntersectingArea(const Rect &a) const
00203         {
00204             if (x2 < a.x1 || a.x2 < x1 || y2 < a.y2 || a.y2 < y2) return 0;
00205 
00206             return static_cast<AreaType>(std::min(a.x2, x2) - std::max(a.x1, x1))
00207                  * static_cast<AreaType>(std::min(a.y2, y2) - std::max(a.y1, y1));
00208         }
00209 
00211         inline AreaType getMargin() const
00212         {
00213             return 2 * static_cast<AreaType>( (x2 - x1) + (y2 - y1) );
00214         }
00215 
00217         inline Point getCenter() const
00218         {
00219             return Point(x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2);
00220         }
00221 
00223         inline bool containsRect(const Rect &r) const
00224         {
00225             return (x1 <= r.x1) && (y1 <= r.y1) && (r.x2 <= x2) && (r.y2 <= y2);
00226         }
00227         
00229         inline bool touchesRect(const Rect &r) const
00230         {
00231             // note that this will not work for floating point numbers.
00232             return (x1 == r.x1) || (y1 == r.y1) || (r.x2 == x2) || (r.y2 == y2);
00233         }
00234 
00237         inline bool intersectsRect(const Rect &r) const
00238         {
00239             return (x1 <= r.x2 && x2 >= r.x1 && y1 <= r.y2 && y2 >= r.y1);
00240         }
00241     };
00242 
00244     struct LevelStats
00245     {
00247         unsigned int nodes;
00248 
00250         unsigned int children;
00251 
00253         unsigned int unusedchildren;
00254 
00256         unsigned int bytes;
00257 
00259         unsigned int unusedbytes;
00260 
00262         AreaType overlap;
00263         
00265         AreaType wastearea;
00266 
00268         inline LevelStats()
00269         {
00270             nodes = 0;
00271             children = 0;
00272             unusedchildren = 0;
00273             bytes = 0;
00274             unusedbytes = 0;
00275             overlap = 0;
00276             wastearea = 0;
00277         }
00278 
00280         inline LevelStats & operator+=(const LevelStats &s)
00281         {
00282             nodes += s.nodes;
00283             children += s.children;
00284             unusedchildren += s.unusedchildren;
00285             bytes += s.bytes;
00286             unusedbytes += s.unusedbytes;
00287             overlap += s.overlap;
00288             wastearea += s.wastearea;
00289             return *this;
00290         }
00291     };
00292 
00294     struct Stats
00295     {
00297         std::vector<LevelStats> level;
00298 
00300         inline Stats()
00301         {
00302         }
00303     };
00304     
00308     template <typename _DataType, typename _DataTypeCallback>
00309     class Tree
00310     {
00311     public:
00312         // *** Parameters of the R-Tree
00313 
00314         typedef _DataType               DataType;
00315         typedef const _DataType&        DataRef;
00316 
00317         typedef _DataTypeCallback       DataTypeCallback;
00318 
00319         typedef unsigned int pageid_t;
00320 
00321         static const unsigned int       pagesize = 32;
00322 
00323         static const unsigned int       pageminfill = 12;
00324 
00325         unsigned int                    reinsertnum;
00326 
00327     public:
00328     
00330         struct ReinsertDist
00331         {
00332             unsigned int        childid;
00333             AreaType    distance;
00334 
00335             static inline bool order_distance(const ReinsertDist &a, const ReinsertDist &b)
00336             {
00337                 return a.distance < b.distance;
00338             }
00339             static inline bool order_childid(const ReinsertDist &a, const ReinsertDist &b)
00340             {
00341                 return a.childid < b.childid;
00342             }
00343         };
00344 
00345     protected:
00347         class LeafNode;
00348         class InnerNode;
00349 
00350         class InnerNodeData;
00351         class LeafNodeData;
00352 
00354         class NodeHead
00355         {
00356         public:
00359             unsigned short      level;
00360         
00362             unsigned short      childnum;
00363 
00365             Rect                nodeMBR;
00366 
00367             // *** Operations within NodeHead
00368 
00370             inline void initializeRoot()
00371             {
00372                 nodeMBR.setInfinite();
00373                 level = 0;
00374                 childnum = 0;
00375             }
00376 
00378             inline void initializeSibling(unsigned int _level)
00379             {
00380                 nodeMBR.setInfinite();
00381                 level = _level;
00382                 childnum = 0;
00383             }
00384         };
00385 
00389         template <typename _NodeData>
00390         class Node : public NodeHead
00391         {
00392         public:
00394             typedef _NodeData   NodeData;
00395 
00397             typedef Node<NodeData>      NodeType;
00398 
00400             NodeData    children[pagesize];
00401 
00402             // *** Primitive Operations
00403 
00405             inline void recalcChildrenMBR(const Tree &tree, class Rect &dest) const
00406             {
00407                 dest.setInfinite();
00408 
00409                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00410                     dest.combineRect(children[ci].getMBR(tree));
00411             }
00412 
00415             unsigned int        findLeastEnlargement(const Tree &tree, const Rect &newrect) const
00416             {
00417                 AreaType area = std::numeric_limits<AreaType>::max();
00418                 unsigned int bestchild = std::numeric_limits<unsigned int>::max();
00419 
00420                 Rect rt;
00421 
00422                 // search through the children rectangles
00423                 for(unsigned int i = 0; i < this->childnum; i++)
00424                 {
00425                     rt.combineRects(newrect, children[i].getMBR(tree));
00426 
00427                     AreaType enlarge = rt.getArea() - children[i].getMBR(tree).getArea();
00428 
00429                     if (enlarge < area)
00430                     {
00431                         area = enlarge;
00432                         bestchild = i;
00433                     }
00434                     // break the tie between equal enlargements
00435                     else if (enlarge == area)
00436                     {
00437                         if (rt.getArea() < children[bestchild].getMBR(tree).getArea())
00438                         {
00439                             bestchild = i;
00440                         }
00441                     }
00442                 }
00443     
00444                 assert( bestchild < this->childnum );
00445 
00446                 return bestchild;
00447             }
00448 
00451             unsigned int        findLeastOverlap(const Tree &tree, const Rect &newrect) const
00452             {
00453                 unsigned int min_bestchild = std::numeric_limits<unsigned int>::max();
00454                 AreaType min_overlap = std::numeric_limits<AreaType>::max();
00455                 AreaType min_enlarge = std::numeric_limits<AreaType>::max();
00456 
00457                 Rect rt, ru;
00458 
00459                 for (unsigned int ci = 0; ci < this->childnum; ci++)
00460                 {
00461                     // calculate the needed rectangle
00462                     rt.combineRects(newrect, children[ci].getMBR(tree));
00463 
00464                     AreaType overlap = 0;
00465 
00466                     // calculate the overlap of the new combine rectangle
00467                     for(unsigned int cj = 0; cj < this->childnum; cj++)
00468                     {
00469                         if (ci == cj) continue;
00470 
00471                         AreaType isa = rt.getIntersectingArea(children[cj].getMBR(tree));
00472 
00473                         if (isa > 0)
00474                         {
00475                             overlap += isa - children[ci].getMBR(tree).getIntersectingArea(children[cj].getMBR(tree));
00476                         }
00477                     }
00478 
00479                     // and the area enlargement
00480                     AreaType enlarge = rt.getArea() - children[ci].getMBR(tree).getArea();
00481 
00482                     // find the minimum overlap
00483                     if (min_overlap > overlap)
00484                     {
00485                         min_bestchild = ci;
00486                         min_overlap = overlap;
00487                         min_enlarge = enlarge;
00488                     }
00489                     // break ties by choosing the lower area enlargement
00490                     else if (min_overlap == overlap)
00491                     {
00492                         if (min_enlarge > enlarge)
00493                         {
00494                             min_bestchild = ci;
00495                             min_enlarge = enlarge;
00496                         }
00497                         // break further ties by choosing the rectangle with smaller area
00498                         else if (min_enlarge == enlarge)
00499                         {
00500                             if (children[min_bestchild].getMBR(tree).getArea() > children[ci].getMBR(tree).getArea())
00501                             {
00502                                 min_bestchild = ci;
00503                                 min_enlarge = enlarge;
00504                             }
00505                         }
00506                     }
00507                 }
00508 
00509                 assert( min_bestchild < this->childnum );
00510 
00511                 return min_bestchild;
00512             }
00513 
00514             // *** Simple walking of the tree
00515 
00518             class NodeHead*     chooseSubtree(Tree &tree, const Rect &newrect, unsigned int maxlevel, std::stack<pageid_t>& path)
00519             {
00520                 if (this->level == maxlevel) return this;
00521 
00522 #if defined(R_TREE_LINEAR) || defined(R_TREE_QUADRATIC)
00523 
00524                 unsigned int child = findLeastEnlargement(tree, newrect);
00525 
00526 #elif defined(R_STAR_TREE)
00527 
00528                 unsigned int child;
00529                 if (this->level == 1) // if children nodes are leaves
00530                 {
00531                     child = findLeastOverlap(tree, newrect);
00532                 }
00533                 else
00534                 {
00535                     child = findLeastEnlargement(tree, newrect);
00536                 }
00537 
00538 #endif
00539 
00540                 assert(this->level != 0);
00541                 class InnerNode *in = reinterpret_cast<class InnerNode*>(this);
00542 
00543                 pageid_t childpage = in->children[child].page;
00544 
00545                 class NodeHead *childnode = tree.pageman.getPage(childpage);
00546                 path.push(childpage);
00547 
00548                 if (childnode->level == 0) return childnode;
00549 
00550                 return static_cast<class InnerNode*>(childnode)->chooseSubtree(tree, newrect, maxlevel, path);
00551             }
00552 
00554             class LeafNode* findLeaf(Tree &tree, const class LeafNodeData &rmdata, std::queue<pageid_t>& path)
00555             {
00556                 if (this->level == 0)
00557                 {
00558                     LeafNode *ln = reinterpret_cast<LeafNode*>(this);
00559 
00560                     // look through children rectangles and compare data
00561                     for(unsigned int ci = 0; ci < ln->childnum; ci++)
00562                     {
00563                         if (ln->children[ci] == rmdata)
00564                         {
00565                             return ln;
00566                         }
00567                     }
00568                 }
00569                 else
00570                 {
00571                     InnerNode *in = reinterpret_cast<InnerNode*>(this);
00572 
00573                     Rect rmrect = rmdata.getMBR(tree);
00574 
00575                     // look through children sub-rectangles and descend into those
00576                     // enclosing rect.
00577                     for(unsigned int ci = 0; ci < in->childnum; ci++)
00578                     {
00579                         if (in->children[ci].getMBR(tree).containsRect(rmrect))
00580                         {
00581                             NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00582 
00583                             LeafNode *ret;
00584                             if (cn->level == 0) 
00585                                 ret = static_cast<LeafNode*>(cn)->findLeaf(tree, rmdata, path);
00586                             else
00587                                 ret = static_cast<InnerNode*>(cn)->findLeaf(tree, rmdata, path);
00588 
00589                             if (ret)
00590                             {
00591                                 path.push(in->children[ci].page);
00592                                 return ret;
00593                             }
00594                         }
00595                     }
00596                 }
00597                 return NULL;
00598             }
00599 
00601             void writeFig(const Tree &tree, std::ostream &o, int maxlevel) const
00602             {
00603                 if (static_cast<int>(this->level) < maxlevel) return;
00604 
00605                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00606                 {
00607                     if (this->level > 0)
00608                     {
00609                         // descend into child rectangle
00610                         const InnerNode *in = reinterpret_cast<const InnerNode*>(this);
00611 
00612                         NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00613                     
00614                         if (cn->level == 0)
00615                             static_cast<LeafNode*>(cn)->writeFig(tree, o, maxlevel);
00616                         else
00617                             static_cast<InnerNode*>(cn)->writeFig(tree, o, maxlevel);
00618                     }
00619 
00620                     const Rect &rect = children[ci].getMBR(tree);
00621 
00622                     if (rect.getArea() == 0) continue; // xfig doesnt like non-rectangles
00623 
00624                     // output rectangle as fig polyline
00625                     o << "2 2 0 1 " << 32+this->level << " 7 " << 100-this->level << " -1 -1 0.000 0 0 -1 0 0 5\n"
00626                       << "       "
00627                       << rect.x1 << " " << rect.y1 << " "
00628                       << rect.x2 << " " << rect.y1 << " "
00629                       << rect.x2 << " " << rect.y2 << " "
00630                       << rect.x1 << " " << rect.y2 << " "
00631                       << rect.x1 << " " << rect.y1 << "\n";
00632                 }
00633             }
00634 
00636             bool                checkNode(const Tree &tree, unsigned int thislevel, unsigned int *numentries) const
00637             {
00638                 assert(this->level == thislevel);
00639 
00640                 if (this->level > 0)
00641                 {
00642                     // descend into child rectangles
00643                     const InnerNode *in = reinterpret_cast<const InnerNode*>(this);
00644 
00645                     for(unsigned int ci = 0; ci < in->childnum; ci++)
00646                     {
00647                         NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00648 
00649                         if (cn->level == 0) {
00650                             if (!static_cast<const LeafNode*>(cn)->checkNode(tree, thislevel-1, numentries)) return false;
00651                         }
00652                         else {
00653                             if (!static_cast<const InnerNode*>(cn)->checkNode(tree, thislevel-1, numentries)) return false;
00654                         }
00655                     }
00656                 }
00657 
00658                 // check that the nodeMBR corresponds to the children MBRs
00659                 Rect r;
00660                 recalcChildrenMBR(tree, r);
00661                 assert(r == this->nodeMBR);
00662 
00663                 // check minimum fill
00664                 assert(this->childnum >= pageminfill or this->level == tree.levels);
00665 
00666                 // calculate valid entries
00667                 if (this->level == 0)
00668                     numentries += this->childnum;
00669 
00670                 return true;
00671             }
00672 
00674             void calcStats(const Tree &tree, Stats &s) const
00675             {
00676                 AreaType overlap = 0;
00677 
00678                 // calculate overlap
00679                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00680                 {
00681                     for(unsigned int cj = ci+1; cj < this->childnum; cj++)
00682                     {
00683                         assert(ci != cj);
00684                         overlap += children[ci].getMBR(tree).getIntersectingArea(children[cj].getMBR(tree));
00685                     }
00686                 }
00687 
00688                 // calculate "outter" space
00689 
00690                 AreaType waste = this->nodeMBR.getArea();
00691                 Rect rup;
00692                 rup.setInfinite();
00693 
00694                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00695                 {
00696                     Rect rnew;
00697                     rnew.intersectRects(rup, children[ci].getMBR(tree));
00698 
00699                     if (!rup.valid()) { // first rectangle
00700                         waste -= rnew.getArea();
00701                     }
00702                     else { // subtract the enlargement
00703                         waste -= rnew.getArea() - rup.getArea();
00704                     }
00705 
00706                     rup = rnew;
00707                 }
00708 
00709                 assert(waste >= 0);
00710                 
00711                 // add up stats
00712                 LevelStats &ls = s.level.at(this->level);
00713 
00714                 ls.nodes++;
00715                 ls.children += this->childnum;
00716                 ls.unusedchildren += pagesize - this->childnum;
00717                 ls.bytes += sizeof(*this);
00718                 ls.unusedbytes += (pagesize - this->childnum) * sizeof(NodeData);
00719                 ls.overlap += overlap;
00720                 ls.wastearea += waste;
00721 
00722                 if (this->level > 0)
00723                 {
00724                     // descend into child rectangles
00725                     const InnerNode *in = reinterpret_cast<const InnerNode*>(this);
00726 
00727                     for(unsigned int ci = 0; ci < in->childnum; ci++)
00728                     {
00729                         NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00730 
00731                         if (cn->level == 0)
00732                             static_cast<LeafNode*>(cn)->calcStats(tree, s);
00733                         else
00734                             static_cast<InnerNode*>(cn)->calcStats(tree, s);
00735                     }
00736                 }
00737             }
00738 
00740             AreaType    calcOverlap(const Tree &tree) const
00741             {
00742                 AreaType overlap = 0;
00743     
00744                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00745                 {
00746                     for(unsigned int cj = ci+1; cj < this->childnum; cj++)
00747                     {
00748                         assert(ci != cj);
00749                         overlap += children[ci].getMBR(tree).getIntersectingArea(children[cj].getMBR(tree));
00750                     }
00751                 }
00752 
00753                 if (this->level > 0)
00754                 {
00755                     // descend into child rectangles
00756                     const InnerNode *in = reinterpret_cast<const InnerNode*>(this);
00757 
00758                     for(unsigned int ci = 0; ci < in->childnum; ci++)
00759                     {
00760                         NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00761 
00762                         if (cn->level == 0)
00763                             overlap += static_cast<LeafNode*>(cn)->calcOverlap(tree);
00764                         else
00765                             overlap += static_cast<InnerNode*>(cn)->calcOverlap(tree);
00766                     }
00767                 }
00768     
00769                 return overlap;
00770             }
00771         
00773             AreaType    calcWasteArea(const Tree &tree) const
00774             {
00775                 AreaType waste = this->nodeMBR.getArea();
00776                 Rect rup;
00777                 rup.setInfinite();
00778 
00779                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00780                 {
00781                     Rect rnew;
00782                     rnew.intersectRects(rup, children[ci].getMBR(tree));
00783 
00784                     if (!rup.valid()) { // first rectangle
00785                         waste -= rnew.getArea();
00786                     }
00787                     else { // subtract the enlargement
00788                         waste -= rnew.getArea() - rup.getArea();
00789                     }
00790 
00791                     rup = rnew;
00792                 }
00793 
00794                 assert(waste >= 0);
00795 
00796                 if (this->level > 0)
00797                 {
00798                     // descend into child rectangles
00799                     const InnerNode *in = reinterpret_cast<const InnerNode*>(this);
00800 
00801                     for(unsigned int ci = 0; ci < in->childnum; ci++)
00802                     {
00803                         NodeHead *cn = tree.pageman.getPage(in->children[ci].page);
00804 
00805                         if (cn->level == 0)
00806                             waste += static_cast<LeafNode*>(cn)->calcWasteArea(tree);
00807                         else
00808                             waste += static_cast<InnerNode*>(cn)->calcWasteArea(tree);
00809                     }
00810                 }
00811     
00812                 return waste;
00813             }
00814 
00815             // *** Insert and Reinsert functions
00816 
00819             bool        insertChild(Tree &tree, pageid_t mypageid, const NodeData &newdata, std::stack<pageid_t>& path, char *overflowedLevel)
00820             {
00821                 if (this->childnum < pagesize) // still room for one more?
00822                 {
00823                     // fill in last child
00824                     this->children[this->childnum] = newdata;
00825                     this->childnum++;
00826 
00827                     // check if we need to adjust the rectangle path
00828                     if (not this->nodeMBR.containsRect(newdata.getMBR(tree)))
00829                     {
00830                         this->nodeMBR.combineRect(newdata.getMBR(tree));
00831             
00832                         // and propagate the changes upward
00833                         if (not path.empty())
00834                         {
00835                             pageid_t parentpage = path.top();
00836                             path.pop();
00837 
00838                             NodeHead *parentnode = tree.pageman.getPage(parentpage);
00839                             assert(parentnode->level != 0);
00840 
00841                             static_cast<InnerNode*>(parentnode)->adjustTree(tree, parentpage, *this, mypageid, path);
00842                         }
00843                         return true;
00844                     }
00845                     else
00846                         return false; // tree not adjusted
00847                 }
00848 #if defined(R_STAR_TREE)
00849                 else if (!path.empty() && overflowedLevel[this->level] == 0 && tree.reinsertnum > 0)
00850                 {
00851                     //std::cerr << "Reinsert on level " << level << "\n";
00852                     overflowedLevel[this->level] = 1;
00853 
00854                     reinsertData(tree, mypageid, newdata, path, overflowedLevel);
00855 
00856                     return true;
00857                 }
00858 #endif
00859                 else
00860                 {
00861                     // we have to split this node.
00862                     NodeType *nn;
00863                     pageid_t nn_page;
00864 
00865                     splitNode(tree, newdata, &nn, nn_page);
00866 
00867                     if (path.empty())
00868                     {
00869                         // if we just split the root, then we have to create a new root
00870                         // containing the two newly created nodes.
00871 
00872                         //std::cerr << "Split Root\n";
00873 
00874                         tree.rootpage = tree.pageman.new_innerpage();
00875                         InnerNode *root = static_cast<InnerNode*>( tree.pageman.getPage(tree.rootpage) );
00876 
00877                         root->initializeRoot();
00878 
00879                         tree.levels++;
00880                         root->level = this->level + 1;
00881                         root->childnum = 2;
00882 
00883                         assert(root->level == tree.levels);
00884 
00885                         root->children[0].rect = this->nodeMBR;
00886                         root->children[0].page = mypageid;
00887 
00888                         root->children[1].rect = nn->nodeMBR;
00889                         root->children[1].page = nn_page;
00890 
00891                         root->nodeMBR.combineRects(this->nodeMBR, nn->nodeMBR);
00892                     }
00893                     else
00894                     {
00895                         // else we have to insert nn into the parent page and propagate the
00896                         // changes to the two nodeMBR upward
00897 
00898                         //std::cerr << "Split\n";
00899 
00900                         pageid_t parentpage = path.top();
00901                         path.pop();
00902 
00903                         NodeHead *parentnode = tree.pageman.getPage(parentpage);
00904                         assert(parentnode->level != 0);
00905 
00906                         static_cast<InnerNode*>(parentnode)->adjustTreeSplit(tree, parentpage,
00907                                                                              *this, mypageid,
00908                                                                              *nn, nn_page, path, overflowedLevel);
00909                     }
00910 
00911                     return true;
00912                 }
00913             }
00914 
00916             void        adjustTree(Tree &tree, pageid_t mypageid, const NodeHead& adj, pageid_t adjpage, std::stack<pageid_t>& path)
00917             {
00918                 // find child number of the adj node.
00919                 unsigned int adjchild;
00920                 for(adjchild = 0; adjchild < this->childnum; adjchild++)
00921                 {
00922                     if (this->children[adjchild].page == adjpage) break;
00923                 }
00924 
00925                 assert(adjchild < this->childnum);
00926 
00927                 this->children[adjchild].rect = adj.nodeMBR;
00928 
00929                 // this node's MBR needs recalculation if the newly inserted child's
00930                 // rectangle is not contained (thus the MBR will grow)
00931 
00932                 // we dont need any pre-calculation because the combineRect() takes just as
00933                 // long as the containsRect().
00934                 this->nodeMBR.combineRect(adj.nodeMBR);
00935 
00936                 // and propagate the changes upward
00937                 if (not path.empty())
00938                 {
00939                     pageid_t parentpage = path.top();
00940                     path.pop();
00941 
00942                     NodeHead *parentnode = tree.pageman.getPage(parentpage);
00943                     assert(parentnode->level != 0);
00944 
00945                     static_cast<InnerNode*>(parentnode)->adjustTree(tree, parentpage, *this, mypageid, path);
00946                 }
00947             }
00948 
00951             void        adjustTreeSplit(Tree &tree, pageid_t mypageid, const NodeHead &adjN, pageid_t adjNpage, const NodeHead &adjNN, pageid_t adjNNpage, std::stack<pageid_t>& path, char *overflowedLevel)
00952             {
00953                 // find child number of the adjN node.
00954                 unsigned int adjchild;
00955                 for(adjchild = 0; adjchild < this->childnum; adjchild++)
00956                 {
00957                     if (this->children[adjchild].page == adjNpage) break;
00958                 }
00959 
00960                 assert(adjchild < this->childnum);
00961 
00962                 // the nodeMBR of N most always grows smaller during a split. we always
00963                 // recalculate this nodeMBR.
00964     
00965                 this->children[adjchild].rect = adjN.nodeMBR;
00966 
00967                 this->nodeMBR.setInfinite();
00968 
00969                 for(unsigned int ci = 0; ci < this->childnum; ci++)
00970                     this->nodeMBR.combineRect(this->children[ci].getMBR(tree));
00971 
00972                 // use the usual insert method to put the new node NN into this page.
00973                 InnerNodeData newdata(adjNN.nodeMBR, adjNNpage);
00974                 bool adjustedTree = insertChild(tree, mypageid, newdata, path, overflowedLevel);
00975 
00976                 // if insertChild hasnt adjusted the tree, then we need to propagate the
00977                 // changes upward
00978                 if (!adjustedTree and not path.empty())
00979                 {
00980                     pageid_t parentpage = path.top();
00981                     path.pop();
00982 
00983                     NodeHead *parentnode = tree.pageman.getPage(parentpage);
00984                     static_cast<InnerNode*>(parentnode)->adjustTreeReinsert(tree, parentpage, *this, mypageid, path);
00985                 }
00986             }
00987 
00990             void        adjustTreeReinsert(Tree &tree, pageid_t mypageid, const NodeHead &adj, pageid_t adjpage,std::stack<pageid_t>& path)
00991             {
00992                 // find child number of the adjchild node.
00993                 unsigned int adjci;
00994                 for(adjci = 0; adjci < this->childnum; adjci++)
00995                 {
00996                     if (this->children[adjci].page == adjpage) break;
00997                 }
00998 
00999                 assert(adjci < this->childnum);
01000 
01001                 // the nodeMBR of N most always grows smaller during a reinsert. we always
01002                 // recalculate this nodeMBR.
01003     
01004                 this->children[adjci].rect = adj.nodeMBR;
01005 
01006                 this->nodeMBR.setInfinite();
01007 
01008                 for(unsigned int ci = 0; ci < this->childnum; ci++)
01009                     this->nodeMBR.combineRect(this->children[ci].getMBR(tree));
01010 
01011                 // propagate the changes upward
01012                 if (not path.empty())
01013                 {
01014                     pageid_t parentpage = path.top();
01015                     path.pop();
01016 
01017                     NodeHead *parentnode = tree.pageman.getPage(parentpage);
01018                     static_cast<InnerNode*>(parentnode)->adjustTreeReinsert(tree, parentpage, *this, mypageid, path);
01019                 }
01020             }
01021 
01023             void        reinsertData(Tree &tree, pageid_t mypageid, const NodeData &newdata, std::stack<pageid_t>& path, char *overflowedLevel)
01024             {
01025                 assert(this->childnum == pagesize);
01026 
01027                 std::vector<ReinsertDist> distlist(this->childnum+1);
01028 
01029                 Point mycenter = this->nodeMBR.getCenter();
01030 
01031                 for(unsigned int ci = 0; ci < this->childnum; ci++)
01032                 {
01033                     distlist[ci].childid = ci;
01034 
01035                     distlist[ci].distance = mycenter.getDistanceSquare( this->children[ci].getMBR(tree).getCenter() );
01036                     assert(distlist[ci].distance >= 0);
01037                 }
01038 
01039                 distlist[this->childnum].childid = this->childnum;
01040                 distlist[this->childnum].distance = mycenter.getDistanceSquare( newdata.getMBR(tree).getCenter() );
01041                 assert(distlist[this->childnum].distance >= 0);
01042 
01043                 // sort by ascending order of distance
01044                 std::sort(distlist.begin(), distlist.end(), ReinsertDist::order_distance);
01045 
01046                 // the first (childnum+1)-reinsertnum entries are kept.
01047                 unsigned int keptnum = (this->childnum+1) - tree.reinsertnum;
01048 
01049                 // remove the following entries into a temporary space.
01050                 std::vector<NodeData> reinsertLater(tree.reinsertnum);
01051 
01052                 for(unsigned int i = 0; i < tree.reinsertnum; i++)
01053                 {
01054                     if (distlist[keptnum+i].childid < this->childnum)
01055                     {
01056                         reinsertLater[i] = this->children[ distlist[keptnum+i].childid ];
01057                     }
01058                     else
01059                     {
01060                         reinsertLater[i] = newdata;
01061                     }
01062                 }
01063 
01064                 // sort the first reinsertnum entries and rearrange the children
01065                 std::sort(distlist.begin(), distlist.begin() + keptnum, ReinsertDist::order_childid);
01066 
01067                 this->nodeMBR.setInfinite();
01068 
01069                 for(unsigned int ci = 0; ci < keptnum; ci++)
01070                 {
01071                     if (distlist[ci].childid == ci)
01072                     {
01073                         this->nodeMBR.combineRect(this->children[ci].getMBR(tree));
01074                         continue;
01075                     }
01076 
01077                     if (distlist[ci].childid < this->childnum)
01078                     {
01079                         this->children[ci] = this->children[ distlist[ci].childid ];
01080                     }
01081                     else
01082                     {
01083                         this->children[ci] = newdata;
01084                     }
01085 
01086                     this->nodeMBR.combineRect(this->children[ci].getMBR(tree));
01087                 }
01088 
01089                 this->childnum = keptnum;
01090 
01091                 // adjust the tree upward
01092                 assert(!path.empty());
01093                 {
01094                     pageid_t parentpage = path.top();
01095                     path.pop();
01096 
01097                     NodeHead *parentnode = tree.pageman.getPage(parentpage);
01098                     static_cast<InnerNode*>(parentnode)->adjustTreeReinsert(tree, parentpage, *this, mypageid, path);
01099                 }
01100 
01101                 // reinsert the removed children at maximum the same level
01102                 for(unsigned int ri = 0; ri < tree.reinsertnum; ri++)
01103                 {
01104                     tree.reinsertRect(reinsertLater[ri], this->level, overflowedLevel);
01105                 }
01106             }
01107 
01109             void        deleteChild(const Tree &tree, unsigned int ci)
01110             {
01111                 assert(ci < this->childnum);
01112 
01113                 // rearrage the children if needed
01114                 if (this->childnum > 0 && ci+1 != this->childnum)
01115                 {
01116                     this->children[ci] = this->children[this->childnum-1];
01117                 }
01118 
01119                 this->childnum--;
01120     
01121                 // recalculate the nodeMBR
01122                 recalcChildrenMBR(tree, this->nodeMBR);
01123             }
01124 
01125             // *** Functions for splitting a node
01126         
01129             void        splitNode(Tree &tree, const NodeData &newdata, NodeType** nndest, pageid_t &nn_page)
01130             {
01131                 // create two groups of children rectangles
01132                 std::vector<unsigned int> group1, group2;
01133 
01134 #if defined(R_TREE_LINEAR) || defined(R_TREE_QUADRATIC)
01135 
01136                 splitNodeMakeGroups(tree, newdata.getMBR(tree), group1, group2);
01137 
01138 #elif defined(R_STAR_TREE)
01139 
01140                 splitNodeMakeGroupsRStar(tree, newdata.getMBR(tree), group1, group2);
01141 
01142 #endif  
01143                 // create two new nodes on the same level and write the groups of children
01144                 // into them. the new node n is only temporary and will be copied to this.
01145     
01146                 nn_page = tree.pageman.newPage( sizeof(NodeType) );
01147     
01148                 NodeType *n = new NodeType();
01149                 NodeType *nn = static_cast<NodeType*>(tree.pageman.getPage(nn_page));
01150 
01151                 n->initializeSibling(this->level);
01152                 nn->initializeSibling(this->level);
01153 
01154                 for(unsigned int gi = 0; gi < group1.size(); gi++)
01155                 {
01156                     unsigned int ci = group1[gi];
01157 
01158                     if (ci < this->childnum)
01159                     {
01160                         n->children[gi] = this->children[ci];
01161                     }
01162                     else
01163                     {
01164                         // insert new rectangle into this node
01165                         n->children[gi] = newdata;
01166                     }
01167                     n->nodeMBR.combineRect(n->children[gi].getMBR(tree));
01168                 }
01169                 n->childnum = static_cast<unsigned short>(group1.size());
01170     
01171                 for(unsigned int gi = 0; gi < group2.size(); gi++)
01172                 {
01173                     unsigned int ci = group2[gi];
01174 
01175                     if (ci < this->childnum)
01176                     {
01177                         nn->children[gi] = this->children[ci];
01178                     }
01179                     else
01180                     {
01181                         // insert new rectangle into this node
01182                         nn->children[gi] = newdata;
01183                     }
01184                     nn->nodeMBR.combineRect(nn->children[gi].getMBR(tree));
01185                 }
01186                 nn->childnum = static_cast<unsigned short>(group2.size());
01187 
01188                 // copy node n into this one
01189                 *this = *n;
01190                 delete n;
01191 
01192                 *nndest = nn;
01193             }
01194 
01197             void                splitNodeMakeGroups(const Tree &tree, const Rect &newrect, std::vector<unsigned int> &group1, std::vector<unsigned int> &group2) const
01198             {
01199                 unsigned int seed1, seed2;
01200 
01201 #if defined(R_TREE_LINEAR)
01202 
01203                 pickSeedsLinear(tree, newrect, seed1, seed2);
01204 
01205 #elif defined(R_TREE_QUADRATIC)
01206 
01207                 pickSeedsQuadratic(tree, newrect, seed1, seed2);
01208 
01209 #else
01210                 assert(0);
01211 #endif
01212 
01213                 assert(seed1 <= this->childnum);
01214                 assert(seed2 <= this->childnum);
01215                 assert(seed1 != seed2);
01216 
01217                 group1.push_back(seed1);
01218                 group2.push_back(seed2);
01219 
01220                 // char mask used to mark already assigned children
01221                 char cmask[pagesize+1];
01222                 memset(cmask, 0, pagesize+1);
01223 
01224                 cmask[seed1] = 1;
01225                 cmask[seed2] = 1;
01226 
01227                 // min bounding rectangles of the two groups
01228                 Rect mbr1 = (seed1 < this->childnum) ? children[seed1].getMBR(tree) : newrect;
01229                 Rect mbr2 = (seed2 < this->childnum) ? children[seed2].getMBR(tree) : newrect;
01230 
01231                 unsigned int num_ungrouped = (this->childnum + 1) - 2;
01232 
01233                 unsigned int min_pageload = static_cast<unsigned int>(pagesize * 0.5);
01234     
01235                 while(num_ungrouped > 0)
01236                 {
01237                     // check if either group has so few entries that the rest must be
01238                     // assigned to it
01239                     if (group1.size() + num_ungrouped <= min_pageload)
01240                     {
01241                         // assign rest of children to group1.
01242                         for(unsigned int ci = 0; ci < this->childnum; ci++)
01243                         {
01244                             if (cmask[ci]) continue;
01245 
01246                             group1.push_back(ci);
01247                             cmask[ci] = 1;
01248                             num_ungrouped--;
01249                         }
01250                         if (!cmask[this->childnum])
01251                         {
01252                             group1.push_back(this->childnum);
01253                             cmask[this->childnum] = 1;
01254                             num_ungrouped--;
01255                         }
01256                         break;
01257                     }
01258                     else if (group2.size() + num_ungrouped <= min_pageload)
01259                     {
01260                         // assign rest of children to group2.
01261                         for(unsigned int ci = 0; ci < this->childnum; ci++)
01262                         {
01263                             if (cmask[ci]) continue;
01264 
01265                             group2.push_back(ci);
01266                             cmask[ci] = 1;
01267                             num_ungrouped--;
01268                         }
01269                         if (!cmask[this->childnum])
01270                         {
01271                             group2.push_back(this->childnum);
01272                             cmask[this->childnum] = 1;
01273                             num_ungrouped--;
01274                         }
01275                         break;
01276                     }
01277                     else
01278                     {
01279                         // quadratic pickNext Algorithm: Select one remaining entry for
01280                         // classification in a group.
01281             
01282                         // for all ungrouped rectangles, calculate the increase of the mbr
01283                         // if it was put into either group. select that rectangle which has
01284                         // the greatest difference.
01285 
01286                         unsigned int childsel = std::numeric_limits<unsigned int>::max();
01287                         AreaType childmaxdiff = std::numeric_limits<AreaType>::min();
01288 
01289                         AreaType childsel_inc1 = std::numeric_limits<AreaType>::min(),
01290                             childsel_inc2 = std::numeric_limits<AreaType>::min();
01291             
01292                         Rect tr_group1, tr_group2;
01293             
01294                         AreaType area_mbr1 = mbr1.getArea();
01295                         AreaType area_mbr2 = mbr2.getArea();
01296 
01297                         for(unsigned int ci = 0; ci < this->childnum; ci++)
01298                         {
01299                             if (cmask[ci]) continue;
01300 
01301                             tr_group1.combineRects(mbr1, children[ci].getMBR(tree));
01302                             tr_group2.combineRects(mbr2, children[ci].getMBR(tree));
01303 
01304                             assert(tr_group1.getArea() >= area_mbr1);
01305                             assert(tr_group2.getArea() >= area_mbr2);
01306 
01307                             AreaType increase1 = tr_group1.getArea() - area_mbr1;
01308                             AreaType increase2 = tr_group2.getArea() - area_mbr2;
01309                 
01310                             AreaType diff = std::max(increase1 - increase2,
01311                                                      increase2 - increase1);
01312                 
01313                             if (childmaxdiff < diff)
01314                             {
01315                                 childmaxdiff = diff;
01316                                 childsel = ci;
01317                                 childsel_inc1 = increase1;
01318                                 childsel_inc2 = increase2;
01319                             }
01320                         }
01321                         { // and last but not least the new rectangle
01322 
01323                             if (!cmask[this->childnum])
01324                             {
01325                                 tr_group1.combineRects(mbr1, newrect);
01326                                 tr_group2.combineRects(mbr2, newrect);
01327 
01328                                 AreaType increase1 = tr_group1.getArea() - area_mbr1;
01329                                 AreaType increase2 = tr_group2.getArea() - area_mbr2;
01330                 
01331                                 AreaType diff = std::max(increase1 - increase2,
01332                                                          increase2 - increase1);
01333                 
01334                                 if (childmaxdiff < diff)
01335                                 {
01336                                     childmaxdiff = diff;
01337                                     childsel = this->childnum;
01338                                     childsel_inc1 = increase1;
01339                                     childsel_inc2 = increase2;
01340                                 }
01341                             }
01342                         }
01343             
01344                         assert(childsel <= this->childnum);
01345 
01346                         // childsel is the selected child rectangle. figure out the right group
01347 
01348                         int group = 0;
01349                         if (childsel_inc1 < childsel_inc2)
01350                         {
01351                             group = 1;
01352                         }
01353                         else if (childsel_inc2 < childsel_inc1)
01354                         {
01355                             group = 2;
01356                         }
01357                         // break ties by adding the entry to the group with smaller area
01358                         else if (area_mbr1 < area_mbr2)
01359                         {
01360                             group = 1;
01361                         }
01362                         else if (area_mbr2 < area_mbr1)
01363                         {
01364                             group = 2;
01365                         }
01366                         // break further ties by putting it into the one with fewer rects
01367                         else if (group1.size() < group2.size())
01368                         {
01369                             group = 1;
01370                         }
01371                         else if (group2.size() < group1.size())
01372                         {
01373                             group = 2;
01374                         }
01375                         // and last choose any
01376                         else
01377                         {
01378                             group = 1 + (childsel % 2);
01379                         }
01380 
01381                         // put the child number into the right group and enlarge the group MBR.
01382                         if (group == 1)
01383                         {
01384                             group1.push_back(childsel);
01385                 
01386                             if (childsel < this->childnum)
01387                                 mbr1.combineRect(children[childsel].getMBR(tree));
01388                             else
01389                                 mbr1.combineRect(newrect);
01390                         }
01391                         else if (group == 2)
01392                         {
01393                             group2.push_back(childsel);
01394                 
01395                             if (childsel < this->childnum)
01396                                 mbr2.combineRect(children[childsel].getMBR(tree));
01397                             else
01398                                 mbr2.combineRect(newrect);
01399                         }
01400                         else {
01401                             assert(0);
01402                         }
01403 
01404                         cmask[childsel] = 1;
01405                         num_ungrouped--;
01406                     }
01407                 }
01408 
01409                 assert(group1.size() + group2.size() == static_cast<unsigned int>(this->childnum) + 1);
01410                 assert(group1.size() >= pageminfill);
01411                 assert(group2.size() >= pageminfill);
01412 
01413 #if 0
01414                 std::cerr << "selected groups: " << std::endl;
01415                 std::cerr << "g1:";
01416                 for(unsigned int i = 0; i < group1.size(); i++)
01417                     std::cerr << " " << group1[i];
01418                 std::cerr << std::endl;
01419                 std::cerr << "g2:";
01420                 for(unsigned int i = 0; i < group2.size(); i++)
01421                     std::cerr << " " << group2[i];
01422                 std::cerr << std::endl;
01423 #endif
01424             }
01425    
01427             void                pickSeedsQuadratic(const Tree &tree, const Rect &newrect, unsigned int &seed1, unsigned int &seed2) const
01428             {
01429                 Rect rt;
01430                 AreaType max_inefficiency = std::numeric_limits<AreaType>::min();
01431 
01432                 // for each pair of entries E1 and E2
01433                 for(unsigned int i = 0; i < this->childnum; i++)
01434                 {
01435                     AreaType areaE1 = children[i].getMBR(tree).getArea();
01436 
01437                     for(unsigned int j = i+1; j < this->childnum; j++)
01438                     {
01439                         rt.combineRects(children[i].getMBR(tree), children[j].getMBR(tree));
01440 
01441                         AreaType d = rt.getArea() - areaE1 - children[j].getMBR(tree).getArea();
01442 
01443                         if (d > max_inefficiency)
01444                         {
01445                             max_inefficiency = d;
01446                             seed1 = i;
01447                             seed2 = j;
01448                         }
01449                     }
01450 
01451                     // compare with the new rectangle
01452                     {
01453                         rt.combineRects(children[i].getMBR(tree), newrect);
01454 
01455                         AreaType d = rt.getArea() - areaE1 - newrect.getArea();
01456 
01457                         if (d > max_inefficiency)
01458                         {
01459                             max_inefficiency = d;
01460                             seed1 = i;
01461                             seed2 = this->childnum;
01462                         }
01463                     }
01464                 }
01465             }
01466     
01468             void                pickSeedsLinear(const Tree &tree, const Rect &newrect, unsigned int &seed1, unsigned int &seed2) const
01469             {
01470                 // Find extreme rectangles along all dimensions
01471 
01472                 // x-Axis
01473 
01474                 CoordType max_x1, min_x2;
01475                 unsigned int max_x1_ci, min_x2_ci;
01476 
01477                 CoordType min_x1, max_x2;
01478 
01479                 double normalized_x;
01480 
01481                 {
01482                     // initialize max and min with the new rectangle
01483                     min_x1 = max_x1 = newrect.x1;
01484                     min_x2 = max_x2 = newrect.x2;
01485                     max_x1_ci = this->childnum;
01486                     min_x2_ci = this->childnum;
01487 
01488                     for(unsigned int ci = 0; ci < this->childnum; ci++)
01489                     {
01490                         if (max_x1 < children[ci].getMBR(tree).x1)
01491                         {
01492                             max_x1 = children[ci].getMBR(tree).x1;
01493                             max_x1_ci = ci;
01494                         }
01495                         min_x1 = std::min(min_x1, children[ci].getMBR(tree).x1);
01496 
01497                         if (min_x2 > children[ci].getMBR(tree).x2)
01498                         {
01499                             min_x2 = children[ci].getMBR(tree).x2;
01500                             min_x2_ci = ci;
01501                         }
01502                         max_x2 = std::min(max_x2, children[ci].getMBR(tree).x2);
01503                     }
01504 
01505                     CoordType separation = max_x1 - min_x2;
01506 
01507                     CoordType width = max_x2 - min_x1;
01508                     if (width <= 0) width = 1;
01509 
01510                     normalized_x = static_cast<double>(separation) / static_cast<double>(width);
01511                 }
01512 
01513                 // y-Axis
01514 
01515                 CoordType max_y1, min_y2;
01516                 unsigned int max_y1_ci, min_y2_ci;
01517 
01518                 CoordType min_y1, max_y2;
01519 
01520                 double normalized_y;
01521 
01522                 {
01523                     // initialize max and min with the new rectangle
01524                     min_y1 = max_y1 = newrect.y1;
01525                     min_y2 = max_y2 = newrect.y2;
01526                     max_y1_ci = this->childnum;
01527                     min_y2_ci = this->childnum;
01528 
01529                     for(unsigned int ci = 0; ci < this->childnum; ci++)
01530                     {
01531                         if (max_y1 < children[ci].getMBR(tree).y1)
01532                         {
01533                             max_y1 = children[ci].getMBR(tree).y1;
01534                             max_y1_ci = ci;
01535                         }
01536                         min_y1 = std::min(min_y1, children[ci].getMBR(tree).y1);
01537 
01538                         if (min_y2 > children[ci].getMBR(tree).y2)
01539                         {
01540                             min_y2 = children[ci].getMBR(tree).y2;
01541                             min_y2_ci = ci;
01542                         }
01543                         max_y2 = std::min(max_y2, children[ci].getMBR(tree).y2);
01544                     }
01545 
01546                     CoordType separation = max_y1 - min_y2;
01547 
01548                     CoordType width = max_y2 - min_y1;
01549                     if (width <= 0) width = 1;
01550 
01551                     normalized_y = static_cast<double>(separation) / static_cast<double>(width);
01552                 }
01553 
01554                 if (normalized_y > normalized_x)
01555                 {
01556                     // choose the extreme pair of the y-Axis
01557                     max_x1_ci = max_y1_ci;
01558                     min_x2_ci = min_y2_ci;
01559                 }
01560                 else {
01561                     // choose the extreme pair of the x-Axis
01562                 }
01563 
01564                 // break collision
01565                 if (max_x1_ci == min_x2_ci)
01566                 {
01567                     if (min_x2_ci == 0) min_x2_ci++;
01568                     else min_x2_ci--;
01569                 }
01570 
01571                 seed1 = max_x1_ci;
01572                 seed2 = min_x2_ci;
01573             }
01574     
01576             struct SplitDist
01577             {
01578                 unsigned int    childid;
01579                 Rect            mbr;
01580 
01581                 static inline bool cmp_axis1_lower(const SplitDist &a, const SplitDist &b)
01582                 {
01583                     return a.mbr.x1 < b.mbr.x1;
01584                 }
01585                 static inline bool cmp_axis1_upper(const SplitDist &a, const SplitDist &b)
01586                 {
01587                     return a.mbr.x2 < b.mbr.x2;
01588                 }
01589                 static inline bool cmp_axis2_lower(const SplitDist &a, const SplitDist &b)
01590                 {
01591                     return a.mbr.y1 < b.mbr.y1;
01592                 }
01593                 static inline bool cmp_axis2_upper(const SplitDist &a, const SplitDist &b)
01594                 {
01595                     return a.mbr.y2 < b.mbr.y2;
01596                 }
01597 
01598                 typedef bool (*cmpfunc_t)(const SplitDist &a, const SplitDist &b);
01599 
01600                 static inline cmpfunc_t get_cmpfunc(unsigned int axis, unsigned int lower_upper)
01601                 {
01602                     if (axis == 0) {
01603                         if (lower_upper == 0) return cmp_axis1_lower;
01604                         if (lower_upper == 1) return cmp_axis1_upper;
01605                     }
01606                     if (axis == 1) {
01607                         if (lower_upper == 0) return cmp_axis2_lower;
01608                         if (lower_upper == 1) return cmp_axis2_upper;
01609                     }
01610                     assert(0);
01611                     return cmp_axis1_lower;
01612                 }
01613             };
01614 
01617             void                splitNodeMakeGroupsRStar(const Tree &tree, const Rect &newrect, std::vector<unsigned int> &group1, std::vector<unsigned int> &group2) const
01618             {
01619                 assert(this->childnum == pagesize);
01620 
01621                 std::vector<SplitDist> distlower(this->childnum+1);
01622                 std::vector<SplitDist> distupper(this->childnum+1);
01623 
01624                 for(unsigned int ci = 0; ci < this->childnum; ci++)
01625                 {
01626                     distlower[ci].childid = ci;
01627                     distlower[ci].mbr = children[ci].getMBR(tree);
01628 
01629                     distupper[ci].childid = ci;
01630                     distupper[ci].mbr = children[ci].getMBR(tree);
01631                 }
01632 
01633                 distlower[this->childnum].childid = this->childnum;
01634                 distlower[this->childnum].mbr = newrect;
01635 
01636                 distupper[this->childnum].childid = this->childnum;
01637                 distupper[this->childnum].mbr = newrect;
01638 
01639                 // Algorithm chooseSplitAxis
01640 
01641                 AreaType minMargin = std::numeric_limits<AreaType>::max();
01642                 int splitAxis = -1;
01643                 int splitIndex = -1;
01644 
01645                 unsigned int distnum = this->childnum - 2*pageminfill + 2;
01646     
01647                 {
01648                     // sort the two arrays by x
01649                     std::sort(distlower.begin(), distlower.end(), SplitDist::cmp_axis1_lower);
01650                     std::sort(distupper.begin(), distupper.end(), SplitDist::cmp_axis1_upper);
01651 
01652                     Rect bb_lower_group1, bb_upper_group1;
01653                     Rect bb_lower_group2, bb_upper_group2;
01654 
01655                     AreaType margin_lower = 0;
01656                     AreaType margin_upper = 0;
01657 
01658                     // for each of the M-2m+2 distributions, calculate the margin-values
01659                     for(unsigned int di = 0; di < distnum; di++)
01660                     {
01661                         bb_lower_group1.setInfinite();
01662                         bb_upper_group1.setInfinite();
01663 
01664                         unsigned int listsplit = pageminfill + di;
01665 
01666                         for(unsigned int i = 0; i < listsplit; i++)
01667                         {
01668                             bb_lower_group1.combineRect(distlower[i].mbr);
01669                             bb_upper_group1.combineRect(distupper[i].mbr);
01670                         }
01671 
01672                         bb_lower_group2.setInfinite();
01673                         bb_upper_group2.setInfinite();
01674 
01675                         for(unsigned int i = listsplit; i < static_cast<unsigned int>(this->childnum+1); i++)
01676                         {
01677                             bb_lower_group2.combineRect(distlower[i].mbr);
01678                             bb_upper_group2.combineRect(distupper[i].mbr);
01679                         }
01680 
01681                         // compute S, the sum of all margin-values
01682                         margin_lower += bb_lower_group1.getMargin() + bb_lower_group2.getMargin();
01683                         margin_upper += bb_upper_group1.getMargin() + bb_upper_group2.getMargin();
01684                     }
01685         
01686                     AreaType margin = std::min(margin_lower, margin_upper);
01687 
01688                     // find the minimum margin value
01689                     if (minMargin > margin)
01690                     {
01691                         minMargin = margin;
01692                         splitAxis = 0;
01693                         splitIndex = (margin_lower < margin_upper) ? 0 : 1;
01694                     }
01695                 }
01696                 { // same as above but this time sorted by y
01697                     // sort the two arrays by y
01698                     std::sort(distlower.begin(), distlower.end(), SplitDist::cmp_axis2_lower);
01699                     std::sort(distupper.begin(), distupper.end(), SplitDist::cmp_axis2_upper);
01700 
01701                     Rect bb_lower_group1, bb_upper_group1;
01702                     Rect bb_lower_group2, bb_upper_group2;
01703 
01704                     AreaType margin_lower = 0;
01705                     AreaType margin_upper = 0;
01706 
01707                     // for each of the M-2m+2 distributions, calculate the margin-values
01708                     for(unsigned int di = 0; di < distnum; di++)
01709                     {
01710                         bb_lower_group1.setInfinite();
01711                         bb_upper_group1.setInfinite();
01712 
01713                         unsigned int listsplit = pageminfill + di;
01714 
01715                         for(unsigned int i = 0; i < listsplit; i++)
01716                         {
01717                             bb_lower_group1.combineRect(distlower[i].mbr);
01718                             bb_upper_group1.combineRect(distupper[i].mbr);
01719                         }
01720 
01721                         bb_lower_group2.setInfinite();
01722                         bb_upper_group2.setInfinite();
01723 
01724                         for(unsigned int i = listsplit; i < static_cast<unsigned int>(this->childnum+1); i++)
01725                         {
01726                             bb_lower_group2.combineRect(distlower[i].mbr);
01727                             bb_upper_group2.combineRect(distupper[i].mbr);
01728                         }
01729 
01730                         // compute S, the sum of all margin-values
01731                         margin_lower += bb_lower_group1.getMargin() + bb_lower_group2.getMargin();
01732                         margin_upper += bb_upper_group1.getMargin() + bb_upper_group2.getMargin();
01733                     }
01734         
01735                     AreaType margin = std::min(margin_lower, margin_upper);
01736                     assert(margin >= 0);
01737 
01738                     // find the minimum margin value
01739                     if (minMargin > margin)
01740                     {
01741                         minMargin = margin;
01742                         splitAxis = 1;
01743                         splitIndex = (margin_lower < margin_upper) ? 0 : 1;
01744                     }
01745                 }
01746 
01747                 // resort the distlist by the selected order
01748                 std::sort(distlower.begin(), distlower.end(), SplitDist::get_cmpfunc(splitAxis, splitIndex));
01749 
01750                 // Algorithm chooseSplitIndex
01751 
01752                 unsigned int min_distrib = distnum;
01753                 AreaType min_overlap = std::numeric_limits<AreaType>::max();
01754                 AreaType min_area = std::numeric_limits<AreaType>::max();
01755                 {
01756                     Rect bb_group1, bb_group2;
01757 
01758                     // for each of the M-2m+2 distributions, calculate the minimum overlap
01759                     for(unsigned int di = 0; di < distnum; di++)
01760                     {
01761                         bb_group1.setInfinite();
01762 
01763                         unsigned int listsplit = pageminfill + di;
01764 
01765                         for(unsigned int i = 0; i < listsplit; i++)
01766                         {
01767                             bb_group1.combineRect(distlower[i].mbr);
01768                         }
01769 
01770                         bb_group2.setInfinite();
01771 
01772                         for(unsigned int i = listsplit; i < static_cast<unsigned int>(this->childnum+1); i++)
01773                         {
01774                             bb_group2.combineRect(distlower[i].mbr);
01775                         }
01776 
01777                         AreaType overlap = bb_group1.getIntersectingArea(bb_group2);
01778                         assert(overlap >= 0);
01779 
01780                         if (min_overlap > overlap)
01781                         {
01782                             min_distrib = di;
01783                             min_overlap = overlap;
01784                             min_area = bb_group1.getArea() + bb_group2.getArea();
01785                         }
01786                         // break ties by choosing the distribution with minimum area-value
01787                         else if (min_overlap == overlap)
01788                         {
01789                             if (bb_group1.getArea() + bb_group2.getArea() < min_area)
01790                             {
01791                                 min_distrib = di;
01792                                 min_overlap = overlap;
01793                                 min_area = bb_group1.getArea() + bb_group2.getArea();
01794                             }
01795                         }
01796                     }
01797                     assert(min_distrib < distnum);
01798                 }
01799 
01800                 // put the selected distribution into the right groups
01801                 {
01802                     unsigned int listsplit = pageminfill + min_distrib;
01803 
01804                     for(unsigned int i = 0; i < listsplit; i++)
01805                     {
01806                         group1.push_back(distlower[i].childid);
01807                     }
01808 
01809                     for(unsigned int i = listsplit; i < static_cast<unsigned int>(this->childnum+1); i++)
01810                     {
01811                         group2.push_back(distlower[i].childid);
01812                     }
01813                 }
01814 
01815                 assert(group1.size() + group2.size() == static_cast<unsigned int>(this->childnum) + 1);
01816                 assert(group1.size() >= pageminfill);
01817                 assert(group2.size() >= pageminfill);
01818             }
01819 
01821             void                condenseTree(Tree &tree, pageid_t mypageid, std::stack<pageid_t>& toReinsert, std::queue<pageid_t>& path)
01822             {
01823                 if (path.empty())
01824                 {
01825                     // condenseTree the root if it is not a leaf and has just one child
01826                     if (this->level != 0 && this->childnum == 1)
01827                     {
01828                         InnerNode *in = reinterpret_cast<InnerNode*>(this);
01829 
01830                         tree.rootpage = in->children[0].page;
01831 
01832                         tree.levels--;
01833 
01834                         tree.pageman.deletePage(mypageid);
01835                     }
01836                 }
01837                 else
01838                 {
01839                     // find the InnerNode containing a child pointing to this node
01840                     pageid_t parentpage = path.front();
01841                     path.pop();
01842 
01843                     InnerNode *parentnode = static_cast<InnerNode*>(tree.pageman.getPage(parentpage));
01844                     assert(parentnode->level != 0);
01845 
01846                     // find the child position of this node
01847                     unsigned int ci;
01848                     for(ci = 0; ci < parentnode->childnum; ci++)
01849                     {
01850                         if (parentnode->children[ci].page == mypageid) break;
01851                     }
01852 
01853                     assert(ci < parentnode->childnum);
01854 
01855                     if (this->childnum < pageminfill)
01856                     {
01857                         // this node will be deleted and entries moved to other nodes on the same level
01858                         parentnode->deleteChild(tree, ci);
01859 
01860                         toReinsert.push(mypageid);
01861                     }
01862                     else
01863                     {
01864                         // no need to delete this node, adapt the nodeMBR of our parent
01865                         parentnode->children[ci].rect = this->nodeMBR;
01866 
01867                         parentnode->recalcChildrenMBR(tree, parentnode->nodeMBR);
01868                     }
01869 
01870                     // propagate upward
01871                     parentnode->condenseTree(tree, parentpage, toReinsert, path);
01872                 }
01873             }
01874         };
01875 
01877         struct InnerNodeData
01878         {
01879         public:
01881             Rect        rect;
01882 
01884             pageid_t    page;
01885 
01887             inline InnerNodeData()
01888             { }
01889 
01891             inline InnerNodeData(const Rect &r, pageid_t p)
01892                 : rect(r), page(p)
01893             { }
01894 
01896             inline const class Rect getMBR(const Tree &) const
01897             { return rect; }
01898         };
01899 
01901         class InnerNode : public Node<InnerNodeData>
01902         {
01903         public:
01904             // nothing further than Node's functions
01905         };
01906 
01908         class LeafNodeData : public DataType
01909         {
01910         public:
01911             LeafNodeData() : DataType()
01912             { }
01913 
01915             LeafNodeData(const DataType &init) : _DataType(init)
01916             { }
01917 
01919             inline const class Rect getMBR(const Tree &tree) const
01920             { return tree.DTCallback->getMBR(*static_cast<const DataType*>(this)); }
01921         };
01922 
01924         class LeafNode : public Node<LeafNodeData>
01925         {
01926         public:
01928             void        deleteDataLeaf(Tree &tree, pageid_t mypageid, const LeafNodeData &rmdata, std::queue<pageid_t>& path)
01929             {
01930                 assert(this->level == 0);
01931 
01932                 // find the entry that should be deleted
01933     
01934                 unsigned int ci;
01935                 for(ci = 0; ci < this->childnum; ci++)
01936                 {
01937                     if (this->children[ci] == rmdata) break;
01938                 }
01939 
01940                 assert(ci < this->childnum);
01941 
01942                 // rearrage the children if needed
01943                 if (this->childnum > 0 && ci+1 != this->childnum)
01944                 {
01945                     this->children[ci] = this->children[this->childnum-1];
01946                 }
01947 
01948                 this->childnum--;
01949     
01950                 // recalculate the nodeMBR
01951                 recalcChildrenMBR(tree, this->nodeMBR);
01952 
01953                 // call condenseTree to propagte changes
01954 
01955                 std::stack<pageid_t> toReinsert;
01956                 condenseTree(tree, mypageid, toReinsert, path);
01957 
01958                 // reinsert all child of the nodes which are going to be deleted
01959                 while(!toReinsert.empty())
01960                 {
01961                     pageid_t delpage = toReinsert.top();
01962                     toReinsert.pop();
01963 
01964                     NodeHead *delnode = tree.pageman.getPage(delpage);
01965 
01966                     if (delnode->level == 0)
01967                     {
01968                         LeafNode *ln = static_cast<LeafNode*>(delnode);
01969 
01970                         for(unsigned int ci = 0; ci < ln->childnum; ci++)
01971                         {
01972                             char *overflowedLevel = static_cast<char*>(alloca(tree.levels+1));
01973                             memset(overflowedLevel, 0, tree.levels+1);
01974 
01975                             tree.reinsertRect(ln->children[ci], 0, overflowedLevel);
01976                         }
01977                     }
01978                     else
01979                     {
01980                         InnerNode *in = static_cast<InnerNode*>(delnode);
01981 
01982                         for(unsigned int ci = 0; ci < in->childnum; ci++)
01983                         {
01984                             char *overflowedLevel = static_cast<char*>(alloca(tree.levels+1));
01985                             memset(overflowedLevel, 0, tree.levels+1);
01986 
01987                             tree.reinsertRect(in->children[ci], in->level, overflowedLevel);
01988                         }
01989                     }
01990 
01991                     tree.pageman.deletePage(delpage);
01992                 }
01993             }
01994         };
01995 
01996         // *** Methods used to reinsert data and inner pointers into the tree
01997 
01999         template <typename NodeData>
02000         void    reinsertRect(NodeData &newdata, unsigned int maxlevel, char *overflowedLevel)
02001         {
02002             NodeHead *root = pageman.getPage(rootpage);
02003 
02004             // choose the node in which to insert the new rectangle
02005             std::stack<pageid_t> path;
02006 
02007             path.push(rootpage);
02008             class NodeHead *node;
02009             if (root->level == 0)
02010                 node = static_cast<LeafNode*>(root)->chooseSubtree(*this, newdata.getMBR(*this), maxlevel, path);
02011             else
02012                 node = static_cast<InnerNode*>(root)->chooseSubtree(*this, newdata.getMBR(*this), maxlevel, path);
02013 
02014             assert(node);
02015             assert(node->level == maxlevel);
02016 
02017             pageid_t page = path.top(); // the last entry is the node.
02018             path.pop();
02019             static_cast<Node<NodeData>*>(node)->insertChild(*this, page, newdata, path, overflowedLevel);
02020         }
02021 
02023         class PageManager
02024         {
02025         public:
02026             typedef std::vector<class InnerNode*> innerpages_t;
02027             std::vector<class InnerNode*> innerpages;
02028 
02029             typedef std::vector<class LeafNode*> leafpages_t;
02030             std::vector<class LeafNode*> leafpages;
02031 
02032             PageManager()
02033             { }
02034 
02035             PageManager(const PageManager &c)
02036             {
02037                 for(unsigned int i = 0; i < c.innerpages.size(); i++)
02038                     innerpages.push_back( new InnerNode(*c.innerpages[i]) );
02039 
02040                 for(unsigned int i = 0; i < c.leafpages.size(); i++)
02041                     leafpages.push_back( new LeafNode(*c.leafpages[i]) );
02042             }
02043 
02044             PageManager& operator=(const PageManager &c)
02045             {
02046                 clear();
02047 
02048                 for(unsigned int i = 0; i < c.innerpages.size(); i++)
02049                     innerpages.push_back( new InnerNode(*c.innerpages[i]) );
02050 
02051                 for(unsigned int i = 0; i < c.leafpages.size(); i++)
02052                     leafpages.push_back( new LeafNode(*c.leafpages[i]) );
02053 
02054                 return *this;
02055             }
02056         
02057             ~PageManager()
02058             {
02059                 for(unsigned int pi = 0; pi < innerpages.size(); pi++)
02060                     delete innerpages[pi];
02061 
02062                 for(unsigned int pi = 0; pi < leafpages.size(); pi++)
02063                     delete leafpages[pi];
02064             }
02065 
02066             static const pageid_t leafmask = 0x80000000;
02067 
02068             class NodeHead*     getPage(pageid_t pi) const
02069             {
02070                 if (pi & leafmask)
02071                 {
02072                     assert((pi & ~leafmask) < leafpages.size());
02073                     assert(leafpages[(pi & ~leafmask)]);
02074                     return leafpages[(pi & ~leafmask)];
02075                 }
02076                 else
02077                 {
02078                     assert(pi < innerpages.size());
02079                     assert(innerpages[pi]);
02080                     return innerpages[pi];
02081                 }
02082             }
02083 
02084             pageid_t    new_innerpage()
02085             {
02086                 for(pageid_t pi = 0; pi < innerpages.size(); pi++)
02087                 {
02088                     if (innerpages[pi] == static_cast<InnerNode*>(NULL))
02089                     {
02090                         innerpages[pi] = new InnerNode;
02091                         return pi;
02092                     }
02093                 }
02094 
02095                 innerpages.push_back(new InnerNode);
02096                 return static_cast<pageid_t>(innerpages.size()-1);
02097             }
02098 
02100             pageid_t    new_leafpage()
02101             {
02102                 for(pageid_t pi = 0; pi < leafpages.size(); pi++)
02103                 {
02104                     if (leafpages[pi] == static_cast<LeafNode*>(NULL))
02105                     {
02106                         leafpages[pi] = new LeafNode;
02107                         return pi | leafmask;
02108                     }
02109                 }
02110 
02111                 leafpages.push_back(new LeafNode);
02112                 return static_cast<pageid_t>((leafpages.size()-1) | leafmask);
02113             }
02114 
02117             pageid_t newPage(unsigned int nodesize)
02118             {
02119                 assert( sizeof(InnerNode) != sizeof(LeafNode) );
02120 
02121                 if (nodesize == sizeof(InnerNode))
02122                     return new_innerpage();
02123                 else if (nodesize == sizeof(LeafNode))
02124                     return new_leafpage();
02125                 else {
02126                     assert(0);
02127                     return new_innerpage();
02128                 }
02129             }
02130 
02131             void deletePage(pageid_t pi)
02132             {
02133                 if (pi & leafmask)
02134                 {
02135                     assert((pi & ~leafmask) < leafpages.size());
02136                     assert(leafpages[pi & ~leafmask]);
02137                     delete leafpages[pi & ~leafmask];
02138                     leafpages[pi & ~leafmask] = NULL;
02139                 }
02140                 else
02141                 {
02142                     assert(pi < innerpages.size());
02143                     assert(innerpages[pi]);
02144                     delete innerpages[pi];
02145                     innerpages[pi] = NULL;
02146                 }
02147             }
02148 
02149             void clear()
02150             {
02151                 for(unsigned int pi = 0; pi < innerpages.size(); pi++)
02152                     delete innerpages[pi];
02153 
02154                 for(unsigned int pi = 0; pi < leafpages.size(); pi++)
02155                     delete leafpages[pi];
02156 
02157                 innerpages.clear();
02158                 leafpages.clear();
02159             }
02160         };
02161 
02162     private:
02163         // *** Data of the R-Tree
02164 
02165         pageid_t        rootpage;
02166 
02167         PageManager     pageman;
02168 
02169         unsigned int    levels;
02170 
02171         unsigned int    entries;
02172 
02173         mutable DataTypeCallback        *DTCallback;
02174 
02175     public:
02176         // *** Operations on the R-Tree
02177 
02178         explicit Tree(DataTypeCallback *cb)
02179         {
02180             rootpage = pageman.new_leafpage();
02181 
02182             NodeHead *root = pageman.getPage(rootpage);
02183             root->initializeRoot();
02184 
02185             levels = 0;
02186             entries = 0;
02187             DTCallback = cb;
02188 
02189             reinsertnum = pagesize - pageminfill;
02190             assert(pageminfill + reinsertnum <= pagesize);
02191         }
02192 
02194         Tree(const Tree &o)
02195         {
02196             rootpage = o.rootpage;
02197             pageman = o.pageman;
02198 
02199             levels = o.levels;
02200             entries = o.entries;
02201             reinsertnum = o.reinsertnum;
02202             DTCallback = o.DTCallback;
02203         }
02204 
02206         Tree& operator=(const Tree &o)
02207         {
02208             rootpage = o.rootpage;
02209             pageman = o.pageman;
02210 
02211             levels = o.levels;
02212             entries = o.entries;
02213             reinsertnum = o.reinsertnum;
02214 
02215             return *this;
02216         }
02217 
02219         void    clear()
02220         {
02221             pageman.clear();
02222 
02223             rootpage = pageman.new_leafpage();
02224 
02225             NodeHead *root = pageman.getPage(rootpage);
02226             root->initializeRoot();
02227 
02228             levels = 0;
02229             entries = 0;
02230 
02231             assert(pageminfill + reinsertnum <= pagesize);
02232         }
02233 
02235         void    setCallback(DataTypeCallback *newcb)
02236         {
02237             DTCallback = newcb;
02238         }
02239 
02241         void    setReinsertNum(int rn)
02242         {
02243             reinsertnum = rn;
02244             assert(pageminfill + reinsertnum <= pagesize);
02245         }
02246         
02248         void    insertRect(const DataRef newdata)
02249         {
02250             assert(DTCallback->getMBR(newdata).valid());
02251 
02252             NodeHead *root = pageman.getPage(rootpage);
02253 
02254             // choose the leaf in which to insert the new rectangle
02255             std::stack<pageid_t> path;
02256 
02257             path.push(rootpage);
02258             class NodeHead *_leaf;
02259             if (root->level == 0) {
02260                 _leaf = static_cast<class LeafNode*>(root)->chooseSubtree(*this, DTCallback->getMBR(newdata), 0, path);
02261             }
02262             else {
02263                 _leaf = static_cast<class InnerNode*>(root)->chooseSubtree(*this, DTCallback->getMBR(newdata), 0, path);
02264             }
02265 
02266             assert(_leaf);
02267             assert(_leaf->level == 0);
02268             class LeafNode *leaf = static_cast<class LeafNode*>(_leaf);
02269 
02270             // table of overflowed levels in the R*-Tree
02271             char *overflowedLevel = static_cast<char*>(alloca(levels+1));
02272             memset(overflowedLevel, 0, levels+1);
02273 
02274             pageid_t leafpage = path.top(); // the last entry is the leaf.
02275             path.pop();
02276             leaf->insertChild(*this, leafpage, LeafNodeData(newdata), path, overflowedLevel);
02277 
02278             entries++;
02279         }
02280 
02282         bool    deleteRect(const DataRef rmdata)
02283         {
02284             assert(DTCallback->getMBR(rmdata).valid());
02285             NodeHead *root = pageman.getPage(rootpage);
02286 
02287             // find the leaf from which to delete the rectangle
02288             std::queue<pageid_t> path;
02289 
02290             class LeafNode *leaf;
02291             if (root->level == 0) {
02292                 leaf = static_cast<class LeafNode*>(root)->findLeaf(*this, LeafNodeData(rmdata), path);
02293             }
02294             else {
02295                 leaf = static_cast<class InnerNode*>(root)->findLeaf(*this, LeafNodeData(rmdata), path);
02296             }
02297 
02298             path.push(rootpage);
02299 
02300             if (!leaf) return false;
02301 
02302             assert(leaf->level == 0);
02303 
02304             pageid_t leafpage = path.front(); // the last entry is the leaf.
02305             path.pop();
02306 
02307             leaf->deleteDataLeaf(*this, leafpage, rmdata, path);
02308 
02309             entries--;
02310 
02311             return true;
02312         }
02313 
02315         void    writeFig(bool writefigheader, std::ostream &o, int maxlevel) const
02316         {
02317             if (writefigheader)
02318                 o << "#FIG 3.2\nPortrait\nCenter\nMetric\nA0\n100.00\nSingle\n-2\n10000 2\n";
02319 
02320             // colors of the rtree levels
02321 
02322             o << "0 32 #9E9E9E" << std::endl;
02323             o << "0 33 #7CF22D" << std::endl;
02324             o << "0 34 #1757C6" << std::endl;
02325             o << "0 35 #F00000" << std::endl;
02326             o << "0 36 #AD14AD" << std::endl;
02327 
02328             NodeHead *root = pageman.getPage(rootpage);
02329 
02330 #ifdef MOVIEMAKING
02331             Rect rect = root->nodeMBR;
02332 
02333             rect = Rect(602460, -5483624, 1500876, -4751257);
02334 
02335             // output rectangle as fig polyline
02336             o << "2 2 0 1 " << 32 + root->level + 1 << " 7 " << 100 - root->level << " -1 -1 0.000 0 0 -1 0 0 5\n"
02337               << "       "
02338               << rect.x1 << " " << rect.y1 << " "
02339               << rect.x2 << " " << rect.y1 << " "
02340               << rect.x2 << " " << rect.y2 << " "
02341               << rect.x1 << " " << rect.y2 << " "
02342               << rect.x1 << " " << rect.y1 << "\n";
02343 #endif
02344 
02345             if (root->level == 0)
02346                 static_cast<LeafNode*>(root)->writeFig(*this, o, maxlevel);
02347             else
02348                 static_cast<InnerNode*>(root)->writeFig(*this, o, maxlevel);
02349         }
02350 
02352         void    saveSnapshot(std::ostream &s) const
02353         {
02354             // first write a signature
02355             unsigned int key = 0x34343434;
02356             s.write(reinterpret_cast<char*>(&key), sizeof(key));
02357 
02358             // *** write vital r-tree parameters
02359             key = pagesize;
02360             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02361 
02362             key = sizeof(pageid_t);
02363             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02364 
02365             key = sizeof(DataType);
02366             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02367 
02368             key = sizeof(class InnerNode);
02369             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02370 
02371             key = sizeof(class LeafNode);
02372             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02373 
02374             // *** write global variables
02375             s.write(reinterpret_cast<const char*>(&rootpage), sizeof(rootpage));
02376 
02377             s.write(reinterpret_cast<const char*>(&levels), sizeof(levels));
02378 
02379             s.write(reinterpret_cast<const char*>(&entries), sizeof(entries));
02380 
02381             // *** write inner pages. valgrind will complain here, because we save
02382             // *** memory which was uninitialized: the unused children in each page.
02383             key = pageman.innerpages.size();
02384             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02385     
02386             for(unsigned int i = 0; i < pageman.innerpages.size(); i++)
02387             {
02388                 if (pageman.innerpages[i] == NULL) continue;
02389 
02390                 key = i;
02391                 s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02392 
02393                 s.write(reinterpret_cast<const char*>(pageman.innerpages[i]), sizeof(InnerNode));
02394             }
02395 
02396             // *** write leaf pages
02397             key = pageman.leafpages.size();
02398             s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02399     
02400             for(unsigned int i = 0; i < pageman.leafpages.size(); i++)
02401             {
02402                 if (pageman.leafpages[i] == NULL) continue;
02403 
02404                 key = i;
02405                 s.write(reinterpret_cast<const char*>(&key), sizeof(key));
02406 
02407                 s.write(reinterpret_cast<const char*>(pageman.leafpages[i]), sizeof(LeafNode));
02408             }
02409         }
02410 
02412         bool    loadSnapshot(std::istream &s)
02413         {
02414             unsigned int key;
02415     
02416             // read signature
02417             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02418             if (key != 0x34343434) return false;
02419 
02420             // *** read vital r-tree parameters
02421             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02422             if (key != pagesize) return false;
02423 
02424             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02425             if (key != sizeof(pageid_t)) return false;
02426 
02427             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02428             if (key != sizeof(DataType)) return false;
02429     
02430             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02431             if (key != sizeof(class InnerNode)) return false;
02432 
02433             if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02434             if (key != sizeof(class LeafNode)) return false;
02435 
02436             // wipe tree
02437             clear();
02438 
02439             // *** read global variables
02440 
02441             if (!s.read(reinterpret_cast<char*>(&rootpage), sizeof(rootpage))) return false;
02442 
02443             if (!s.read(reinterpret_cast<char*>(&levels), sizeof(levels))) return false;
02444 
02445             if (!s.read(reinterpret_cast<char*>(&entries), sizeof(entries))) return false;
02446 
02447             std::cerr << "Loading R-Tree with " << entries << " entries: ";
02448 
02449             // *** read inner pages
02450             unsigned int len;
02451 
02452             if (!s.read(reinterpret_cast<char*>(&len), sizeof(len))) return false;
02453             pageman.innerpages.resize(len);
02454     
02455             for(unsigned int i = 0; i < len; i++)
02456             {
02457                 if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02458                 if (key >= len) return false;
02459 
02460                 pageman.innerpages[key] = new InnerNode;
02461                 if (!s.read(reinterpret_cast<char*>(pageman.innerpages[key]), sizeof(InnerNode))) return false;
02462             }
02463 
02464             std::cerr << len << " inner nodes and ";
02465 
02466             // *** read leaf pages
02467             if (!s.read(reinterpret_cast<char*>(&len), sizeof(len))) return false;
02468             pageman.leafpages.resize(len);
02469     
02470             for(unsigned int i = 0; i < len; i++)
02471             {
02472                 if (!s.read(reinterpret_cast<char*>(&key), sizeof(key))) return false;
02473                 if (key >= len) return false;
02474 
02475                 pageman.leafpages[key] = new LeafNode;
02476                 if (!s.read(reinterpret_cast<char*>(pageman.leafpages[key]), sizeof(LeafNode))) return false;
02477             }
02478     
02479             std::cerr << len << " leaf nodes.\n";
02480 
02481             return true;
02482         }
02483 
02485         bool    testTree() const
02486         {
02487             NodeHead *root = pageman.getPage(rootpage);
02488 
02489             unsigned int testentries = 0;
02490 
02491             if (root->level == 0) {
02492                 return static_cast<class LeafNode*>(root)->checkNode(*this, levels, &testentries);
02493             }
02494             else {
02495                 return static_cast<class InnerNode*>(root)->checkNode(*this, levels, &testentries);
02496             }
02497 
02498             assert(testentries == entries);
02499         }
02500 
02502         void calcStats(Stats &s) const
02503         {
02504             NodeHead *root = pageman.getPage(rootpage);
02505 
02506             if (s.level.size() <= levels) {
02507                 s.level.resize(levels+1);
02508             }
02509 
02510             if (root->level == 0) {
02511                 static_cast<class LeafNode*>(root)->calcStats(*this, s);
02512             }
02513             else {
02514                 static_cast<class InnerNode*>(root)->calcStats(*this, s);
02515             }
02516         }
02518         AreaType        calcOverlap() const
02519         {
02520             NodeHead *root = pageman.getPage(rootpage);
02521 
02522             if (root->level == 0) {
02523                 return static_cast<class LeafNode*>(root)->calcOverlap(*this);
02524             }
02525             else {
02526                 return static_cast<class InnerNode*>(root)->calcOverlap(*this);
02527             }
02528         }
02529 
02531         AreaType        calcWasteArea() const
02532         {
02533             NodeHead *root = pageman.getPage(rootpage);
02534 
02535             if (root->level == 0) {
02536                 return static_cast<class LeafNode*>(root)->calcWasteArea(*this);
02537             }
02538             else {
02539                 return static_cast<class InnerNode*>(root)->calcWasteArea(*this);
02540             }
02541         }
02542 
02544         unsigned int size() const
02545         { return entries; }
02546 
02548         bool    empty() const
02549         { return (entries == 0); }
02550 
02553         template <typename Visitor>
02554         void    queryRange(const Rect &range, Visitor &vis) const
02555         {
02556             assert(range.valid());
02557         
02558             std::stack<pageid_t> pagestack;
02559             pagestack.push(rootpage);
02560 
02561             while(!pagestack.empty())
02562             {
02563                 pageid_t page = pagestack.top();
02564                 pagestack.pop();
02565 
02566                 NodeHead *node = pageman.getPage(page);
02567 
02568                 if (node->level == 0)
02569                 {
02570                     LeafNode *leaf = static_cast<LeafNode*>(node);
02571 
02572                     for(unsigned int ci = 0; ci < leaf->childnum; ci++)
02573                     {
02574                         if (leaf->children[ci].getMBR(*this).intersectsRect(range))
02575                         {
02576                             if (!vis(static_cast<const Rect&>(leaf->children[ci].getMBR(*this)),
02577                                      static_cast<DataType&>(leaf->children[ci])))
02578                                 return;
02579                         }
02580                     }
02581                 }
02582                 else
02583                 {
02584                     InnerNode *inner = static_cast<InnerNode*>(node);
02585 
02586                     for(unsigned int ci = 0; ci < inner->childnum; ci++)
02587                     {
02588                         if (inner->children[ci].getMBR(*this).intersectsRect(range))
02589                         {
02590                             pagestack.push(inner->children[ci].page);
02591                         }
02592                     }
02593                 }
02594             }
02595         }
02596 
02599         class NNPQData
02600         {
02601         public:
02602             pageid_t    page;
02603 
02604             AreaType    mindist;
02605 
02606             NNPQData(pageid_t _page, AreaType _mindist)
02607                 : page(_page), mindist(_mindist)
02608             {
02609             }
02610 
02611             bool operator< (const class NNPQData &o) const
02612             { return mindist < o.mindist; }
02613         };
02614 
02615         // *** Warning: This code was never tested! It was written then decided
02616         // *** that it could not be used for it's purpose.
02617 
02620         template <typename NNVisitor>
02621         void    queryNearestNeighbor(const Point &point, NNVisitor &vis) const
02622         {
02623             // put all rectangles into the priority queue ordering them by distance
02624             // to the point, if the rectangle distance is greater then
02625             // vis.mindistance then discard the subtree without entering it.
02626 
02627             std::priority_queue<NNPQData, std::deque<NNPQData> > rectqueue;
02628 
02629             rectqueue.push(NNPQData(rootpage, 0));
02630 
02631             while(!rectqueue.empty())
02632             {
02633                 NNPQData rp = rectqueue.top();
02634 
02635                 // if this rectangle's mindistance is larger then the currently
02636                 // found neighbor, then break the loop.
02637                 if (rp.mindist >= vis.mindistance) break;
02638 
02639                 rectqueue.pop();
02640 
02641                 // fetch the page
02642                 NodeHead *node = pageman.getPage(rp.page);
02643 
02644                 if (node->level == 0)
02645                 {
02646                     LeafNode *leaf = static_cast<LeafNode*>(node);
02647 
02648                     for(unsigned int ci = 0; ci < leaf->childnum; ci++)
02649                     {
02650                         AreaType md = point.getMinimumDistanceSquare(leaf->children[ci].getMBR(*this));
02651 
02652                         if (md <= vis.mindistance)
02653                         {
02654                             if (!vis(static_cast<const Rect&>(leaf->children[ci].getMBR(*this)),
02655                                      md,
02656                                      static_cast<DataType&>(leaf->children[ci])))
02657                                 return;
02658                         }
02659                     }
02660                 }
02661                 else
02662                 {
02663                     InnerNode *inner = static_cast<InnerNode*>(node);
02664 
02665                     for(unsigned int ci = 0; ci < inner->childnum; ci++)
02666                     {
02667                         // push the all subrectangles onto the rectqueue
02668                         AreaType md = point.getMinimumDistanceSquare(inner->children[ci].getMBR(*this));
02669 
02670                         if (md <= vis.mindistance)
02671                             rectqueue.push( NNPQData(inner->children[ci].page, md) );
02672                     }
02673                 }
02674 
02675             }
02676         }
02677     };
02678 };
02679 
02681 inline std::ostream& operator<< (std::ostream &o, const RTree::LevelStats &ls)
02682 {
02683     return o << "nodes: " << ls.nodes << ", "
02684              << "children: " << ls.children << ", "
02685              << "unused: " << ls.unusedchildren << ", "
02686              << "avgfill: " << (static_cast<double>(ls.children) / ls.nodes) << ", "
02687              << "bytes: " << ls.bytes << ", "
02688              << "unused: " << ls.unusedbytes << ", "
02689              << "overlap: " << ls.overlap << ", "
02690              << "wastearea: " << ls.wastearea;
02691 }
02692 
02694 inline RTree::LevelStats operator+ (const RTree::LevelStats &a, const RTree::LevelStats &b)
02695 {
02696     RTree::LevelStats c;
02697 
02698     c += a;
02699     c += b;
02700 
02701     return c;
02702 }
02703 
02704 } // namespace VGServer
02705 
02706 #endif // VGS_RTree_H

Generated on Wed Sep 27 14:34:00 2006 for VGServer by  doxygen 1.4.7