library of assembled shared sources

http://lass.cocamware.com

aabb_tree.inl

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 
00044 
00045 #ifndef LASS_GUARDIAN_OF_INCLUSION_SPAT_AABB_TREE_INL
00046 #define LASS_GUARDIAN_OF_INCLUSION_SPAT_AABB_TREE_INL
00047 
00048 #include "spat_common.h"
00049 #include "aabb_tree.h"
00050 
00051 namespace lass
00052 {
00053 namespace spat
00054 {
00055 
00056 // --- public --------------------------------------------------------------------------------------
00057 
00058 template <typename O, typename OT, typename SH>
00059 AabbTree<O, OT, SH>::AabbTree():
00060     objects_(),
00061     nodes_(),
00062     end_()
00063 {
00064 }
00065 
00066 
00067 
00068 template <typename O, typename OT, typename SH>
00069 AabbTree<O, OT, SH>::AabbTree(TObjectIterator first, TObjectIterator last):
00070     objects_(),
00071     nodes_(),
00072     end_(last)
00073 {
00074     if (first != last)
00075     {
00076         TInputs inputs;
00077         for (TObjectIterator i = first; i != last; ++i)
00078         {
00079             inputs.push_back(Input(TObjectTraits::objectAabb(i), i));
00080         }
00081         balance(inputs.begin(), inputs.end());
00082     }
00083 }
00084 
00085 
00086 
00087 template <typename O, typename OT, typename SH>
00088 void AabbTree<O, OT, SH>::reset(TObjectIterator first, TObjectIterator last)
00089 {
00090     TSelf temp(first, last);
00091     swap(temp);
00092 }
00093 
00094 
00095 
00096 template <typename O, typename OT, typename SH> inline
00097 const typename AabbTree<O, OT, SH>::TAabb
00098 AabbTree<O, OT, SH>::aabb() const
00099 {
00100     if (isEmpty())
00101     {
00102         return TObjectTraits::aabbEmpty();
00103     }
00104     return nodes_[0].aabb();
00105 }
00106 
00107 
00108 
00109 template <typename O, typename OT, typename SH> inline
00110 bool AabbTree<O, OT, SH>::contains(const TPoint& point, const TInfo* info) const
00111 {
00112     if (isEmpty())
00113     {
00114         return false;
00115     }
00116     return doContains(0, point, info);
00117 }
00118 
00119 
00120 
00121 template <typename O, typename OT, typename SH>
00122 template <typename OutputIterator> inline
00123 OutputIterator AabbTree<O, OT, SH>::find(
00124         const TPoint& point, OutputIterator result, const TInfo* info) const
00125 {
00126     if (isEmpty())
00127     {
00128         return result;
00129     }
00130     return doFind(0, point, result, info);
00131 }
00132 
00133 
00134 
00135 template <typename O, typename OT, typename SH>
00136 typename AabbTree<O, OT, SH>::TObjectIterator inline
00137 AabbTree<O, OT, SH>::intersect(const TRay& ray, TReference t, TParam tMin, const TInfo* info) const
00138 {
00139     if (isEmpty())
00140     {
00141         return end_;
00142     }
00143     return doIntersect(0, ray, t, tMin, info);
00144 }
00145 
00146 
00147 
00148 template <typename O, typename OT, typename SH>
00149 bool inline AabbTree<O, OT, SH>::intersects(const TRay& ray, TParam tMin, TParam tMax, const TInfo* info) const
00150 {
00151     if (isEmpty())
00152     {
00153         return false;
00154     }
00155     return doIntersects(0, ray, tMin, tMax, info);
00156 }
00157 
00158 
00159 
00160 template <typename O, typename OT, typename SH>
00161 const typename AabbTree<O, OT, SH>::Neighbour
00162 AabbTree<O, OT, SH>::nearestNeighbour(const TPoint& point, const TInfo* info) const
00163 {
00164     Neighbour nearest(end_, std::numeric_limits<TValue>::infinity());
00165     if (!isEmpty())
00166     {
00167         doNearestNeighbour(0, point, info, nearest);
00168     }
00169     return nearest;
00170 }
00171 
00172 
00173 
00174 template <class O, class OT, typename SH>
00175 template <typename RandomAccessIterator>
00176 RandomAccessIterator
00177 AabbTree<O, OT, SH>::rangeSearch(
00178         const TPoint& target, TParam maxRadius, size_t maxCount, RandomAccessIterator first, 
00179         const TInfo* info) const
00180 {
00181     if (isEmpty() || maxRadius == 0)
00182     {
00183         return first;
00184     }
00185     TValue squaredRadius = maxRadius * maxRadius;
00186     return doRangeSearch(0, target, squaredRadius, maxCount, first, first, info);
00187 }
00188 
00189 
00190 
00191 template <typename O, typename OT, typename SH>
00192 void AabbTree<O, OT, SH>::swap(TSelf& other)
00193 {
00194     nodes_.swap(other.nodes_);
00195     objects_.swap(other.objects_);
00196     std::swap(end_, other.end_);
00197 }
00198 
00199 
00200 
00201 template <typename O, typename OT, typename SH>
00202 const bool AabbTree<O, OT, SH>::isEmpty() const
00203 {
00204     return objects_.empty();
00205 }
00206 
00207 
00208 
00209 template <typename O, typename OT, typename SH>
00210 const typename AabbTree<O, OT, SH>::TObjectIterator
00211 AabbTree<O, OT, SH>::end() const
00212 {
00213     return end_;
00214 }
00215 
00216 
00217 
00218 template <typename O, typename OT, typename SH>
00219 void AabbTree<O, OT, SH>::reset()
00220 {
00221     TSelf temp;
00222     swap(temp);
00223 }
00224 
00225 
00226 
00227 // --- protected -----------------------------------------------------------------------------------
00228 
00229 
00230 
00231 // --- private -------------------------------------------------------------------------------------
00232 
00233 template <typename O, typename OT, typename SH>
00234 const int AabbTree<O, OT, SH>::balance(TInputIterator first, TInputIterator last)
00235 {
00236     const SplitInfo<OT> split = TSplitHeuristics::template split<OT>(first, last);  
00237     if (split.axis < 0)
00238     {
00239         return addLeafNode(split.aabb, first, last);
00240     }
00241 
00242     TInputIterator middle = std::partition(first, last, impl::Splitter<TObjectTraits>(split));
00243         if (middle == first || middle == last)
00244     {
00245         const ptrdiff_t halfSize = (last - first) / 2;
00246         LASS_ASSERT(halfSize > 0);
00247         middle = first + halfSize;
00248         std::nth_element(first, middle, last, impl::LessAxis<TObjectTraits>(split.axis));
00249     }
00250     LASS_ASSERT(middle != first && middle != last);
00251 
00252     const int node = addInternalNode(split.aabb);
00253     const int left = balance(first, middle);
00254     LASS_ASSERT(left == node + 1);
00255     const int right = balance(middle, last);
00256     nodes_[node].right() = right;
00257     return node;
00258 }
00259 
00260 
00261 
00262 template <typename O, typename OT, typename SH>
00263 const int AabbTree<O, OT, SH>::addLeafNode(
00264         const TAabb& aabb, TInputIterator first, TInputIterator last)
00265 {
00266     const int begin = static_cast<int>(objects_.size());
00267     while (first != last)
00268     {
00269         objects_.push_back((first++)->object);
00270     }
00271     const int end = static_cast<int>(objects_.size());
00272     
00273     LASS_ASSERT(begin >= 0 && end >= 0);
00274     nodes_.push_back(Node(aabb, begin, end));
00275 
00276     LASS_ASSERT(static_cast<int>(nodes_.size()) > 0);
00277     return static_cast<int>(nodes_.size()) - 1;
00278 }
00279 
00280 
00281 
00282 template <typename O, typename OT, typename SH>
00283 const int AabbTree<O, OT, SH>::addInternalNode(const TAabb& aabb)
00284 {
00285     nodes_.push_back(Node(aabb));
00286 
00287     LASS_ASSERT(static_cast<int>(nodes_.size()) > 0);
00288     return static_cast<int>(nodes_.size()) - 1;
00289 }
00290 
00291 
00292 
00293 template <typename O, typename OT, typename SH>
00294 bool AabbTree<O, OT, SH>::doContains(int index, const TPoint& point, const TInfo* info) const
00295 {
00296     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00297     LASS_ASSERT(index >= 0 && static_cast<size_t>(index) < nodes_.size());
00298     const Node& node = nodes_[index];
00299 
00300     if (!TObjectTraits::aabbContains(node.aabb(), point))
00301     {
00302         return false;
00303     }
00304     if (node.isInternal())
00305     {
00306         return doContains(index + 1, point, info) || doContains(node.right(), point, info);
00307     }
00308     for (int i = node.first(); i != node.last(); ++i)
00309     {
00310         LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00311         if (TObjectTraits::objectContains(objects_[i], point, info))
00312         {
00313             return true;
00314         }
00315     }
00316     return false;
00317 }
00318 
00319 
00320 
00321 template <typename O, typename OT, typename SH>
00322 template <typename OutputIterator>
00323 OutputIterator AabbTree<O, OT, SH>::doFind(
00324         int index, const TPoint& point, OutputIterator result, const TInfo* info) const
00325 {
00326     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00327     LASS_ASSERT(index >= 0 && static_cast<size_t>(index) < nodes_.size());
00328     const Node& node = nodes_[index];
00329 
00330     if (!TObjectTraits::aabbContains(node.aabb(), point))
00331     {
00332         return result;
00333     }
00334     if (node.isInternal())
00335     {
00336         result = doFind(index + 1, point, result, info);
00337         return doFind(node.right(), point, result, info);
00338     }
00339     for (int i = node.first(); i != node.last(); ++i)
00340     {
00341         LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00342         if (TObjectTraits::objectContains(objects_[i], point, info))
00343         {
00344             *result++ = objects_[i];
00345         }
00346     }
00347     return result;
00348 }
00349 
00350 
00351 
00352 template <typename O, typename OT, typename SH>
00353 typename AabbTree<O, OT, SH>::TObjectIterator 
00354 AabbTree<O, OT, SH>::doIntersect(
00355         int index, const TRay& ray, TReference t, TParam tMin, const TInfo* info) const
00356 {
00357     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00358     LASS_ASSERT(index >= 0 && static_cast<size_t>(index) < nodes_.size());
00359     const Node& node = nodes_[index];
00360 
00361     TValue tDummy;
00362     if (!TObjectTraits::aabbIntersect(node.aabb(), ray, tDummy, tMin))
00363     {
00364         return end_;
00365     }
00366 
00367     if (node.isInternal())
00368     {
00369         TValue tLeft;
00370         TObjectIterator left = doIntersect(index + 1, ray, tLeft, tMin, info);
00371         TValue tRight;
00372         TObjectIterator right = doIntersect(node.right(), ray, tRight, tMin, info);
00373 
00374         if (left != end_ && (right == end_ || tLeft < tRight))
00375         {
00376             t = tLeft;
00377             return left;
00378         }
00379         if (right != end_)
00380         {
00381             LASS_ASSERT(left == end_ || !(tLeft < tRight));
00382             t = tRight;
00383             return right;
00384         }
00385         return end_;
00386     }
00387 
00388     TValue tBest = 0;
00389     TObjectIterator best = end_;
00390     for (int i = node.first(); i != node.last(); ++i)
00391     {
00392         LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00393         TValue tCandidate = 0;
00394         if (TObjectTraits::objectIntersect(objects_[i], ray, tCandidate, tMin, info))
00395         {
00396             if (best == end_ || tCandidate < tBest)
00397             {
00398                 tBest = tCandidate;
00399                 best = objects_[i];
00400             }
00401         }
00402     }
00403     if (best != end_)
00404     {
00405         t = tBest;
00406     }
00407     return best;
00408 }
00409 
00410 
00411 
00412 template <typename O, typename OT, typename SH>
00413 bool AabbTree<O, OT, SH>::doIntersects(
00414         int index, const TRay& ray, TParam tMin, const TParam tMax, const TInfo* info) const
00415 {
00416     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00417     LASS_ASSERT(index >= 0 && static_cast<size_t>(index) < nodes_.size());
00418     const Node& node = nodes_[index];
00419 
00420     TValue tDummy = 0;
00421     if (!TObjectTraits::aabbIntersect(node.aabb(), ray, tDummy, tMin))
00422     {
00423         return false;
00424     }
00425     if (node.isInternal())
00426     {
00427         return doIntersects(index + 1, ray, tMin, tMax, info)
00428             || doIntersects(node.right(), ray, tMin, tMax, info);
00429     }
00430     for (int i = node.first(); i != node.last(); ++i)
00431     {
00432         LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00433         if (TObjectTraits::objectIntersects(objects_[i], ray, tMin, tMax, info))
00434         {
00435             return true;
00436         }
00437     }
00438     return false;
00439 }
00440 
00441 
00442 
00443 template <typename O, typename OT, typename SH>
00444 void AabbTree<O, OT, SH>::doNearestNeighbour(
00445         int index, const TPoint& target, const TInfo* info, Neighbour& best) const
00446 {
00447     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00448     LASS_ASSERT(best.squaredDistance() >= 0);
00449 
00450     const Node& node = nodes_[index];
00451 
00452     if (node.isLeaf())
00453     {
00454         for (int i = node.first(); i != node.last(); ++i)
00455         {
00456             LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00457             const TValue squaredDistance = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
00458             if (squaredDistance < best.squaredDistance())
00459             {
00460                 best = Neighbour(objects_[i], squaredDistance);
00461             }
00462         }
00463     }
00464     else
00465     {
00466         int children[2];
00467         TValue squaredDistances[2];
00468         getChildren(index, target, children, squaredDistances);
00469         if (squaredDistances[0] < best.squaredDistance())
00470         {
00471             doNearestNeighbour(children[0], target, info, best);
00472             if (squaredDistances[1] < best.squaredDistance())
00473             {
00474                 doNearestNeighbour(children[1], target, info, best);
00475             }
00476         }
00477     }
00478 }
00479 
00480 
00481 
00482 template <typename O, typename OT, typename SH>
00483 template <typename RandomIterator>
00484 RandomIterator AabbTree<O, OT, SH>::doRangeSearch(
00485     int index, const TPoint& target, TReference squaredRadius, size_t maxCount,
00486     RandomIterator first, RandomIterator last, const TInfo* info) const
00487 {
00488     LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_INIT_NODE(TInfo, info);
00489     LASS_ASSERT(squaredRadius >= 0);
00490 
00491     const Node& node = nodes_[index];
00492 
00493     if (node.isLeaf())
00494     {
00495         for (int i = node.first(); i != node.last(); ++i)
00496         {
00497             LASS_SPAT_OBJECT_TREES_DIAGNOSTICS_VISIT_OBJECT;
00498             const TValue sqrDist = TObjectTraits::objectSquaredDistance(objects_[i], target, info);
00499             if (sqrDist < squaredRadius)
00500             {
00501                 *last++ = Neighbour(objects_[i], sqrDist);
00502                 std::push_heap(first, last);
00503                 LASS_ASSERT(last >= first);
00504                 if (static_cast<size_t>(last - first) > maxCount)
00505                 {
00506                     std::pop_heap(first, last);
00507                     --last;
00508                     squaredRadius = first->squaredDistance();
00509                 }
00510             }
00511         }
00512         return last;
00513     }
00514 
00515     int children[2];
00516     TValue squaredDistances[2];
00517     getChildren(index, target, children, squaredDistances);
00518     if (squaredDistances[0] < squaredRadius)
00519     {
00520         last = doRangeSearch(children[0], target, squaredRadius, maxCount, first, last, info);
00521         if (squaredDistances[1] < squaredRadius)
00522         {
00523             last = doRangeSearch(children[1], target, squaredRadius, maxCount, first, last, info);
00524         }
00525     }
00526 
00527     return last;
00528 }
00529 
00530 
00531 
00532 template <typename O, typename OT, typename SH>
00533 void AabbTree<O, OT, SH>::getChildren(
00534         int index, const TPoint& target, int indices[2], TValue squaredDistances[2]) const
00535 {
00536     const Node& node = nodes_[index];
00537     indices[0] = index + 1;
00538     indices[1] = node.right();
00539 
00540     for (size_t i = 0; i < 2; ++i)
00541     {
00542         const Node& child = nodes_[indices[i]];
00543         squaredDistances[i] = 0;
00544         const TPoint& min = TObjectTraits::aabbMin(child.aabb());
00545         const TPoint& max = TObjectTraits::aabbMax(child.aabb());
00546         for (size_t k = 0; k < dimension; ++k)
00547         {
00548             const TValue x = TObjectTraits::coord(target, k);
00549             const TValue d = std::max(TObjectTraits::coord(min, k) - x, x - TObjectTraits::coord(max, k));
00550             if (d > 0)
00551             {
00552                 squaredDistances[i] += d * d;
00553             }
00554         }
00555     }
00556 
00557     if (squaredDistances[1] < squaredDistances[0])
00558     {
00559         std::swap(squaredDistances[0], squaredDistances[1]);
00560         std::swap(indices[0], indices[1]);
00561     }
00562 }
00563 
00564 
00565 
00566 // --- free ----------------------------------------------------------------------------------------
00567 
00568 
00569 
00570 }
00571 
00572 }
00573 
00574 #endif
00575 
00576 // EOF

Generated on Mon Nov 10 14:19:59 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo