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 class UT_Vector3;
00038 class UT_BoundingBox;
00039 class UT_FloatArray;
00040 class ut_KDPQueue;
00041 class ut_KDSplit;
00042
00043
00044
00045 #define UT_KD_MAXDIM 254
00046
00047
00048 struct UT_KDQueryPt {
00049 UT_KDQueryPt(const float *p)
00050 { P = p; myData = 0; }
00051 UT_KDQueryPt(const float *p, const void *data)
00052 { P = p; myData = data; }
00053
00054 const float *P;
00055 const void *myData;
00056 };
00057
00058 class UT_API UT_KDTree
00059 {
00060 public:
00061
00062 typedef enum {
00063 UT_KD_MEDIAN,
00064 UT_KD_SAH
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 void setBalancer(ut_KDBalancer balance)
00116 {
00117 myBalancer = balance;
00118 }
00119
00120
00121 void setMaxLeafNodes(int max_leaf_nodes)
00122 {
00123 UT_ASSERT_P(max_leaf_nodes >= 3);
00124 myMaxLeafNodes = SYSmax(3, max_leaf_nodes);
00125 }
00126
00127
00128
00129 void flagDirty()
00130 {
00131
00132 setEntries(myFullEntries);
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142 virtual int comparePosition(int idx0,
00143 int idx1, int dim) const = 0;
00144
00145 virtual const fpreal *getP(int idx) const = 0;
00146
00147
00148
00149
00150 virtual bool pointsHaveRadius() const { return false; }
00151
00152 virtual fpreal getRadius(int ) const { return 0; }
00153
00154
00155 virtual bool isValid(int ) const
00156 { return true; }
00157 virtual bool isValid(int idx, const UT_KDQueryPt & ) const
00158 { return isValid(idx); }
00159
00160
00161
00162
00163 int findClosest(const UT_KDQueryPt &pt,
00164 fpreal max_distance);
00165
00166
00167 int findClosestQueue(const UT_KDQueryPt &pt,
00168 ut_KDPQueue &queue);
00169
00170
00171
00172
00173 int findClosest(UT_IntArray &list,
00174 const UT_KDQueryPt &pt,
00175 fpreal max_distance,
00176 int max_nodes,
00177 bool sorted = true);
00178
00179
00180 int findClosestQueue(UT_IntArray &list,
00181 ut_KDPQueue &q,
00182 const UT_KDQueryPt &pt);
00183
00184
00185
00186
00187 int findClosest(UT_IntArray &list,
00188 UT_FloatArray &dist,
00189 const UT_KDQueryPt &pt,
00190 fpreal max_distance,
00191 int max_nodes,
00192 bool sorted = true);
00193
00194 int findNClosest(UT_IntArray &list,
00195 const UT_KDQueryPt &pt,
00196 int max_nodes)
00197 {
00198 return findClosest(list, pt, 1e37, max_nodes);
00199 }
00200 int findAllClosest(UT_IntArray &list,
00201 const UT_KDQueryPt &pt,
00202 fpreal max_distance)
00203 {
00204 return findClosest(list, pt, max_distance,
00205 myFullEntries, false);
00206 }
00207
00208
00209
00210 int findTubeClosest(const UT_Vector3 &orig,
00211 const UT_Vector3 &dir);
00212 int findTubeClosest(UT_IntArray &list,
00213 const UT_Vector3 &orig,
00214 const UT_Vector3 &dir,
00215 fpreal tube_radius,
00216 int max_nodes,
00217 bool sorted=true);
00218 int findTubeClosest(UT_IntArray &list,
00219 UT_FloatArray &dlist,
00220 const UT_Vector3 &orig,
00221 const UT_Vector3 &dir,
00222 fpreal tube_radius,
00223 int max_nodes,
00224 bool sorted=true);
00225
00226 int findTubeNClosest(UT_IntArray &list,
00227 const UT_Vector3 &orig,
00228 const UT_Vector3 &dir,
00229 int max_nodes)
00230 {
00231 return findTubeClosest(list, orig, dir,
00232 1e37, max_nodes);
00233 }
00234 int findTubeAllClosest(UT_IntArray &list,
00235 const UT_Vector3 &orig,
00236 const UT_Vector3 &dir,
00237 fpreal radius)
00238 {
00239 return findTubeClosest(list, orig, dir, radius,
00240 myFullEntries, false);
00241 }
00242
00243 const fpreal *getBoxMin();
00244 const fpreal *getBoxMax();
00245
00246
00247
00248
00249 static ut_KDPQueue *createQueue(fpreal max_dist,
00250 int max_nodes,
00251 bool sorted);
00252 static void destroyQueue(ut_KDPQueue *q);
00253
00254 protected:
00255 int findClosest(ut_KDPQueue &list, const UT_KDQueryPt &pt);
00256 int findTubeClosest(ut_KDPQueue &list,
00257 const UT_Vector3 &orig,
00258 const UT_Vector3 &dir);
00259
00260 void recurseFind(ut_KDPQueue &list, const UT_KDQueryPt &pt,
00261 ut_KDSplit *split, int lo, int hi) const;
00262 void recurseTubeFind(ut_KDPQueue &q,
00263 ut_KDSplit *split, int lo, int hi,
00264 const UT_Vector3 &orig,
00265 const UT_Vector3 &dir,
00266 UT_BoundingBox &box) const;
00267 bool isBalanced() const { return myBalanced; }
00268
00269 void computeBox(int start_index=0);
00270 bool isBoxClose(const fpreal *P, fpreal qd, fpreal r) const;
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 void balance();
00282
00283 ut_KDSplit *balanceSet(fpreal &radius,
00284 int *list, int entries, int axis);
00285
00286
00287
00288
00289
00290 fpreal myBMin[UT_KD_MAXDIM];
00291 fpreal myBMax[UT_KD_MAXDIM];
00292
00293
00294
00295
00296
00297
00298 int *myList;
00299
00300
00301
00302 ut_KDSplit *mySplits;
00303
00304
00305 size_t myEntries;
00306
00307
00308
00309
00310 size_t myFullEntries;
00311 size_t myRebalanceCount;
00312 int myDim;
00313 int myMaxLeafNodes;
00314 bool myBalanced;
00315 bool myBoxComputed;
00316
00317
00318 bool myHasRadius;
00319 ut_KDBalancer myBalancer;
00320 };
00321
00322 #endif