home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
-
- COPYRIGHT (C) 1992 UNIVERSITY OF CALIFORNIA
-
- ***************************************************************/
-
- #include <math.h>
- #include "kdnode.h"
- #define NULL 0
-
- int ClosestIndex;
- float *LoBound, *HiBound, ClosestDist, ClosestDistSq;
-
- /****************************************************************/
-
- int FindClosestVector(OKDTree, k, ncv, cbook, Z, CVDist)
- int k, ncv;
- float *cbook, *Z, *CVDist;
- struct KDTreeNode *OKDTree;
- {
- int i;
-
- ClosestDist = ClosestDistSq = 1.e30;
-
- LoBound = (float*)malloc(k*sizeof(float));
- HiBound = (float*)malloc(k*sizeof(float));
- if(!LoBound || !HiBound ) {
- printf("ERROR: Not enough room for malloc\n");
- exit(-1);
- }
- for(i = 0; i < k; i++) {
- LoBound[i] = -1.e30;
- HiBound[i] = 1.e30;
- }
-
- SearchOKDTree(OKDTree, k, ncv, cbook, Z);
-
- *CVDist = ClosestDist;
- return ClosestIndex;
-
- }
-
- /****************************************************************/
-
- int SearchOKDTree(Node, k, ncv, cbook, Z)
- struct KDTreeNode *Node;
- int k, ncv;
- float *cbook, *Z;
- {
- int Index, i, Axis;
- float Part, Store;
- register float xx, delta, *cbptr, *max, *zptr;
-
- /*________________________________________________________________*/
-
- if(Node->Left == NULL) { /* Terminal node */
- for(i = 0; i < Node->ListSize; i++) {
- zptr = Z;
- cbptr = cbook + (Index = Node->List[i])*k;
- max = cbptr + k;
- xx = 0.;
- while(cbptr < max) {
- delta = *zptr++ - *cbptr++;
- xx += delta*delta;
- if(xx > ClosestDistSq)
- break;
- }
- if(xx < ClosestDistSq) {
- ClosestIndex = Index;
- ClosestDistSq = xx;
- }
- }
-
- ClosestDist = sqrt(ClosestDistSq);
-
- if(BallWithinBounds(Z, k))
- return -1;
- return 0;
-
- }
-
- /*________________________________________________________________*/
-
- else { /* Nonterminal node */
-
- if(Z[Axis = Node->KeyIndex] <= (Part = Node->PartitionValue)) {
- Store = HiBound[Axis];
- HiBound[Axis] = Part;
- i = SearchOKDTree(Node->Left, k, ncv, cbook, Z);
- HiBound[Axis] = Store;
- if(i == -1)
- return -1;
- }
-
- else { /* Search the right node */
- Store = LoBound[Axis];
- LoBound[Axis] = Part;
- i = SearchOKDTree(Node->Right, k, ncv, cbook, Z);
- LoBound[Axis] = Store;
- if(i == -1)
- return -1;
- }
-
- if(Z[Axis] <= Part) { /* Search the right node */
- Store = LoBound[Axis];
- LoBound[Axis] = Part;
- if(BoundsOverlapBall(Z, k)) {
- i = SearchOKDTree(Node->Right, k, ncv, cbook, Z);
- LoBound[Axis] = Store;
- if(i == -1)
- return -1;
- }
-
- else LoBound[Axis] = Store;
-
- }
-
- else { /* Search the left node */
- Store = HiBound[Axis];
- HiBound[Axis] = Part;
-
- if(BoundsOverlapBall(Z, k)) {
- i = SearchOKDTree(Node->Left, k, ncv, cbook, Z);
- HiBound[Axis] = Store;
- if(i == -1)
- return -1;
- }
-
- else HiBound[Axis] = Store;
-
- }
-
- if(BallWithinBounds(Z, k))
- return -1;
- return 0;
-
- }
-
- }
-
- /****************************************************************/
-
- int BallWithinBounds(z, k)
- register float *z;
- int k;
- {
- register float delta, *lptr, *hptr, *max;
-
- lptr = LoBound;
- hptr = HiBound;
-
- max = z + k;
- while(z < max) {
- delta = *z - *lptr++;
- if(delta <= 0.)
- delta = -delta;
- if(delta <= ClosestDist)
- return 0;
- delta = *z++ - *hptr++;
- if(delta <= 0.)
- delta = -delta;
- if(delta <= ClosestDist)
- return 0;
- }
-
- return 1;
-
- }
-
- /****************************************************************/
-
- int BoundsOverlapBall(z, k)
- register float *z;
- int k;
- {
- register float sum = 0., delta, *lptr, *hptr, *max;
-
- lptr = LoBound;
- hptr = HiBound;
-
- max = z + k;
- while(z < max) {
-
- if(*z < *lptr)
- delta = *z - *lptr;
- else if(*z > *hptr)
- delta = *z - *hptr;
- else
- delta = 0;
-
- sum += delta*delta;
- if(sum > ClosestDistSq)
- return 0;
-
- z++;
- lptr++;
- hptr++;
-
- }
-
- return 1;
- }
-