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); } }
ANNkd_ptr rbd_tree( // recursive construction of bd-tree ANNpointArray pa, // point array ANNidxArray pidx, // point indices to store in subtree int n, // number of points int dim, // dimension of space int bsp, // bucket space ANNorthRect &bnd_box, // bounding box for current node ANNkd_splitter splitter, // splitting routine ANNshrinkRule shrink) // shrinking rule { ANNdecomp decomp; // decomposition method ANNorthRect inner_box(dim); // inner box (if shrinking) if (n <= bsp) { // n small, make a leaf node if (n == 0) // empty leaf node return KD_TRIVIAL; // return (canonical) empty leaf else // construct the node and return return new ANNkd_leaf(n, pidx); } decomp = selectDecomp( // select decomposition method pa, pidx, // points and indices n, dim, // number of points and dimension bnd_box, // current bounding box splitter, shrink, // splitting/shrinking methods inner_box); // inner box if shrinking (returned) if (decomp == SPLIT) { // split selected int cd; // cutting dimension ANNcoord cv; // cutting value int n_lo; // number on low side of cut // invoke splitting procedure (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo); ANNcoord lv = bnd_box.lo[cd]; // save bounds for cutting dimension ANNcoord hv = bnd_box.hi[cd]; bnd_box.hi[cd] = cv; // modify bounds for left subtree ANNkd_ptr lo = rbd_tree( // build left subtree pa, pidx, n_lo, // ...from pidx[0..n_lo-1] dim, bsp, bnd_box, splitter, shrink); bnd_box.hi[cd] = hv; // restore bounds bnd_box.lo[cd] = cv; // modify bounds for right subtree ANNkd_ptr hi = rbd_tree( // build right subtree pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1] dim, bsp, bnd_box, splitter, shrink); bnd_box.lo[cd] = lv; // restore bounds // create the splitting node return new ANNkd_split(cd, cv, lv, hv, lo, hi); } else { // shrink selected int n_in; // number of points in box int n_bnds; // number of bounding sides annBoxSplit( // split points around inner box pa, // points to split pidx, // point indices n, // number of points dim, // dimension inner_box, // inner box n_in); // number of points inside (returned) ANNkd_ptr in = rbd_tree( // build inner subtree pidx[0..n_in-1] pa, pidx, n_in, dim, bsp, inner_box, splitter, shrink); ANNkd_ptr out = rbd_tree( // build outer subtree pidx[n_in..n] pa, pidx+n_in, n - n_in, dim, bsp, bnd_box, splitter, shrink); ANNorthHSArray bnds = NULL; // bounds (alloc in Box2Bnds and // ...freed in bd_shrink destroyer) annBox2Bnds( // convert inner box to bounds inner_box, // inner box bnd_box, // enclosing box dim, // dimension n_bnds, // number of bounds (returned) bnds); // bounds array (modified) // return shrinking node return new ANNbd_shrink(n_bnds, bnds, in, out); } }