// // $Id: index.cpp 4034 2008-10-03 01:17:40Z rares $ // // index.cpp // // Copyright (C) 2003 - 2007 by The Regents of the University of // California // // Redistribution of this file is permitted under the terms of the // BSD license // // Date: March 2002 // // Authors: Michael Ortega-Binderberger (miki@ics.uci.edu) // Liang Jin (liangj@ics.uci.edu) // Chen Li (chenli@ics.uci.edu) // #include #include #include #include #include #include "index.h" // global variable, root #define DEFINED(val) (val >= 0.0 && val <= 1.0 ? TRUE: FALSE) //struct Node *RTreeRoot; FILE *fp; int spheres_exist=0; // Make a new index, empty. Consists of a single node. Rtree::Rtree() { struct Node *x; x = RTreeNewNode(); TreeRoot = x; x->level = 0; /* leaf */ join_other_tree = NULL; join_dist_func = NULL; join_disk_acc1 = NULL; join_disk_acc_length1 = 0; join_disk_acc2 = NULL; join_disk_acc_length2 = 0; join_cpu_comp = NULL; join_cpu_comp_length = 0; join_cpu_comp_total = NULL; join_active_query = false; join_pqueue = NULL; join_max_distance = NULL; } Rtree::~Rtree() { } int Rtree::RTreeLoad(char *dumpfile) { int loadcount; fp= fopen(dumpfile, "r"); loadcount=Load(TreeRoot); //cout << loadcount << " nodes loaded" << endl; fclose(fp); //CreateSpheres(TreeRoot); // this will fill in all the radii spheres_exist = 1; return loadcount; } int Rtree::Load(struct Node *N) { //struct Node *newNode; struct Node *n= N; int nodeCount = 0; int i; fread(&(n->count), sizeof(int), 1, fp); fread(&(n->level), sizeof(int), 1, fp); if (n->level > 0) /* this is an internal node in the tree */ { for(i=0; icount; i++) fread(&(n->branch[i].rect), sizeof(struct Rect), 1, fp); for(i=0; i< n->count; i++) { n->branch[i].child = RTreeNewNode(); nodeCount = nodeCount + Load(n->branch[i].child) + 1; } //cout << "Inner node level: " << n->level << endl; return nodeCount; } else /* this is a leaf node */ { for(i=0; icount; i++) fread(&(n->branch[i].rect), sizeof(struct Rect), 1, fp); for(i=0; icount; i++) fread(&(n->branch[i].child), sizeof(struct Node*), 1, fp); //cout << "Leaf level: " << n->level << endl; return 0; } } bool Rtree::GenerateMBRfromNode(struct Node * node, struct Rect * the_mbr_rect) { // true if all ok, false otherwise (like if the node has // no boxes. assert(NULL != node); assert(NULL != the_mbr_rect); bool res = false; float min_dim, max_dim; for (int dims=0; dims < NUMDIMS; dims++) { // for each dimension // get the max and min values min_dim = node->branch[0].rect.boundary[dims]; max_dim = node->branch[0].rect.boundary[dims+NUMDIMS]; for (int i=0; icount; i++) { // go over all branches if (node->branch[i].rect.boundary[dims] < min_dim) { min_dim = node->branch[i].rect.boundary[dims]; } if (node->branch[i].rect.boundary[dims+NUMDIMS] > max_dim) { max_dim = node->branch[i].rect.boundary[dims+NUMDIMS]; } res = true; } the_mbr_rect->boundary[dims] = min_dim; the_mbr_rect->boundary[dims+NUMDIMS] = max_dim; } return res; } void Rtree::print_rect(ostream & os, struct Rect & rect, bool add_endl) { os << " ["; int i; for (i=0; ilevel > 1) { // high level nodes for(i=0; icount; i++) CreateSpheres(n->branch[i].child); // invoke create spheres on all children } else { assert(n->level == 1); for(i=0; icount; i++) { centroid=Center(&n->branch[i].rect); n->branch[i].radius=ComputeRadius(¢roid, n->branch[i].child); } } } int Rtree::RTreeDump(char *dumpfile) { int dumpcount; fp= fopen(dumpfile, "w"); dumpcount=Dump(TreeRoot); fclose(fp); return dumpcount; } int Rtree::Dump(struct Node *N) { struct Node *n= N; int nodeCount = 0; int i/*,j*/; if (n->level > 0) { /* this is an internal node in the tree */ fwrite(&(n->count), sizeof(int), 1, fp); fwrite(&(n->level), sizeof(int), 1, fp); for(i=0; i< n->count; i++) { fwrite(&(n->branch[i].rect), sizeof(struct Rect), 1, fp); } for(i=0; i< n->count; i++) nodeCount = nodeCount + Dump(n->branch[i].child) + 1; RTreeFreeNode(n); return nodeCount; } else /* this is a leaf node */ { fwrite(&(n->count), sizeof(int), 1, fp); fwrite(&(n->level), sizeof(int), 1, fp); for(i=0; icount; i++) { fwrite(&(n->branch[i].rect), sizeof(struct Rect), 1, fp); } for(i=0; icount; i++) fwrite(&(n->branch[i].child), sizeof(struct Node*), 1, fp); RTreeFreeNode(n); return 0; } } // Inserts a new data rectangle into the index structure. // Recursively descends tree, propagates splits back up. // Returns 0 if node was not split. Old node updated. // If node was split, returns 1 and sets the pointer pointed to by // new_node to point to the new node. Old node updated to become one of two. // The level argument specifies the number of steps up from the leaf // level to insert; e.g. a data rectangle goes in at level = 0. // static int RTreeInsertRect2(struct Rect *r, int tid, struct Node *n, struct Node **new_node, int level) { /* register struct Rect *r = R; register int tid = Tid; register struct Node *n = N, **new_node = New_node; register int level = Level; */ register int i; struct Branch b; struct Node *n2; assert(r && n && new_node); assert(level >= 0 && level <= n->level); // Still above level for insertion, go down tree recursively if (n->level > level) { i = RTreePickBranch(r, n); if (!RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level)) { // child was not split n->branch[i].rect = RTreeCombineRect(r,&(n->branch[i].rect)); return 0; } else { // child was split n->branch[i].rect = RTreeNodeCover(n->branch[i].child); b.child = n2; b.rect = RTreeNodeCover(n2); return RTreeAddBranch(&b, n, new_node); } } else if (n->level == level) { /* Have reached level for insertion. Add rect, split if necessary */ b.rect = *r; b.child = (struct Node *) tid; /* child field of leaves contains tid of data record */ return RTreeAddBranch(&b, n, new_node); } else { /* Not supposed to happen */ assert (FALSE); return 0; } } int Rtree::RTreeInsertRect(struct Rect *R, int Tid) { struct Node *rootNode; rootNode = TreeRoot; return (RTreeInsertRect(R, Tid, &rootNode, 0)); } // Insert a data rectangle into an index structure. // RTreeInsertRect provides for splitting the root; // returns 1 if root was split, 0 if it was not. // The level argument specifies the number of steps up from the leaf // level to insert; e.g. a data rectangle goes in at level = 0. // RTreeInsertRect2 does the recursion. // int Rtree::RTreeInsertRect(struct Rect *R, int Tid, struct Node **Root, int Level) { struct Rect *r = R; int tid = Tid; struct Node **root = Root; int level = Level; int i; struct Node *newroot; struct Node *newnode; struct Branch b; int result; if (level < 0) int yy = 1; assert(r && root); assert(level >= 0 && level <= (*root)->level); for (i=0; iboundary[i]) assert(r->boundary[i] <= r->boundary[NUMDIMS+i]); } if (RTreeInsertRect2(r, tid, *root, &newnode, level)) { /* root split */ newroot = RTreeNewNode(); /* grow a new root, & tree taller */ TreeRoot = newroot; newroot->level = (*root)->level + 1; b.rect = RTreeNodeCover(*root); b.child = *root; RTreeAddBranch(&b, newroot, NULL); b.rect = RTreeNodeCover(newnode); b.child = newnode; RTreeAddBranch(&b, newroot, NULL); *root = newroot; result = 1; } else result = 0; return result; } // Allocate space for a node in the list used in DeletRect to // store Nodes that are too empty. // static struct ListNode * RTreeNewListNode() { return (struct ListNode *) malloc(sizeof(struct ListNode)); //return new ListNode; } static void RTreeFreeListNode(struct ListNode *p) { //free(p); delete(p); } // Add a node to the reinsertion list. All its branches will later // be reinserted into the index structure. // static void RTreeReInsert(struct Node *n, struct ListNode **ee) { register struct ListNode *l; l = RTreeNewListNode(); l->node = n; l->next = *ee; *ee = l; } // Delete a rectangle from non-root part of an index structure. // Called by RTreeDeleteRect. Descends tree recursively, // merges branches on the way back up. // static int RTreeDeleteRect2(struct Rect *R, int Tid, struct Node *N, struct ListNode **Ee) { register struct Rect *r = R; register int tid = Tid; register struct Node *n = N; register struct ListNode **ee = Ee; register int i; assert(r && n && ee); assert(tid >= 0); assert(n->level >= 0); if (n->level > 0) { // not a leaf node for (i = 0; i < NODECARD; i++) { if (n->branch[i].child && RTreeOverlap(r, &(n->branch[i].rect))) { if (!RTreeDeleteRect2(r, tid, n->branch[i].child, ee)) { if (n->branch[i].child->count >= MinFill) n->branch[i].rect = RTreeNodeCover( n->branch[i].child); else { // not enough entries in child, eliminate child node RTreeReInsert(n->branch[i].child, ee); RTreeDisconnectBranch(n, i); } return 0; } } } return 1; } else { // a leaf node for (i = 0; i < NODECARD; i++) { if (n->branch[i].child && n->branch[i].child == (struct Node *) tid) { RTreeDisconnectBranch(n, i); return 0; } } return 1; } } // Delete a data rectangle from an index structure. // Pass in a pointer to a Rect, the tid of the record, ptr to ptr to root node. // Returns 1 if record not found, 0 if success. // RTreeDeleteRect provides for eliminating the root. // int Rtree::RTreeDeleteRect(struct Rect *R, int Tid, struct Node**Nn) { register struct Rect *r = R; register int tid = Tid; register struct Node **nn = Nn; register int i; register struct Node *tmp_node_ptr; struct ListNode *reInsertList = NULL; register struct ListNode *e; assert(r && nn); assert(*nn); assert(tid >= 0); if (!RTreeDeleteRect2(r, tid, *nn, &reInsertList)) { // found and deleted a data item // reinsert any branches from eliminated nodes while (reInsertList) { tmp_node_ptr = reInsertList->node; for (i = 0; i < NODECARD; i++) { if (tmp_node_ptr->branch[i].child) { RTreeInsertRect( &(tmp_node_ptr->branch[i].rect), (int) tmp_node_ptr->branch[i].child, nn, tmp_node_ptr->level); } } e = reInsertList; reInsertList = reInsertList->next; RTreeFreeNode(e->node); RTreeFreeListNode(e); } // check for redundant root (not leaf, 1 child) and eliminate if ((*nn)->count == 1 && (*nn)->level > 0) { for (i = 0; i < NODECARD; i++) { tmp_node_ptr = (*nn)->branch[i].child; if(tmp_node_ptr) break; } assert(tmp_node_ptr); RTreeFreeNode(*nn); *nn = tmp_node_ptr; } return 0; } else { return 1; } } // ------------------------------------------------------------ // ------------- Searching functions -------------------------- // generic search, counts accesses only //int Rtree::RTreeSearch(struct Rect *R, long *diskacc, vector &answers) { int Rtree::RTreeSearch(struct Rect *R, vector &answers) { long disk_acc[10]; struct Node *rootNode; rootNode = TreeRoot; return (RTreeSearch(rootNode, R, disk_acc, answers)); } // Search in an index tree or subtree for all data retangles that // overlap the argument rectangle. // Returns the number of qualifying data rects. int Rtree::RTreeSearch(struct Node *N, struct Rect *R, long *diskacc, vector &answers) { struct Node *n = N; struct Rect *r = R; int hitCount = 0, i; struct Point querypoint/*, centroid*/; float maxradius=0.0; assert(n); assert(n->level >= 0); assert(r); maxradius=(r->boundary[NUMDIMS]-r->boundary[0])*RANGEFACTOR; for(i=0; iboundary[i]+ r->boundary[i+NUMDIMS])/2; if (n->level > 0) { /* this is an internal node in the tree */ for (i=0; ilevel == 1) { // use both conditions if (n->branch[i].child && RTreeOverlap(&querypoint,&n->branch[i].rect, maxradius, DIST_METRIC)) { /* centroid=Center(&n->branch[i].rect); if (Distance(&querypoint, ¢roid, DIST_METRIC) <= (n->branch[i].radius + maxradius)) */ //printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount += RTreeSearch(n->branch[i].child, R, diskacc, answers); } } else { if (n->branch[i].child && RTreeOverlap(&querypoint,&n->branch[i].rect, maxradius, DIST_METRIC)) { //printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount += RTreeSearch(n->branch[i].child, R, diskacc, answers); } } } } else { /* this is a leaf node */ for (i=0; ibranch[i].child && RTreeOverlap(r,&n->branch[i].rect)) */ if (n->branch[i].child && RTreeOverlap(&querypoint,&n->branch[i].rect, maxradius, DIST_METRIC)) { // printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount++; answers.push_back((int)n->branch[i].child); // Added by Chen Li } } } return hitCount; } //-------------------------------------------------------------------------------------- //--------------------------------- join search ---------------------------------------- int Rtree::SearchJoinOpen(Rtree * rt, DistanceFunction * df, float * max_join_dist, long *diskacc1, long disk_acc_length1, // disk for tree 1 (me) long *diskacc2, long disk_acc_length2, // disk for tree 2 (other) long *cpu_computations, long cpu_computations_length, // per level long *cpu_comps_total) { // total distance computations join_other_tree = rt; // I'm me (1), this is the parner tree for join(2) join_dist_func = df; // retain distance function join_max_distance = max_join_dist; // init variables. join_disk_acc_length1 = disk_acc_length1; // preserve for later copy join_disk_acc1 = diskacc1; join_disk_acc_length2 = disk_acc_length2; // preserve for later copy join_disk_acc2 = diskacc2; join_cpu_comp = cpu_computations; // preserve for later copy join_cpu_comp_length = cpu_computations_length; join_cpu_comp_total = cpu_comps_total; int i; for (i=0; iTreeRoot, &r1); // bounding box for myself GenerateMBRfromNode(join_other_tree->TreeRoot, &r2); // bounding box for other index //print_rect(cout, r1); print_rect(cout, r2); // gonna print out the bboxes. // bootstrap priority queue with first pair of roots. JoinElement j_el; j_el.first.the_node = TreeRoot; j_el.first.the_mbr = r1; j_el.first.the_id = -1; j_el.first.is_data = false; // is not a data point j_el.first.target_node_explored = false; // have not looked at children j_el.second.the_node = join_other_tree->TreeRoot; j_el.second.the_mbr = r2; j_el.second.the_id = -1; j_el.second.is_data = false; // is not a data point j_el.second.target_node_explored = false; // have not looked at children j_el.dist = 0.0; // two roots forced to have 0 distance at first? // get the queues. if (NULL != join_pqueue) delete join_pqueue; // if old, nuke it. //if (NULL != join_q_already_returned) delete join_q_already_returned; // if old, nuke it. join_pqueue = new JoinPQueue; // get a new queue; //join_q_already_returned = new JoinPQueue; // get a new queue; // count up. join_disk_acc1[j_el.first .the_node->level] ++; // I/O to join_disk_acc2[j_el.second.the_node->level] ++; // the roots (*join_cpu_comp_total) ++; // 'computed the distance between roots' join_pqueue->push(j_el); // bootstrap; join_active_query = true; // ok, we're all set, so mark it return 0; } // exploration model can be SYMMETRIC (explore both sides as n^2 // A_SYMMETRIC void Rtree::join_aux_point_point(JoinElement & j_el, join_pair_result & item, int exploration_model) { // handle the final point to point // regardless of exploration model, its only 1 to 1 assert(j_el.first.is_data && j_el.second.is_data); // they are points assert(NULL==j_el.first.the_node && NULL==j_el.second.the_node); // ensure correctness assert(j_el.first .target_node_explored); assert(j_el.second.target_node_explored); item.distance = j_el.dist; item.first.the_id = j_el.first.the_id; item.first.rect = j_el.first.the_mbr; item.second.the_id = j_el.second.the_id; item.second.rect = j_el.second.the_mbr; } void Rtree::join_aux_node_node(JoinElement::JoinTerm * first, JoinElement::JoinTerm * second, JoinElement & j_el, bool swap, int exploration_model) { // this compares internal nodes in the tree assert( ! first->is_data); assert( ! second->is_data); // none is a point assert(first ->the_node != NULL && second->the_node != NULL); // valid assert(first ->the_node->level > 0); // first is an internal node assert(second->the_node->level > 0); // second is also a node JoinElement j_el_aux; for (int i=0; ithe_node->count; i++) { for (int j=0; jthe_node->count; j++) { j_el_aux.first.the_node = first->the_node->branch[i].child; j_el_aux.first.the_mbr = first->the_node->branch[i].rect; j_el_aux.first.the_id = -1; j_el_aux.first.is_data = false; // its another node j_el_aux.first.target_node_explored = false; // j_el_aux.second.the_node = second->the_node->branch[j].child; j_el_aux.second.the_mbr = second->the_node->branch[j].rect; j_el_aux.second.the_id = -1; j_el_aux.second.is_data = false; // a node j_el_aux.second.target_node_explored = false; // // note the order, the second one is assumed to be the mbr and first is query point j_el_aux.dist = join_dist_func->rectangle_mindist(& j_el_aux.first.the_mbr, & j_el_aux.second.the_mbr); if ((NULL != join_max_distance && j_el_aux.dist < *join_max_distance) || (NULL == join_max_distance)) join_pqueue->push(j_el_aux); (*join_cpu_comp_total) ++; // accounting |n1| * |n2| computations } } // misc accounting crap (only 1 IO per node!) join_disk_acc1[first ->the_node->level]++; join_disk_acc2[second->the_node->level]++; // remember what we got out and mark it as explored j_el.first.target_node_explored = j_el.second.target_node_explored = true; } void Rtree::join_aux_node_leaf(JoinElement::JoinTerm * first, JoinElement::JoinTerm * second, JoinElement & j_el, bool swap, int exploration_model) { // this compares internal node in the tree to a leaf assert( ! first->is_data); assert( ! second->is_data); // none is a point assert(first ->the_node != NULL && second->the_node != NULL); // valid assert(first ->the_node->level > 0); // first is an internal node assert(second->the_node->level == 0); // second one is a leaf JoinElement j_el_aux; for (int i=0; ithe_node->count; i++) { for (int j=0; jthe_node->count; j++) { j_el_aux.first.the_node = first->the_node->branch[i].child; j_el_aux.first.the_mbr = first->the_node->branch[i].rect; j_el_aux.first.the_id = -1; j_el_aux.first.is_data = false; j_el_aux.first.target_node_explored = false; j_el_aux.second.the_node = NULL; j_el_aux.second.the_mbr = second->the_node->branch[j].rect; j_el_aux.second.the_id = (int)second->the_node->branch[j].child; j_el_aux.second.is_data = true; // its a data item (P) j_el_aux.second.target_node_explored = true; // no more to explore // note the order, the second one is assumed to be the mbr and first is a point j_el_aux.dist = join_dist_func->compute_mindist(& j_el_aux.second.the_mbr, & j_el_aux.first.the_mbr); if ((NULL != join_max_distance && j_el_aux.dist < *join_max_distance) || (NULL == join_max_distance)) join_pqueue->push(j_el_aux); (*join_cpu_comp_total) ++; // accounting |n1| * |n2| computations } } // misc accounting crap (only 1 IO per node!) join_disk_acc1[first ->the_node->level]++; join_disk_acc2[second->the_node->level]++; // remember what we got out and mark it as explored j_el.first.target_node_explored = j_el.second.target_node_explored = true; } void Rtree::join_aux_leaf_leaf(JoinElement::JoinTerm * first, JoinElement::JoinTerm * second, JoinElement & j_el, bool swap, int exploration_model) { // compares two leaves assert( ! first->is_data); assert( ! second->is_data); // none is a point assert(first ->the_node != NULL && second->the_node != NULL); // valid assert(first ->the_node->level == 0); // first one is a leaf assert(second->the_node->level == 0); // second one is a leaf JoinElement j_el_aux; for (int i=0; ithe_node->count; i++) { for (int j=0; jthe_node->count; j++) { j_el_aux.first.the_node = NULL; j_el_aux.first.the_mbr = first->the_node->branch[i].rect; j_el_aux.first.the_id = (int)first->the_node->branch[i].child; j_el_aux.first.is_data = true; // its a data item (P) j_el_aux.first.target_node_explored = true; // no more to explore j_el_aux.second.the_node = NULL; j_el_aux.second.the_mbr = second->the_node->branch[j].rect; j_el_aux.second.the_id = (int)second->the_node->branch[j].child; j_el_aux.second.is_data = true; // its a data item (P) j_el_aux.second.target_node_explored = true; // no more to explore // both are considered to be points j_el_aux.dist = join_dist_func->compute_distance(& j_el_aux.second.the_mbr, & j_el_aux.first.the_mbr); if ((NULL != join_max_distance && j_el_aux.dist < *join_max_distance) || (NULL == join_max_distance)) join_pqueue->push(j_el_aux); (*join_cpu_comp_total) ++; // accounting |n1| * |n2| computations } } // misc accounting crap (only 1 IO per node!) join_disk_acc1[first ->the_node->level]++; join_disk_acc2[second->the_node->level]++; // remember what we got out and mark it as explored j_el.first.target_node_explored = j_el.second.target_node_explored = true; } void Rtree::join_aux_leaf_point(JoinElement::JoinTerm * first, JoinElement::JoinTerm * second, JoinElement & j_el, bool swap, int exploration_model) { // compares a leaf to a point (first is leaf, second is point) assert( ! first->is_data); assert( second->is_data); // only second is a point assert(first ->the_node != NULL); // valid assert(first ->the_node->level == 0); // first is a leaf assert(second->the_node == NULL); // second one is a point JoinElement j_el_aux; for (int i=0; ithe_node->count; i++) { j_el_aux.first.the_node = NULL; j_el_aux.first.the_mbr = first->the_node->branch[i].rect; j_el_aux.first.the_id = (int)first->the_node->branch[i].child; j_el_aux.first.is_data = true; // its a data item (P) j_el_aux.first.target_node_explored = true; // no more to explore j_el_aux.second.the_node = second->the_node; j_el_aux.second.the_mbr = second->the_mbr; j_el_aux.second.the_id = second->the_id; j_el_aux.second.is_data = second->is_data; j_el_aux.second.target_node_explored = second->target_node_explored; // both are considered to be points j_el_aux.dist = join_dist_func->compute_distance(& j_el_aux.second.the_mbr, & j_el_aux.first.the_mbr); if ((NULL != join_max_distance && j_el_aux.dist < *join_max_distance) || (NULL == join_max_distance)) join_pqueue->push(j_el_aux); (*join_cpu_comp_total) ++; // accounting |n1| * |n2| computations } // misc accounting crap (only 1 IO per node!) join_disk_acc1[first ->the_node->level]++; //join_disk_acc2[second->the_node->level]++; // just copied second // remember what we got out and mark it as explored j_el.first.target_node_explored = j_el.second.target_node_explored = true; } void Rtree::join_aux_node_point(JoinElement::JoinTerm * first, JoinElement::JoinTerm * second, JoinElement & j_el, bool swap, int exploration_model) { // compares an internal node to a point (first is node, second is point) assert( ! first->is_data); assert( second->is_data); // only second is a point assert(first ->the_node != NULL); // valid assert(first ->the_node->level > 0); // first is a node assert(second->the_node == NULL); // second one is a point JoinElement j_el_aux; for (int i=0; ithe_node->count; i++) { j_el_aux.first.the_node = first->the_node->branch[i].child; j_el_aux.first.the_mbr = first->the_node->branch[i].rect; j_el_aux.first.the_id = -1; j_el_aux.first.is_data = false; // its not data j_el_aux.first.target_node_explored = false; // j_el_aux.second.the_node = second->the_node; j_el_aux.second.the_mbr = second->the_mbr; j_el_aux.second.the_id = second->the_id; j_el_aux.second.is_data = second->is_data; j_el_aux.second.target_node_explored = second->target_node_explored; // note the order, the second one is assumed to be the mbr and first is a point j_el_aux.dist = join_dist_func->compute_mindist(& j_el_aux.second.the_mbr, & j_el_aux.first.the_mbr); if ((NULL != join_max_distance && j_el_aux.dist < *join_max_distance) || (NULL == join_max_distance)) join_pqueue->push(j_el_aux); (*join_cpu_comp_total) ++; // accounting |n1| * |n2| computations } // misc accounting crap (only 1 IO per node!) join_disk_acc1[first ->the_node->level]++; //join_disk_acc2[second->the_node->level]++;//just copied second, no io // remember what we got out and mark it as explored j_el.first.target_node_explored = j_el.second.target_node_explored = true; } int Rtree::SearchJoinNext(float & distance, join_pair_result & item) { assert(join_active_query); assert(NULL != join_dist_func); assert(NULL != join_pqueue); //assert(NULL != join_q_already_returned); JoinElement j_el, j_el_aux; JoinElement::JoinTerm * first = NULL, * second = NULL, *term = NULL; bool swap = false; // needed for functions that can be called with exckanged trees int em = 1; // explore model while (join_pqueue->size() > 0) { // still stuff j_el = join_pqueue->top(); // get the top first = &j_el.first; // alias them second = &j_el.second; // alias them join_pqueue->pop(); // and dispose it swap = false; if (first->is_data && second->is_data) { // P-P // both are points, assemble and return them. join_aux_point_point(j_el, item, em); distance = item.distance; //join_q_already_returned->push(j_el); // ok, processed it already return 1; } else if (NULL != first->the_node && NULL != second->the_node) { // both leaf or node assert( ! first->is_data); assert( ! second->is_data); // none is a point if (first->the_node->level > 0 && second->the_node->level >0) { // N-N join_aux_node_node(first, second, j_el, swap, em); // both are internal nodes } else if (first->the_node->level == 0 && second->the_node->level > 0) { // L-N swap = true; join_aux_node_leaf(second, first, j_el, swap, em); // first is leaf, second is internal node } else if (first->the_node->level > 0 && second->the_node->level == 0) { // N-L join_aux_node_leaf(first, second, j_el, swap, em); // second is leaf, first is internal node } else if (first->the_node->level == 0 && second->the_node->level == 0) { // L-L join_aux_leaf_leaf(first, second, j_el, swap, em); // second is leaf, first is internal node } } else { // one or both are NULL // if both are NULL, then it must be p-p which is // handled elsewhere, so its bad... //cout << "first is " << first->the_node << endl; //cout << "second is " << second->the_node << endl; assert( ! (first->is_data && second->is_data)); // p-p must not be allowed here! assert( first->is_data || second->is_data); // exactly 1 is a p assert( (NULL==first->the_node && NULL!=second->the_node) || (NULL!=first->the_node && NULL==second->the_node)); // only 1 if (NULL==first->the_node && NULL != second->the_node) { // swap them term = first; first = second; second = term; swap = true; } // else nothing to swap! assert(NULL != first->the_node && NULL == second->the_node); assert(second->is_data); // first is N or L, second is P if (first->the_node->level > 0) { // N-P join_aux_node_point(first, second, j_el, swap, em); } else if (first->the_node->level == 0) { // L-P join_aux_leaf_point(first, second, j_el, swap, em); } else { // should not happen assert(false); } } //join_q_already_returned->push(j_el); // ok, processed it already } return 0; // queue empty } int Rtree::SearchJoinClose() { assert(join_active_query); if (NULL != join_pqueue) { delete join_pqueue; // if old, nuke it. join_pqueue = NULL; } /*if (NULL != join_q_already_returned) { delete join_q_already_returned; // if old, nuke it. join_q_already_returned = NULL; }*/ join_active_query = false; return 1; // all ok } int Rtree::SearchJoinNewIteration(DistanceFunction * df_new, int & cpu_distance_comps, int & nodes_copied, int reconstruct_model) { assert(join_active_query); assert(NULL != join_dist_func); // ensure correct state return 1; // all ok } //-------------------------------------------------------------------------------------- //-------------- Range search using a sphere-------------------------------------------- //-------------- Written by Chen Li---------------------------------------------------- //-------------------------------------------------------------------------------------- int Rtree::RTreeSearchSphere(struct Point *queryPoint, float radius, vector &answers) { long disk_acc[10]; struct Node *rootNode = TreeRoot; return RTreeSearchSphere(rootNode, queryPoint, radius, disk_acc, answers); } // Search in an index tree or subtree for all data retangles that // overlap the given sphere // Returns the number of qualifying data rects. int Rtree::RTreeSearchSphere(struct Node *N, struct Point *queryPoint, float radius, long *diskacc, vector &answers) { struct Node *n = N; int hitCount = 0, i; //struct Rect *r = R; //struct Point querypoint/*, centroid*/; //float maxradius=0.0; assert(n); assert(n->level >= 0); assert(queryPoint); //maxradius=(r->boundary[NUMDIMS] - r->boundary[0]) * RANGEFACTOR; //?? if (n->level > 0) { /* this is an internal node in the tree */ for (i=0; ilevel == 1) { // use both conditions if (n->branch[i].child && RTreeOverlapSphere(&n->branch[i].rect, queryPoint, radius)) { /* centroid=Center(&n->branch[i].rect); if (Distance(&querypoint, ¢roid, DIST_METRIC) <= (n->branch[i].radius + maxradius)) */ //printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount += RTreeSearchSphere(n->branch[i].child, queryPoint, radius, diskacc, answers); } } else { if (n->branch[i].child && RTreeOverlapSphere(&n->branch[i].rect, queryPoint, radius)) { //printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount += RTreeSearchSphere(n->branch[i].child, queryPoint, radius, diskacc, answers); } } } } else { /* this is a leaf node */ for (i=0; ibranch[i].child && RTreeOverlapSphere(r,&n->branch[i].rect)) */ if (n->branch[i].child && RTreeOverlapSphere(&n->branch[i].rect, queryPoint, radius)) { // printf("Accessing a node at level %d \n", n->level); diskacc[n->level]++; hitCount++; answers.push_back((int)n->branch[i].child); // Added by Chen Li } } } return hitCount; }