source: proiecte/pmake3d/make3d_original/Make3dSingleImageStanford_version0.1/third_party/ann_1.1.1/src/kd_tree.cpp @ 37

Last change on this file since 37 was 37, checked in by (none), 14 years ago

Added original make3d

File size: 14.9 KB
Line 
1//----------------------------------------------------------------------
2// File:                        kd_tree.cpp
3// Programmer:          Sunil Arya and David Mount
4// Description:         Basic methods for kd-trees.
5// Last modified:       01/04/05 (Version 1.0)
6//----------------------------------------------------------------------
7// Copyright (c) 1997-2005 University of Maryland and Sunil Arya and
8// David Mount.  All Rights Reserved.
9//
10// This software and related documentation is part of the Approximate
11// Nearest Neighbor Library (ANN).  This software is provided under
12// the provisions of the Lesser GNU Public License (LGPL).  See the
13// file ../ReadMe.txt for further information.
14//
15// The University of Maryland (U.M.) and the authors make no
16// representations about the suitability or fitness of this software for
17// any purpose.  It is provided "as is" without express or implied
18// warranty.
19//----------------------------------------------------------------------
20// History:
21//      Revision 0.1  03/04/98
22//              Initial release
23//      Revision 1.0  04/01/05
24//              Increased aspect ratio bound (ANN_AR_TOOBIG) from 100 to 1000.
25//              Fixed leaf counts to count trivial leaves.
26//              Added optional pa, pi arguments to Skeleton kd_tree constructor
27//                      for use in load constructor.
28//              Added annClose() to eliminate KD_TRIVIAL memory leak.
29//----------------------------------------------------------------------
30
31#include "kd_tree.h"                                    // kd-tree declarations
32#include "kd_split.h"                                   // kd-tree splitting rules
33#include "kd_util.h"                                    // kd-tree utilities
34#include <ANN/ANNperf.h>                                // performance evaluation
35
36//----------------------------------------------------------------------
37//      Global data
38//
39//      For some splitting rules, especially with small bucket sizes,
40//      it is possible to generate a large number of empty leaf nodes.
41//      To save storage we allocate a single trivial leaf node which
42//      contains no points.  For messy coding reasons it is convenient
43//      to have it reference a trivial point index.
44//
45//      KD_TRIVIAL is allocated when the first kd-tree is created.  It
46//      must *never* deallocated (since it may be shared by more than
47//      one tree).
48//----------------------------------------------------------------------
49static int                              IDX_TRIVIAL[] = {0};    // trivial point index
50ANNkd_leaf                              *KD_TRIVIAL = NULL;             // trivial leaf node
51
52//----------------------------------------------------------------------
53//      Printing the kd-tree
54//              These routines print a kd-tree in reverse inorder (high then
55//              root then low).  (This is so that if you look at the output
56//              from the right side it appear from left to right in standard
57//              inorder.)  When outputting leaves we output only the point
58//              indices rather than the point coordinates. There is an option
59//              to print the point coordinates separately.
60//
61//              The tree printing routine calls the printing routines on the
62//              individual nodes of the tree, passing in the level or depth
63//              in the tree.  The level in the tree is used to print indentation
64//              for readability.
65//----------------------------------------------------------------------
66
67void ANNkd_split::print(                                // print splitting node
68                int level,                                              // depth of node in tree
69                ostream &out)                                   // output stream
70{
71        child[ANN_HI]->print(level+1, out);     // print high child
72        out << "    ";
73        for (int i = 0; i < level; i++)         // print indentation
74                out << "..";
75        out << "Split cd=" << cut_dim << " cv=" << cut_val;
76        out << " lbnd=" << cd_bnds[ANN_LO];
77        out << " hbnd=" << cd_bnds[ANN_HI];
78        out << "\n";
79        child[ANN_LO]->print(level+1, out);     // print low child
80}
81
82void ANNkd_leaf::print(                                 // print leaf node
83                int level,                                              // depth of node in tree
84                ostream &out)                                   // output stream
85{
86
87        out << "    ";
88        for (int i = 0; i < level; i++)         // print indentation
89                out << "..";
90
91        if (this == KD_TRIVIAL) {                       // canonical trivial leaf node
92                out << "Leaf (trivial)\n";
93        }
94        else{
95                out << "Leaf n=" << n_pts << " <";
96                for (int j = 0; j < n_pts; j++) {
97                        out << bkt[j];
98                        if (j < n_pts-1) out << ",";
99                }
100                out << ">\n";
101        }
102}
103
104void ANNkd_tree::Print(                                 // print entire tree
105                ANNbool with_pts,                               // print points as well?
106                ostream &out)                                   // output stream
107{
108        out << "ANN Version " << ANNversion << "\n";
109        if (with_pts) {                                         // print point coordinates
110                out << "    Points:\n";
111                for (int i = 0; i < n_pts; i++) {
112                        out << "\t" << i << ": ";
113                        annPrintPt(pts[i], dim, out);
114                        out << "\n";
115                }
116        }
117        if (root == NULL)                                       // empty tree?
118                out << "    Null tree.\n";
119        else {
120                root->print(0, out);                    // invoke printing at root
121        }
122}
123
124//----------------------------------------------------------------------
125//      kd_tree statistics (for performance evaluation)
126//              This routine compute various statistics information for
127//              a kd-tree.  It is used by the implementors for performance
128//              evaluation of the data structure.
129//----------------------------------------------------------------------
130
131#define MAX(a,b)                ((a) > (b) ? (a) : (b))
132
133void ANNkdStats::merge(const ANNkdStats &st)    // merge stats from child
134{
135        n_lf += st.n_lf;                        n_tl += st.n_tl;
136        n_spl += st.n_spl;                      n_shr += st.n_shr;
137        depth = MAX(depth, st.depth);
138        sum_ar += st.sum_ar;
139}
140
141//----------------------------------------------------------------------
142//      Update statistics for nodes
143//----------------------------------------------------------------------
144
145const double ANN_AR_TOOBIG = 1000;                              // too big an aspect ratio
146
147void ANNkd_leaf::getStats(                                              // get subtree statistics
148        int                                     dim,                                    // dimension of space
149        ANNkdStats                      &st,                                    // stats (modified)
150        ANNorthRect                     &bnd_box)                               // bounding box
151{
152        st.reset();
153        st.n_lf = 1;                                                            // count this leaf
154        if (this == KD_TRIVIAL) st.n_tl = 1;            // count trivial leaf
155        double ar = annAspectRatio(dim, bnd_box);       // aspect ratio of leaf
156                                                                                                // incr sum (ignore outliers)
157        st.sum_ar += float(ar < ANN_AR_TOOBIG ? ar : ANN_AR_TOOBIG);
158}
159
160void ANNkd_split::getStats(                                             // get subtree statistics
161        int                                     dim,                                    // dimension of space
162        ANNkdStats                      &st,                                    // stats (modified)
163        ANNorthRect                     &bnd_box)                               // bounding box
164{
165        ANNkdStats ch_stats;                                            // stats for children
166                                                                                                // get stats for low child
167        ANNcoord hv = bnd_box.hi[cut_dim];                      // save box bounds
168        bnd_box.hi[cut_dim] = cut_val;                          // upper bound for low child
169        ch_stats.reset();                                                       // reset
170        child[ANN_LO]->getStats(dim, ch_stats, bnd_box);
171        st.merge(ch_stats);                                                     // merge them
172        bnd_box.hi[cut_dim] = hv;                                       // restore bound
173                                                                                                // get stats for high child
174        ANNcoord lv = bnd_box.lo[cut_dim];                      // save box bounds
175        bnd_box.lo[cut_dim] = cut_val;                          // lower bound for high child
176        ch_stats.reset();                                                       // reset
177        child[ANN_HI]->getStats(dim, ch_stats, bnd_box);
178        st.merge(ch_stats);                                                     // merge them
179        bnd_box.lo[cut_dim] = lv;                                       // restore bound
180
181        st.depth++;                                                                     // increment depth
182        st.n_spl++;                                                                     // increment number of splits
183}
184
185//----------------------------------------------------------------------
186//      getStats
187//              Collects a number of statistics related to kd_tree or
188//              bd_tree.
189//----------------------------------------------------------------------
190
191void ANNkd_tree::getStats(                                              // get tree statistics
192        ANNkdStats                      &st)                                    // stats (modified)
193{
194        st.reset(dim, n_pts, bkt_size);                         // reset stats
195                                                                                                // create bounding box
196        ANNorthRect bnd_box(dim, bnd_box_lo, bnd_box_hi);
197        if (root != NULL) {                                                     // if nonempty tree
198                root->getStats(dim, st, bnd_box);               // get statistics
199                st.avg_ar = st.sum_ar / st.n_lf;                // average leaf asp ratio
200        }
201}
202
203//----------------------------------------------------------------------
204//      kd_tree destructor
205//              The destructor just frees the various elements that were
206//              allocated in the construction process.
207//----------------------------------------------------------------------
208
209ANNkd_tree::~ANNkd_tree()                               // tree destructor
210{
211        if (root != NULL) delete root;
212        if (pidx != NULL) delete [] pidx;
213        if (bnd_box_lo != NULL) annDeallocPt(bnd_box_lo);
214        if (bnd_box_hi != NULL) annDeallocPt(bnd_box_hi);
215}
216
217//----------------------------------------------------------------------
218//      This is called with all use of ANN is finished.  It eliminates the
219//      minor memory leak caused by the allocation of KD_TRIVIAL.
220//----------------------------------------------------------------------
221void annClose()                         // close use of ANN
222{
223        if (KD_TRIVIAL != NULL) {
224                delete KD_TRIVIAL;
225                KD_TRIVIAL = NULL;
226        }
227}
228
229//----------------------------------------------------------------------
230//      kd_tree constructors
231//              There is a skeleton kd-tree constructor which sets up a
232//              trivial empty tree.      The last optional argument allows
233//              the routine to be passed a point index array which is
234//              assumed to be of the proper size (n).  Otherwise, one is
235//              allocated and initialized to the identity.      Warning: In
236//              either case the destructor will deallocate this array.
237//
238//              As a kludge, we need to allocate KD_TRIVIAL if one has not
239//              already been allocated.  (This is because I'm too dumb to
240//              figure out how to cause a pointer to be allocated at load
241//              time.)
242//----------------------------------------------------------------------
243
244void ANNkd_tree::SkeletonTree(                  // construct skeleton tree
245                int n,                                                  // number of points
246                int dd,                                                 // dimension
247                int bs,                                                 // bucket size
248                ANNpointArray pa,                               // point array
249                ANNidxArray pi)                                 // point indices
250{
251        dim = dd;                                                       // initialize basic elements
252        n_pts = n;
253        bkt_size = bs;
254        pts = pa;                                                       // initialize points array
255
256        root = NULL;                                            // no associated tree yet
257
258        if (pi == NULL) {                                       // point indices provided?
259                pidx = new ANNidx[n];                   // no, allocate space for point indices
260                for (int i = 0; i < n; i++) {
261                        pidx[i] = i;                            // initially identity
262                }
263        }
264        else {
265                pidx = pi;                                              // yes, use them
266        }
267
268        bnd_box_lo = bnd_box_hi = NULL;         // bounding box is nonexistent
269        if (KD_TRIVIAL == NULL)                         // no trivial leaf node yet?
270                KD_TRIVIAL = new ANNkd_leaf(0, IDX_TRIVIAL);    // allocate it
271}
272
273ANNkd_tree::ANNkd_tree(                                 // basic constructor
274                int n,                                                  // number of points
275                int dd,                                                 // dimension
276                int bs)                                                 // bucket size
277{  SkeletonTree(n, dd, bs);  }                  // construct skeleton tree
278
279//----------------------------------------------------------------------
280//      rkd_tree - recursive procedure to build a kd-tree
281//
282//              Builds a kd-tree for points in pa as indexed through the
283//              array pidx[0..n-1] (typically a subarray of the array used in
284//              the top-level call).  This routine permutes the array pidx,
285//              but does not alter pa[].
286//
287//              The construction is based on a standard algorithm for constructing
288//              the kd-tree (see Friedman, Bentley, and Finkel, ``An algorithm for
289//              finding best matches in logarithmic expected time,'' ACM Transactions
290//              on Mathematical Software, 3(3):209-226, 1977).  The procedure
291//              operates by a simple divide-and-conquer strategy, which determines
292//              an appropriate orthogonal cutting plane (see below), and splits
293//              the points.  When the number of points falls below the bucket size,
294//              we simply store the points in a leaf node's bucket.
295//
296//              One of the arguments is a pointer to a splitting routine,
297//              whose prototype is:
298//             
299//                              void split(
300//                                              ANNpointArray pa,  // complete point array
301//                                              ANNidxArray pidx,  // point array (permuted on return)
302//                                              ANNorthRect &bnds, // bounds of current cell
303//                                              int n,                     // number of points
304//                                              int dim,                   // dimension of space
305//                                              int &cut_dim,      // cutting dimension
306//                                              ANNcoord &cut_val, // cutting value
307//                                              int &n_lo)                 // no. of points on low side of cut
308//
309//              This procedure selects a cutting dimension and cutting value,
310//              partitions pa about these values, and returns the number of
311//              points on the low side of the cut.
312//----------------------------------------------------------------------
313
314ANNkd_ptr rkd_tree(                             // recursive construction of kd-tree
315        ANNpointArray           pa,                             // point array
316        ANNidxArray                     pidx,                   // point indices to store in subtree
317        int                                     n,                              // number of points
318        int                                     dim,                    // dimension of space
319        int                                     bsp,                    // bucket space
320        ANNorthRect                     &bnd_box,               // bounding box for current node
321        ANNkd_splitter          splitter)               // splitting routine
322{
323        if (n <= bsp) {                                         // n small, make a leaf node
324                if (n == 0)                                             // empty leaf node
325                        return KD_TRIVIAL;                      // return (canonical) empty leaf
326                else                                                    // construct the node and return
327                        return new ANNkd_leaf(n, pidx); 
328        }
329        else {                                                          // n large, make a splitting node
330                int cd;                                                 // cutting dimension
331                ANNcoord cv;                                    // cutting value
332                int n_lo;                                               // number on low side of cut
333                ANNkd_node *lo, *hi;                    // low and high children
334
335                                                                                // invoke splitting procedure
336                (*splitter)(pa, pidx, bnd_box, n, dim, cd, cv, n_lo);
337
338                ANNcoord lv = bnd_box.lo[cd];   // save bounds for cutting dimension
339                ANNcoord hv = bnd_box.hi[cd];
340
341                bnd_box.hi[cd] = cv;                    // modify bounds for left subtree
342                lo = rkd_tree(                                  // build left subtree
343                                pa, pidx, n_lo,                 // ...from pidx[0..n_lo-1]
344                                dim, bsp, bnd_box, splitter);
345                bnd_box.hi[cd] = hv;                    // restore bounds
346
347                bnd_box.lo[cd] = cv;                    // modify bounds for right subtree
348                hi = rkd_tree(                                  // build right subtree
349                                pa, pidx + n_lo, n-n_lo,// ...from pidx[n_lo..n-1]
350                                dim, bsp, bnd_box, splitter);
351                bnd_box.lo[cd] = lv;                    // restore bounds
352
353                                                                                // create the splitting node
354                ANNkd_split *ptr = new ANNkd_split(cd, cv, lv, hv, lo, hi);
355
356                return ptr;                                             // return pointer to this node
357        }
358} 
359
360//----------------------------------------------------------------------
361// kd-tree constructor
362//              This is the main constructor for kd-trees given a set of points.
363//              It first builds a skeleton tree, then computes the bounding box
364//              of the data points, and then invokes rkd_tree() to actually
365//              build the tree, passing it the appropriate splitting routine.
366//----------------------------------------------------------------------
367
368ANNkd_tree::ANNkd_tree(                                 // construct from point array
369        ANNpointArray           pa,                             // point array (with at least n pts)
370        int                                     n,                              // number of points
371        int                                     dd,                             // dimension
372        int                                     bs,                             // bucket size
373        ANNsplitRule            split)                  // splitting method
374{
375        SkeletonTree(n, dd, bs);                        // set up the basic stuff
376        pts = pa;                                                       // where the points are
377        if (n == 0) return;                                     // no points--no sweat
378
379        ANNorthRect bnd_box(dd);                        // bounding box for points
380        annEnclRect(pa, pidx, n, dd, bnd_box);// construct bounding rectangle
381                                                                                // copy to tree structure
382        bnd_box_lo = annCopyPt(dd, bnd_box.lo);
383        bnd_box_hi = annCopyPt(dd, bnd_box.hi);
384
385        switch (split) {                                        // build by rule
386        case ANN_KD_STD:                                        // standard kd-splitting rule
387                root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, kd_split);
388                break;
389        case ANN_KD_MIDPT:                                      // midpoint split
390                root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, midpt_split);
391                break;
392        case ANN_KD_FAIR:                                       // fair split
393                root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, fair_split);
394                break;
395        case ANN_KD_SUGGEST:                            // best (in our opinion)
396        case ANN_KD_SL_MIDPT:                           // sliding midpoint split
397                root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_midpt_split);
398                break;
399        case ANN_KD_SL_FAIR:                            // sliding fair split
400                root = rkd_tree(pa, pidx, n, dd, bs, bnd_box, sl_fair_split);
401                break;
402        default:
403                annError("Illegal splitting method", ANNabort);
404        }
405}
Note: See TracBrowser for help on using the repository browser.