void ANNbruteForce::annkSearch( // approx k near neighbor search ANNpoint q, // query point int k, // number of near neighbors to return ANNidxArray nn_idx, // nearest neighbor indices (returned) ANNdistArray dd, // dist to near neighbors (returned) double eps) // error bound (ignored) { ANNmin_k mk(k); // construct a k-limited priority queue int i; if (k > n_pts) { // too many near neighbors? annError("Requesting more near neighbors than data points", ANNabort); } // run every point through queue for (i = 0; i < n_pts; i++) { // compute distance to point ANNdist sqDist = annDist(dim, pts[i], q); if (ANN_ALLOW_SELF_MATCH || sqDist != 0) mk.insert(sqDist, i); } for (i = 0; i < k; i++) { // extract the k closest points dd[i] = mk.ith_smallest_key(i); nn_idx[i] = mk.ith_smallest_info(i); } }
ANNkd_tree::ANNkd_tree( // construct from point array ANNpointArray pa, // point array (with at least n pts) int n, // number of points int dd, // dimension int bs, // bucket size ANNsplitRule split) // splitting method { SkeletonTree(n, dd, bs); // set up the basic stuff pts = pa; // where the points are actual_num_points = n; if (n == 0) return; // no points--no sweat ANNorthRect bnd_box(dd); // bounding box for points annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle // copy to tree structure bnd_box_lo = annCopyPt(dd, bnd_box.lo); bnd_box_hi = annCopyPt(dd, bnd_box.hi); switch (split) { // build by rule case ANN_KD_STD: // standard kd-splitting rule root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split, &pointToLeafVec); break; case ANN_KD_MIDPT: // midpoint split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split, &pointToLeafVec); break; case ANN_KD_FAIR: // fair split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split, &pointToLeafVec); break; case ANN_KD_SUGGEST: // best (in our opinion) case ANN_KD_SL_MIDPT: // sliding midpoint split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split, &pointToLeafVec); break; case ANN_KD_SL_FAIR: // sliding fair split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split, &pointToLeafVec); break; // for kd-trees with deletion /* //case ANN_KD_SUGGEST: case ANN_KD_STD_WD: root = rkd_tree_wd(pa, pidx, n, dd, bs, bnd_box, kd_split_wd); break; case ANN_KD_MIDPT_WD: root = rkd_tree_wd(pa, pidx, n, dd, bs, bnd_box, kd_split_wd); break; case ANN_KD_SL_MIDPT_WD: root = rkd_tree_wd(pa, pidx, n, dd, bs, bnd_box, kd_split_wd); break; */ default: annError("Illegal splitting method", ANNabort); } }
ANNbd_tree::ANNbd_tree( // construct from point array ES_INFO* es_info, ANNpointArray pa, // point array (with at least n pts) int n, // number of points int dd, // dimension int bs, // bucket size ANNsplitRule split, // splitting rule ANNshrinkRule shrink) // shrinking rule : ANNkd_tree(n, dd, bs) // build skeleton base tree { pts = pa; // where the points are if (n == 0) return; // no points--no sweat ANNorthRect bnd_box(dd); // bounding box for points // construct bounding rectangle annEnclRect(es_info, pa, pidx, n, dd, bnd_box); // copy to tree structure bnd_box_lo = annCopyPt(dd, bnd_box.lo); bnd_box_hi = annCopyPt(dd, bnd_box.hi); switch (split) { // build by rule case ANN_KD_STD: // standard kd-splitting rule root = rbd_tree(es_info, pa, pidx, n, dd, bs, bnd_box, kd_split, shrink); break; case ANN_KD_MIDPT: // midpoint split root = rbd_tree(es_info, pa, pidx, n, dd, bs, bnd_box, midpt_split, shrink); break; case ANN_KD_SUGGEST: // best (in our opinion) case ANN_KD_SL_MIDPT: // sliding midpoint split root = rbd_tree(es_info, pa, pidx, n, dd, bs, bnd_box, sl_midpt_split, shrink); break; case ANN_KD_FAIR: // fair split root = rbd_tree(es_info, pa, pidx, n, dd, bs, bnd_box, fair_split, shrink); break; case ANN_KD_SL_FAIR: // sliding fair split root = rbd_tree(es_info, pa, pidx, n, dd, bs, bnd_box, sl_fair_split, shrink); break; default: annError("Illegal splitting method", ANNabort); } }
ANNdecomp selectDecomp( // select decomposition method ES_INFO* es_info, ANNpointArray pa, // point array ANNidxArray pidx, // point indices to store in subtree int n, // number of points int dim, // dimension of space const ANNorthRect &bnd_box, // current bounding box ANNkd_splitter splitter, // splitting procedure ANNshrinkRule shrink, // shrinking rule ANNorthRect &inner_box) // inner box if shrinking (returned) { ANNdecomp decomp = SPLIT; // decomposition switch (shrink) { // check shrinking rule case ANN_BD_NONE: // no shrinking allowed decomp = SPLIT; break; case ANN_BD_SUGGEST: // author's suggestion case ANN_BD_SIMPLE: // simple shrink decomp = trySimpleShrink( es_info, pa, pidx, // points and indices n, dim, // number of points and dimension bnd_box, // current bounding box inner_box); // inner box if shrinking (returned) break; case ANN_BD_CENTROID: // centroid shrink decomp = tryCentroidShrink( es_info, pa, pidx, // points and indices n, dim, // number of points and dimension bnd_box, // current bounding box splitter, // splitting procedure inner_box); // inner box if shrinking (returned) break; default: annError("Illegal shrinking rule", ANNabort); } return decomp; }
ANNkd_tree::ANNkd_tree( // construct from point array ANNpointArray pa, // point array (with at least n pts) int n, // number of points int dd, // dimension double *ss, // scaling coefficient int *tt, // topology of space int bs, // bucket size ANNsplitRule split) // splitting method { SkeletonTree(n, dd, bs); // set up the basic stuff pts = pa; // where the points are if (n == 0) return; // no points--no sweat Scale = new double [dim]; Topology = new int [dim]; TreeTopology = new int [dim]; TreeP3Topology = new int [dim]; for (int i = 0; i < dim; i++) { Scale[i] = ss[i]; Topology[i] = tt[i]; TreeTopology[i] = tt[i]; } for (int i = 0; i < dim; i++) { if (tt[i] != 3) TreeP3Topology[i] = 0; else { TreeP3Topology[i++] = 0; TreeP3Topology[i++] = 1; TreeP3Topology[i++] = 2; TreeP3Topology[i] = 3; } } ANNorthRect bnd_box(dd); // bounding box for points annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle // copy to tree structure bnd_box_lo = annCopyPt(dd, bnd_box.lo); bnd_box_hi = annCopyPt(dd, bnd_box.hi); switch (split) { // build by rule case ANN_KD_STD: // standard kd-splitting rule root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split); break; case ANN_KD_MIDPT: // midpoint split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split); break; case ANN_KD_FAIR: // fair split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split); break; case ANN_KD_SUGGEST: // best (in our opinion) case ANN_KD_SL_MIDPT: // sliding midpoint split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split); break; case ANN_KD_SL_FAIR: // sliding fair split root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split); break; default: annError("Illegal splitting method", ANNabort); } delete [] TreeTopology; delete [] TreeP3Topology; }