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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_IMPL_QUAD_TREE_HELPER_H
00066 #define LASS_GUARDIAN_OF_INCLUSION_SPAT_IMPL_QUAD_TREE_HELPER_H
00067
00068 #include "../spat_common.h"
00069
00070 namespace lass
00071 {
00072 namespace spat
00073 {
00074 namespace impl
00075 {
00076
00077 template <typename ObjectTraits, size_t dimension>
00078 class QuadTreeHelper
00079 {
00080 protected:
00081 typedef ObjectTraits TObjectTraits;
00082 typedef typename ObjectTraits::TPoint TPoint;
00083 typedef typename ObjectTraits::TVector TVector;
00084 typedef typename ObjectTraits::TValue TValue;
00085
00086 const TValue minComponent(const TVector& v) const
00087 {
00088 TValue best = TObjectTraits::coord(v, 0);
00089 for (size_t k = 1; k < dimension; ++k)
00090 {
00091 best = std::min(best, TObjectTraits::coord(v, k));
00092 }
00093 return best;
00094 }
00095
00096 const TValue maxComponent(const TVector& v) const
00097 {
00098 TValue best = TObjectTraits::coord(v, 0);
00099 for (size_t k = 1; k < dimension; ++k)
00100 {
00101 best = std::max(best, TObjectTraits::coord(v, k));
00102 }
00103 return best;
00104 }
00105
00106 template <typename V>
00107 const V middle(const V& a, const V& b) const
00108 {
00109 V result;
00110 for (size_t k = 0; k < dimension; ++k)
00111 {
00112 TObjectTraits::coord(result, k, (TObjectTraits::coord(a, k) + TObjectTraits::coord(b, k)) / 2);
00113 }
00114 return result;
00115 }
00116
00117 const TVector subtract(const TPoint& a, const TPoint& b) const
00118 {
00119 TVector result;
00120 for (size_t k = 0; k < dimension; ++k)
00121 {
00122 TObjectTraits::coord(result, k, TObjectTraits::coord(a, k) - TObjectTraits::coord(b, k));
00123 }
00124 return result;
00125 }
00126
00127 const size_t entryNode(const TVector& tNear, const TVector& tMiddle) const
00128 {
00129 const TValue tEntry = maxComponent(tNear);
00130 size_t iEntry = 0;
00131 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00132 {
00133 iEntry |= (TObjectTraits::coord(tMiddle, k) < tEntry) ? mask : 0;
00134 }
00135 return iEntry;
00136 }
00137
00138 const size_t nextNode(size_t i, const TVector& tFar) const
00139 {
00140 size_t nextMask = 1;
00141 TValue min = TObjectTraits::coord(tFar, 0);
00142 for (size_t k = 1, mask = 2; k < dimension; ++k, mask *= 2)
00143 {
00144 const TValue x = TObjectTraits::coord(tFar, k);
00145 if (x < min)
00146 {
00147 min = x;
00148 nextMask = mask;
00149 }
00150 }
00151 if (i & nextMask)
00152 {
00153 return size_t(-1);
00154 }
00155 return i | nextMask;
00156 }
00157
00158 const size_t findSubNode(const TPoint& center, const TPoint& point) const
00159 {
00160 size_t i = 0;
00161 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00162 {
00163 i |= TObjectTraits::coord(point, k) >= TObjectTraits::coord(center, k) ? mask : 0;
00164 }
00165 return i;
00166 }
00167
00168 const size_t forcePositiveDirection(const TPoint& center, TPoint& support, TVector& direction) const
00169 {
00170 size_t flipMask = 0;
00171 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00172 {
00173 const TValue d = TObjectTraits::coord(direction, k);
00174 if (d < 0)
00175 {
00176 TObjectTraits::coord(support, k,
00177 2 * TObjectTraits::coord(center, k) - TObjectTraits::coord(support, k));
00178 TObjectTraits::coord(direction, k, -d);
00179 flipMask |= mask;
00180 }
00181 }
00182 return flipMask;
00183 }
00184
00185 void nearAndFar(const TPoint& min, const TPoint& max, const TPoint& support,
00186 const TVector& reciprocalDirection, TVector& tNear, TVector& tFar) const
00187 {
00188 for (size_t k = 0; k < dimension; ++k)
00189 {
00190 TObjectTraits::coord(tNear, k, TObjectTraits::coord(reciprocalDirection, k) *
00191 (TObjectTraits::coord(min, k) - TObjectTraits::coord(support, k)));
00192 TObjectTraits::coord(tFar, k, TObjectTraits::coord(reciprocalDirection, k) *
00193 (TObjectTraits::coord(max, k) - TObjectTraits::coord(support, k)));
00194 }
00195 }
00196
00197 void childNearAndFar(TVector& tNear, TVector& tFar, const TVector& tMiddle, size_t iChild) const
00198 {
00199 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00200 {
00201 if (iChild & mask)
00202 {
00203 TObjectTraits::coord(tNear, k, TObjectTraits::coord(tMiddle, k));
00204 }
00205 else
00206 {
00207 TObjectTraits::coord(tFar, k, TObjectTraits::coord(tMiddle, k));
00208 }
00209 }
00210 }
00211
00212 template <typename QuadNodeType>
00213 static void buildSubNodes(QuadNodeType* parentNode)
00214 {
00215 TVector newExtents(parentNode->extents);
00216 for (size_t k = 0; k < dimension; ++k)
00217 {
00218 TObjectTraits::coord(newExtents, k, TObjectTraits::coord(newExtents, k) / 2);
00219 }
00220
00221 const size_t nodeCount = 1 << dimension;
00222 for (size_t i = 0; i < nodeCount; ++i)
00223 {
00224 TPoint newCenter = parentNode->center;
00225 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00226 {
00227 TObjectTraits::coord(newCenter, k,
00228 TObjectTraits::coord(newCenter, k) + (i & mask ? 1 : -1) * TObjectTraits::coord(newExtents, k));
00229 }
00230 parentNode->node[i] = new QuadNodeType(newCenter, newExtents);
00231 }
00232 }
00233 };
00234
00235
00236
00237 template <typename ObjectTraits>
00238 class QuadTreeHelper<ObjectTraits, 2>
00239 {
00240 protected:
00241 typedef ObjectTraits TObjectTraits;
00242 typedef typename ObjectTraits::TPoint TPoint;
00243 typedef typename ObjectTraits::TVector TVector;
00244 typedef typename ObjectTraits::TValue TValue;
00245 enum { dimension = 2 };
00246
00247 const TValue minComponent(const TVector& v) const
00248 {
00249 return std::min(TObjectTraits::coord(v, 0), TObjectTraits::coord(v, 1));
00250 }
00251
00252 const TValue maxComponent(const TVector& v) const
00253 {
00254 return std::max(TObjectTraits::coord(v, 0), TObjectTraits::coord(v, 1));
00255 }
00256
00257 template <typename V>
00258 const V middle(const V& a, const V& b) const
00259 {
00260 return V(
00261 (TObjectTraits::coord(a, 0) + TObjectTraits::coord(b, 0)) / 2,
00262 (TObjectTraits::coord(a, 1) + TObjectTraits::coord(b, 1)) / 2);
00263 }
00264
00265 const TVector subtract(const TPoint& a, const TPoint& b) const
00266 {
00267 return TVector(
00268 TObjectTraits::coord(a, 0) - TObjectTraits::coord(b, 0),
00269 TObjectTraits::coord(a, 1) - TObjectTraits::coord(b, 1));
00270 }
00271
00272 const size_t entryNode(const TVector& tNear, const TVector& tMiddle) const
00273 {
00274 if (TObjectTraits::coord(tNear, 0) > TObjectTraits::coord(tNear, 1))
00275 {
00276 if (TObjectTraits::coord(tMiddle, 1) < TObjectTraits::coord(tNear, 0))
00277 {
00278 return 0x2;
00279 }
00280 }
00281 else
00282 {
00283 if (TObjectTraits::coord(tMiddle, 0) < TObjectTraits::coord(tNear, 1))
00284 {
00285 return 0x1;
00286 }
00287 }
00288 return 0x0;
00289 }
00290
00291 const size_t nextNode(size_t i, const TVector& tFar) const
00292 {
00293 if (TObjectTraits::coord(tFar, 0) < TObjectTraits::coord(tFar, 1))
00294 {
00295 return i & 0x1 ? size_t(-1) : i | 0x1;
00296 }
00297 else
00298 {
00299 return i & 0x2 ? size_t(-1) : i | 0x2;
00300 }
00301 }
00302
00303 const size_t findSubNode(const TPoint& center, const TPoint& point) const
00304 {
00305 return (TObjectTraits::coord(point, 0) >= TObjectTraits::coord(center, 0) ? 0x1 : 0x0)
00306 | (TObjectTraits::coord(point, 1) >= TObjectTraits::coord(center, 1) ? 0x2 : 0x0);
00307 }
00308
00309 const size_t forcePositiveDirection(const TPoint& center, TPoint& support, TVector& direction) const
00310 {
00311 size_t flipMask = 0;
00312 const TValue dx = TObjectTraits::coord(direction, 0);
00313 if (dx < 0)
00314 {
00315 TObjectTraits::coord(support, 0, 2 * TObjectTraits::coord(center, 0) - TObjectTraits::coord(support, 0));
00316 TObjectTraits::coord(direction, 0, -dx);
00317 flipMask |= 0x1;
00318 }
00319 const TValue dy = TObjectTraits::coord(direction, 1);
00320 if (dy < 0)
00321 {
00322 TObjectTraits::coord(support, 1, 2 * TObjectTraits::coord(center, 1) - TObjectTraits::coord(support, 1));
00323 TObjectTraits::coord(direction, 1, -dy);
00324 flipMask |= 0x2;
00325 }
00326 return flipMask;
00327 }
00328
00329 void nearAndFar(const TPoint& min, const TPoint& max, const TPoint& support,
00330 const TVector& reciprocalDirection, TVector& tNear, TVector& tFar) const
00331 {
00332 TObjectTraits::coord(tNear, 0, TObjectTraits::coord(reciprocalDirection, 0) * (TObjectTraits::coord(min, 0) - TObjectTraits::coord(support, 0)));
00333 TObjectTraits::coord(tNear, 1, TObjectTraits::coord(reciprocalDirection, 1) * (TObjectTraits::coord(min, 1) - TObjectTraits::coord(support, 1)));
00334 TObjectTraits::coord(tFar, 0, TObjectTraits::coord(reciprocalDirection, 0) * (TObjectTraits::coord(max, 0) - TObjectTraits::coord(support, 0)));
00335 TObjectTraits::coord(tFar, 1, TObjectTraits::coord(reciprocalDirection, 1) * (TObjectTraits::coord(max, 1) - TObjectTraits::coord(support, 1)));
00336 }
00337
00338 void childNearAndFar(TVector& tNear, TVector& tFar, const TVector& tMiddle, size_t iChild) const
00339 {
00340 TObjectTraits::coord(iChild & 0x1 ? tNear : tFar, 0, TObjectTraits::coord(tMiddle, 0));
00341 TObjectTraits::coord(iChild & 0x2 ? tNear : tFar, 1, TObjectTraits::coord(tMiddle, 1));
00342 }
00343
00344 template <typename QuadNodeType>
00345 static void buildSubNodes(QuadNodeType* parentNode)
00346 {
00347 TVector newExtents(parentNode->extents);
00348 TObjectTraits::coord(newExtents, 0, TObjectTraits::coord(newExtents, 0) / 2);
00349 TObjectTraits::coord(newExtents, 1, TObjectTraits::coord(newExtents, 1) / 2);
00350
00351 for (size_t i = 0; i < 4; ++i)
00352 {
00353 TPoint newCenter = parentNode->center;
00354 TObjectTraits::coord(newCenter, 0,
00355 TObjectTraits::coord(newCenter, 0) + (i & 0x1 ? 1 : -1) * TObjectTraits::coord(newExtents, 0));
00356 TObjectTraits::coord(newCenter, 1,
00357 TObjectTraits::coord(newCenter, 1) + (i & 0x2 ? 1 : -1) * TObjectTraits::coord(newExtents, 1));
00358 parentNode->node[i] = new QuadNodeType(newCenter, newExtents);
00359 }
00360 }
00361 };
00362
00363
00364
00365 template <typename ObjectTraits>
00366 class QuadTreeHelper<ObjectTraits, 3>
00367 {
00368 enum { dimension = 3 };
00369 protected:
00370 typedef ObjectTraits TObjectTraits;
00371 typedef typename ObjectTraits::TPoint TPoint;
00372 typedef typename ObjectTraits::TVector TVector;
00373 typedef typename ObjectTraits::TValue TValue;
00374
00375 const TValue minComponent(const TVector& v) const
00376 {
00377 return std::min(std::min(TObjectTraits::coord(v, 0), TObjectTraits::coord(v, 1)), TObjectTraits::coord(v, 2));
00378 }
00379
00380 const TValue maxComponent(const TVector& v) const
00381 {
00382 return std::max(std::max(TObjectTraits::coord(v, 0), TObjectTraits::coord(v, 1)), TObjectTraits::coord(v, 2));
00383 }
00384
00385 template <typename V>
00386 const V middle(const V& a, const V& b) const
00387 {
00388 return V(
00389 (TObjectTraits::coord(a, 0) + TObjectTraits::coord(b, 0)) / 2,
00390 (TObjectTraits::coord(a, 1) + TObjectTraits::coord(b, 1)) / 2,
00391 (TObjectTraits::coord(a, 2) + TObjectTraits::coord(b, 2)) / 2);
00392 }
00393
00394 const TVector subtract(const TPoint& a, const TPoint& b) const
00395 {
00396 return TVector(
00397 TObjectTraits::coord(a, 0) - TObjectTraits::coord(b, 0),
00398 TObjectTraits::coord(a, 1) - TObjectTraits::coord(b, 1),
00399 TObjectTraits::coord(a, 2) - TObjectTraits::coord(b, 2));
00400 }
00401
00402 const size_t entryNode(const TVector& tNear, const TVector& tMiddle) const
00403 {
00404 const TValue tEntry = maxComponent(tNear);
00405 size_t iEntry = 0;
00406 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00407 {
00408 iEntry |= (TObjectTraits::coord(tMiddle, k) < tEntry) ? mask : 0;
00409 }
00410 return iEntry;
00411 }
00412
00413 const size_t nextNode(size_t i, const TVector& tFar) const
00414 {
00415 const TValue x = TObjectTraits::coord(tFar, 0);
00416 const TValue y = TObjectTraits::coord(tFar, 1);
00417 const TValue z = TObjectTraits::coord(tFar, 2);
00418 if (x < y && x < z)
00419 {
00420 return i & 0x1 ? size_t(-1) : i | 0x1;
00421 }
00422 else if (y < z)
00423 {
00424 return i & 0x2 ? size_t(-1) : i | 0x2;
00425 }
00426 else
00427 {
00428 return i & 0x4 ? size_t(-1) : i | 0x4;
00429 }
00430 }
00431
00432 const size_t findSubNode(const TPoint& center, const TPoint& point) const
00433 {
00434 return (TObjectTraits::coord(point, 0) >= TObjectTraits::coord(center, 0) ? 0x1 : 0x0)
00435 | (TObjectTraits::coord(point, 1) >= TObjectTraits::coord(center, 1) ? 0x2 : 0x0)
00436 | (TObjectTraits::coord(point, 2) >= TObjectTraits::coord(center, 2) ? 0x4 : 0x0);
00437 }
00438
00439 const size_t forcePositiveDirection(const TPoint& center, TPoint& support, TVector& direction) const
00440 {
00441 size_t flipMask = 0;
00442 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00443 {
00444 const TValue d = TObjectTraits::coord(direction, k);
00445 if (d < 0)
00446 {
00447 TObjectTraits::coord(support, k,
00448 2 * TObjectTraits::coord(center, k) - TObjectTraits::coord(support, k));
00449 TObjectTraits::coord(direction, k, -d);
00450 flipMask |= mask;
00451 }
00452 }
00453 return flipMask;
00454 }
00455
00456 void nearAndFar(const TPoint& min, const TPoint& max, const TPoint& support,
00457 const TVector& reciprocalDirection, TVector& tNear, TVector& tFar) const
00458 {
00459 for (size_t k = 0; k < dimension; ++k)
00460 {
00461 TObjectTraits::coord(tNear, k, TObjectTraits::coord(reciprocalDirection, k) *
00462 (TObjectTraits::coord(min, k) - TObjectTraits::coord(support, k)));
00463 TObjectTraits::coord(tFar, k, TObjectTraits::coord(reciprocalDirection, k) *
00464 (TObjectTraits::coord(max, k) - TObjectTraits::coord(support, k)));
00465 }
00466 }
00467
00468 void childNearAndFar(TVector& tNear, TVector& tFar, const TVector& tMiddle, size_t iChild) const
00469 {
00470 for (size_t k = 0, mask = 1; k < dimension; ++k, mask *= 2)
00471 {
00472 if (iChild & mask)
00473 {
00474 TObjectTraits::coord(tNear, k, TObjectTraits::coord(tMiddle, k));
00475 }
00476 else
00477 {
00478 TObjectTraits::coord(tFar, k, TObjectTraits::coord(tMiddle, k));
00479 }
00480 }
00481 }
00482
00483 template <typename QuadNodeType>
00484 static void buildSubNodes(QuadNodeType* parentNode)
00485 {
00486 TVector newExtents(parentNode->extents);
00487 TObjectTraits::coord(newExtents, 0, TObjectTraits::coord(newExtents, 0) / 2);
00488 TObjectTraits::coord(newExtents, 1, TObjectTraits::coord(newExtents, 1) / 2);
00489 TObjectTraits::coord(newExtents, 2, TObjectTraits::coord(newExtents, 2) / 2);
00490
00491 for (size_t i = 0; i < 8; ++i)
00492 {
00493 TPoint newCenter = parentNode->center;
00494 TObjectTraits::coord(newCenter, 0,
00495 TObjectTraits::coord(newCenter, 0) + (i & 0x1 ? 1 : -1) * TObjectTraits::coord(newExtents, 0));
00496 TObjectTraits::coord(newCenter, 1,
00497 TObjectTraits::coord(newCenter, 1) + (i & 0x2 ? 1 : -1) * TObjectTraits::coord(newExtents, 1));
00498 TObjectTraits::coord(newCenter, 2,
00499 TObjectTraits::coord(newCenter, 2) + (i & 0x4 ? 1 : -1) * TObjectTraits::coord(newExtents, 2));
00500 parentNode->node[i] = new QuadNodeType(newCenter, newExtents);
00501 }
00502 }
00503 };
00504
00505 }
00506 }
00507 }
00508
00509 #endif
00510
00511