00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __UT_KDTree__
00030 #define __UT_KDTree__
00031
00032 #include "UT_API.h"
00033 #include <SYS/SYS_Math.h>
00034
00035 #include "UT_IntArray.h"
00036
00037 #include "UT_VectorTypes.h"
00038 class UT_BoundingBox;
00039 class ut_KDPQueue;
00040 class ut_KDSplit;
00041
00042
00043
00044 #define UT_KD_MAXDIM 254
00045
00046
00047 struct UT_KDQueryPt {
00048 UT_KDQueryPt(const float *p)
00049 { P = p; myData = 0; }
00050 UT_KDQueryPt(const float *p, const void *data)
00051 { P = p; myData = data; }
00052
00053 const float *P;
00054 const void *myData;
00055 };
00056
00057 class UT_API UT_KDTree
00058 {
00059 public:
00060
00061 typedef enum {
00062 UT_KD_MEDIAN,
00063 UT_KD_SAH,
00064 UT_KD_CENTROID
00065 } ut_KDBalancer;
00066
00067 public:
00068 UT_KDTree(int dim=3, size_t size=0)
00069 {
00070 myDim = dim;
00071 myList = 0;
00072 mySplits = 0;
00073 myMaxLeafNodes = 25;
00074 myRebalanceCount = 128;
00075 myBalancer = UT_KD_MEDIAN;
00076 myHasRadius = false;
00077 setEntries(size);
00078 }
00079 virtual ~UT_KDTree();
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 void setEntries(size_t size);
00090 size_t getEntries() const { return myFullEntries; }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 void growEntries(size_t amount);
00106 size_t getRebalanceCount() const
00107 {
00108 return myRebalanceCount;
00109 }
00110 void setRebalanceCount(size_t count);
00111
00112
00113
00114
00115
00116
00117
00118
00119 void setBalancer(ut_KDBalancer balance)
00120 {
00121 myBalancer = balance;
00122 }
00123
00124
00125 void setMaxLeafNodes(int max_leaf_nodes)
00126 {
00127 UT_ASSERT_P(max_leaf_nodes >= 3);
00128 myMaxLeafNodes = SYSmax(3, max_leaf_nodes);
00129 }
00130
00131
00132
00133 void flagDirty()
00134 {
00135
00136 setEntries(myFullEntries);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 virtual int comparePosition(int idx0,
00147 int idx1, int dim) const = 0;
00148
00149 virtual const float *getP(int idx) const = 0;
00150
00151
00152
00153
00154 virtual bool pointsHaveRadius() const { return false; }
00155
00156 virtual fpreal getRadius(int ) const { return 0; }
00157
00158
00159 virtual bool isValid(int ) const
00160 { return true; }
00161 virtual bool isValid(int idx, const UT_KDQueryPt & ) const
00162 { return isValid(idx); }
00163
00164
00165
00166
00167 virtual int getInvalidLimit(int maxn) const { return -1; }
00168
00169
00170
00171
00172 int findClosest(const UT_KDQueryPt &pt,
00173 fpreal max_distance);
00174 int findClosestQueue(const UT_KDQueryPt &pt,
00175 ut_KDPQueue &queue,
00176 fpreal max_distance);
00177
00178
00179
00180
00181 int findClosest(UT_IntArray &list,
00182 const UT_KDQueryPt &pt,
00183 fpreal max_distance,
00184 int max_nodes,
00185 bool sorted = true);
00186 int findClosestQueue(UT_IntArray &list,
00187 const UT_KDQueryPt &pt,
00188 ut_KDPQueue &q,
00189 fpreal max_distance,
00190 int max_nodes,
00191 bool sorted = true);
00192
00193
00194
00195
00196 int findClosest(UT_IntArray &list,
00197 UT_FloatArray &dist,
00198 const UT_KDQueryPt &pt,
00199 fpreal max_distance,
00200 int max_nodes,
00201 bool sorted = true);
00202 int findClosestQueue(UT_IntArray &list,
00203 UT_FloatArray &dist,
00204 const UT_KDQueryPt &pt,
00205 ut_KDPQueue &q,
00206 fpreal max_distance,
00207 int max_nodes,
00208 bool sorted = true);
00209
00210 int findNClosest(UT_IntArray &list,
00211 const UT_KDQueryPt &pt,
00212 int max_nodes)
00213 {
00214 return findClosest(list, pt, 1e37, max_nodes);
00215 }
00216 int findAllClosest(UT_IntArray &list,
00217 const UT_KDQueryPt &pt,
00218 fpreal max_distance)
00219 {
00220 return findClosest(list, pt, max_distance,
00221 myFullEntries, false);
00222 }
00223
00224
00225
00226 int findTubeClosest(const UT_Vector3 &orig,
00227 const UT_Vector3 &dir);
00228 int findTubeClosest(UT_IntArray &list,
00229 const UT_Vector3 &orig,
00230 const UT_Vector3 &dir,
00231 fpreal tube_radius,
00232 int max_nodes,
00233 bool sorted=true);
00234 int findTubeClosest(UT_IntArray &list,
00235 UT_FloatArray &dlist,
00236 const UT_Vector3 &orig,
00237 const UT_Vector3 &dir,
00238 fpreal tube_radius,
00239 int max_nodes,
00240 bool sorted=true);
00241
00242 int findTubeNClosest(UT_IntArray &list,
00243 const UT_Vector3 &orig,
00244 const UT_Vector3 &dir,
00245 int max_nodes)
00246 {
00247 return findTubeClosest(list, orig, dir,
00248 1e37, max_nodes);
00249 }
00250 int findTubeAllClosest(UT_IntArray &list,
00251 const UT_Vector3 &orig,
00252 const UT_Vector3 &dir,
00253 fpreal radius)
00254 {
00255 return findTubeClosest(list, orig, dir, radius,
00256 myFullEntries, false);
00257 }
00258
00259 const fpreal *getBoxMin();
00260 const fpreal *getBoxMax();
00261
00262
00263
00264
00265 static ut_KDPQueue *createQueue();
00266 static void destroyQueue(ut_KDPQueue *q);
00267
00268 protected:
00269 int findClosest(ut_KDPQueue &list, const UT_KDQueryPt &pt);
00270 int findTubeClosest(ut_KDPQueue &list,
00271 const UT_Vector3 &orig,
00272 const UT_Vector3 &dir);
00273
00274 void recurseFind(ut_KDPQueue &list, const UT_KDQueryPt &pt,
00275 ut_KDSplit *split, int lo, int hi) const;
00276 void recurseTubeFind(ut_KDPQueue &q,
00277 ut_KDSplit *split, int lo, int hi,
00278 const UT_Vector3 &orig,
00279 const UT_Vector3 &dir,
00280 UT_BoundingBox &box) const;
00281 bool isBalanced() const { return myBalanced; }
00282
00283 void computeBox(int start_index=0);
00284 bool isBoxClose(const fpreal *P, fpreal qd, fpreal r) const;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 void balance();
00296
00297 ut_KDSplit *balanceSet(fpreal &radius,
00298 int *list, int entries, int axis);
00299
00300
00301
00302
00303
00304 fpreal myBMin[UT_KD_MAXDIM];
00305 fpreal myBMax[UT_KD_MAXDIM];
00306
00307
00308
00309
00310
00311
00312 int *myList;
00313
00314
00315
00316 ut_KDSplit *mySplits;
00317
00318
00319 size_t myEntries;
00320
00321
00322
00323
00324 size_t myFullEntries;
00325 size_t myRebalanceCount;
00326 int myDim;
00327 int myMaxLeafNodes;
00328 bool myBalanced;
00329 bool myBoxComputed;
00330
00331
00332 bool myHasRadius;
00333 ut_KDBalancer myBalancer;
00334 };
00335
00336 #endif