Point<Dim> KDTree<Dim>::walkThrough(const Point<Dim> &target, const Point<Dim> &ret, int lower, int upper, int curDim) const { //base case if (lower == upper) { if (shouldReplace(target, ret, points[lower])) { return points[lower]; } return ret; } // other int median = (lower + upper)/2; Point<Dim> ret2 = ret; //a recording for which side are we going int side = 0;//0:left, 1:right if (smallerDimVal(points[median], target, curDim)&&upper>median) //why do we have to check upper>median? { int dim2 = curDim+1; if(dim2>=Dim) dim2=dim2-Dim; ret2 = walkThrough(target, ret, median+1, upper, dim2); side=1; } if (smallerDimVal(target, points[median], curDim)&&lower<median) { int dim2 = curDim+1; if(dim2>=Dim) dim2=dim2-Dim; ret2 = walkThrough(target, ret, lower, median-1, dim2); side=0; } //Check if current node is closer than obtained above if (shouldReplace(target, ret2, points[median])) ret2 = points[median]; //prepare to check the other side Point<Dim> m = points[median];//don't understand why can't point[median][Dim] int distance=0;//distance we have now for(int i=0; i< Dim; i++) distance+= pow(target[i]-ret2[i],2); if(pow(m[curDim]-target[curDim],2)<=distance) { int dim2 = curDim+1; if(dim2>=Dim) dim2=dim2-Dim; if(side==0&&upper>median)//left has been checked, goto right ret2 = walkThrough(target, ret2, median+1, upper, dim2 ); if(side==1&&lower<median)//goto left ret2 = walkThrough(target, ret2, lower, median-1, dim2 ); } return ret2; }
void KDTree<Dim>::partition(int lower, int upper, int curDim, int k) { //travel all subtree while(lower != upper) { Point<Dim> temp = points[k]; Point<Dim> temp1 = points[upper]; points[upper] = points[k]; points[k] = temp1; int storeIndex = lower; for (int i = lower; i < upper; i++)//sort the whole tree { if (smallerDimVal(points[i], temp, curDim) || points[i] == temp) { temp1 = points[storeIndex]; points[storeIndex] = points[i]; points[i] = temp1; storeIndex++; } }//now the tree is sorted temp1 = points[upper]; points[upper] = points[storeIndex]; points[storeIndex] = temp1; if (storeIndex == k) return ; else if (k < storeIndex) upper = storeIndex-1; else { lower = storeIndex+1; } } }
int KDTree<Dim>::partition(int bottom, int top, int i, int curDim) { Point<Dim> holder1 = points[i]; //making a swap Point<Dim> holder2 = points[top]; points[top] = points[i]; points[i] = holder2; int holder3 = bottom; for(int j = bottom ; j < top ; j++) { if(smallerDimVal(points[j], holder1, curDim) || points[j] == holder1) { //another swap holder2 = points[holder3]; points[holder3] = points[j]; points[j] = holder2; holder3++; } } //swap again holder2 = points[top]; points[top] = points[holder3]; points[holder3] = holder2; return holder3; }
Point<Dim> KDTree<Dim>::findNearestNeighbor(const Point<Dim> & query, int lo, int hi, int dim) const{ if(lo >= hi ) return points[lo]; //base case int mid = (hi+lo)/2; //calculate the minPoint index Point<Dim> temp; Point<Dim> curr = points[mid]; dim = dim%Dim; int direction=0; if(smallerDimVal(query, points[mid], dim)){ direction = 0; temp = findNearestNeighbor(query, lo, mid-1, dim+1); //left half } else{ direction =1; temp = findNearestNeighbor(query, mid+1, hi, dim+1); //recusively call the function on the left half } Point<Dim> best; if(shouldReplace(query, temp, curr) ) best= curr; else best = temp; int dimD = (curr[dim] - query[dim])*(curr[dim] - query[dim]); int bestCurr = squareDistance(best, query); if(dimD > bestCurr) return best; else{ Point<Dim> t; if(direction == 0) t = findNearestNeighbor(query, mid+1, hi, dim+1); else t = findNearestNeighbor(query, lo, mid-1,dim+1); if(shouldReplace(query,t, best)) return best; else return t; } }
Point<Dim> KDTree<Dim>::find(const Point<Dim> & query, int cur, int curDim, int a, int b) const { if(a == b) return points[a]; else { Point<Dim> temp; double childdist = 0; double parentdist2 = ((points[cur])[curDim] - query[curDim])*((points[cur])[curDim] - query[curDim]); double parentdist = 0; if(smallerDimVal(query, points[cur], curDim)) { if (cur-1 < a) return points[cur]; else { temp = find(query, (a+cur-1)/2, (curDim+1)%Dim, a, cur-1); for (int i = 0; i < Dim; i++) { childdist += ((temp[i]-query[i])*(temp[i]-query[i])); parentdist += (((points[cur])[i]-query[i])*((points[cur])[i]-query[i])); } if (parentdist2 <= childdist) { Point<Dim> temp2; if (cur+1 > b) temp2 = points[cur]; else temp2 = find(query, (cur+1+b)/2, (curDim+1)%Dim, cur+1, b); if ((parentdist < childdist)||((parentdist == childdist)&&(points[cur] < temp))) temp = points[cur]; if (shouldReplace(query, temp, temp2)) return temp2; else return temp; } else return temp; } } else { if (cur+1 > b) return points[cur]; else { temp = find(query, (cur+1+b)/2, (curDim+1)%Dim, cur+1, b); for (int i = 0; i < Dim; i++) { childdist += ((temp[i]-query[i])*(temp[i]-query[i])); parentdist += (((points[cur])[i]-query[i])*((points[cur])[i]-query[i])); } if (parentdist2 <= childdist) { Point<Dim> temp2; if (cur-1 < a) temp2 = points[cur]; else temp2 = find(query, (a+cur-1)/2, (curDim+1)%Dim, a, cur-1); if ((parentdist < childdist)||((parentdist == childdist)&&(points[cur] < temp))) temp = points[cur]; if (shouldReplace(query, temp, temp2)) return temp2; else return temp; } else return temp; } } } }
int KDTree<Dim>:: partition( int lo, int hi, int n, int dim){ //int pivotVal = (lo+hi)/2; swap(n, hi); int index = lo; for(int i = lo; i < hi; i++){ if(smallerDimVal(points[i], points[hi], dim)){ swap(index, i); index++; } } swap(index, hi); return index; }
void KDTree<Dim>::sort(vector< Point<Dim> > & Points, int curDim, int a, int b) { for (int i = a; i <= b; i++) { for (int j = i+1; j <= b; j++) { if (smallerDimVal(Points[j], Points[i], curDim)) { Point<Dim> temp = Points[i]; Points[i] = Points[j]; Points[j] = temp; } } } }
Point<Dim> KDTree<Dim>::NearestNeighbor_helper(int curDim, const Point<Dim> &query, int bottom, int top, const Point<Dim> ¤tBest) const { Point<Dim> retVal = currentBest;//set a holder (call it return value) equal to currentBest to start bool target = true; //initialize our target bool to true if(bottom==top) { //this means were at a leaf //we need to check if were wcloser than current best and return the appropriate currnent best if(shouldReplace(query, currentBest, points[bottom])==true) { retVal = points[bottom];//set the return value return retVal; //send that thing up! } retVal = currentBest; //otherwise return the currentBest return retVal; } //declare the middle point int middle = (bottom+top)/2; //now lets get to work on tricky stuff if(smallerDimVal(points[middle], query, curDim) && top > middle) { //recursive call to set retVal retVal = NearestNeighbor_helper((curDim+1)%Dim, query, middle+1, top, currentBest); target = false; } if (smallerDimVal(query, points[middle], curDim) && bottom <middle) { //recursive call to set retVal retVal = NearestNeighbor_helper((curDim+1)%Dim, query, bottom, middle-1, currentBest); target = true; } //look to see if the node were on is closer than what was obtained earlier if(shouldReplace(query, retVal, points[middle])) { retVal = points[middle];//set retVal appropriately } //lots of TA guidance here this is still a little foggy Point <Dim> holder = points[middle]; if(pow(holder[curDim] - query[curDim], 2) <= distance(query, retVal)) { if(!target && bottom < middle) { retVal = NearestNeighbor_helper((curDim+1)%Dim, query, bottom, middle-1, retVal);//same as above but replace currentBest with retVal! } if(target && top > middle) { //recurisve call retVal = NearestNeighbor_helper((curDim+1)%Dim, query, middle+1, top, retVal);//same as above but replace currentBest with retVal! } } //AND FINALLY return retVal; }