library of assembled shared sources

http://lass.cocamware.com

aabb_3d.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_PRIM_AABB_3D_INL
00046 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_AABB_3D_INL
00047 
00048 
00049 
00050 #include "aabb_3d.h"
00051 #include <cstdlib>
00052 
00053 
00054 namespace lass
00055 {
00056 
00057 namespace prim
00058 {
00059 
00060 /** Construct an empty bounding box.
00061  */
00062 template <typename T, class MMP>
00063 Aabb3D<T, MMP>::Aabb3D():
00064     min_(Vector3D<T>(TNumTraits::max, TNumTraits::max, TNumTraits::max)),
00065     max_(Vector3D<T>(TNumTraits::min, TNumTraits::min, TNumTraits::min))
00066 {
00067     LASS_ASSERT(isEmpty());
00068 }
00069 
00070 
00071 
00072 /** Construct bounding box, spanned by min and max
00073  */
00074 template <typename T, class MMP>
00075 Aabb3D<T, MMP>::Aabb3D(const TPoint& min, const TPoint& max):
00076     min_(min),
00077     max_(max)
00078 {
00079     MMP::checkMinMax(min_, max_);
00080     LASS_ASSERT(isValid());
00081 }
00082 
00083 
00084 
00085 /** Construct bounding box around a single point (min == max)
00086  */
00087 template <typename T, class MMP>
00088 Aabb3D<T, MMP>::Aabb3D(const TPoint& point):
00089     min_(point),
00090     max_(point)
00091 {
00092     LASS_ASSERT(isValid());
00093 }
00094 
00095 
00096 
00097 /** copy constructor.
00098  */
00099 template <typename T, class MMP>
00100 template <class MMP2>
00101 Aabb3D<T, MMP>::Aabb3D(const Aabb3D<T, MMP2>& other):
00102     min_(other.min()),
00103     max_(other.max())
00104 {
00105 }
00106 
00107 
00108 
00109 /** return corner with smallest component values
00110  */
00111 template <typename T, class MMP>
00112 const typename Aabb3D<T, MMP>::TPoint&
00113 Aabb3D<T, MMP>::min() const
00114 {
00115     LASS_ASSERT(isValid());
00116     return min_;
00117 }
00118 
00119 
00120 
00121 /** Return corner with largest component values
00122  */
00123 template <typename T, class MMP>
00124 const typename Aabb3D<T, MMP>::TPoint&
00125 Aabb3D<T, MMP>::max() const
00126 {
00127     LASS_ASSERT(isValid());
00128     return max_;
00129 }
00130 
00131 
00132 
00133 /** set corner with smallest component values
00134  */
00135 template <typename T, class MMP>
00136 void Aabb3D<T, MMP>::setMin(const TPoint& min)
00137 {
00138     if (isEmpty())
00139     {
00140         min_ = min;
00141         max_ = min;
00142     }
00143     else
00144     {
00145         MMP::setMin(min_, max_, min);
00146     }
00147 }
00148 
00149 
00150 
00151 /** set corner with larges component values
00152  */
00153 template <typename T, class MMP>
00154 void Aabb3D<T, MMP>::setMax(const TPoint& max)
00155 {
00156     if (isEmpty())
00157     {
00158         min_ = max;
00159         max_ = max;
00160     }
00161     else
00162     {
00163         MMP::setMax(min_, max_, max);
00164     }
00165 }
00166 
00167 
00168 
00169 /** assign one bounding box to another.
00170  */
00171 template <typename T, class MMP>
00172 template <class MMP2>
00173 typename Aabb3D<T, MMP>::TSelf&
00174 Aabb3D<T, MMP>::operator=(const Aabb3D<T, MMP2>& other)
00175 {
00176     TSelf temp(other);
00177     swap(temp);
00178     return *this;
00179 }
00180 
00181 
00182 
00183 /** Expand bounding box so it contains point.
00184  */
00185 template <typename T, class MMP>
00186 typename Aabb3D<T, MMP>::TSelf&
00187 Aabb3D<T, MMP>::operator+=(const TPoint& point)
00188 {
00189     LASS_ASSERT(isValid());
00190     min_ = pointwiseMin(min_, point);
00191     max_ = pointwiseMax(max_, point);
00192     return *this;
00193 }
00194 
00195 
00196 
00197 /** Expand boundix box so it contains the other bounding box.
00198  */
00199 template <typename T, class MMP>
00200 template <class MMP2>
00201 typename Aabb3D<T, MMP>::TSelf&
00202 Aabb3D<T, MMP>::operator+=(const Aabb3D<T, MMP2>& other)
00203 {
00204     LASS_ASSERT(isValid());
00205     min_ = pointwiseMin(min_, other.min());
00206     max_ = pointwiseMax(max_, other.max());
00207     return *this;
00208 }
00209 
00210 /** Expand bounding box by distance iDistance.  Negative values causing
00211  *  reversal of the bounding box will cause the box to shrink to the
00212  *  empty box.
00213  */
00214 template <typename T, class MMP>
00215 void Aabb3D<T, MMP>::grow(TParam iDistance)
00216 {
00217     grow(TVector(iDistance, iDistance, iDistance));
00218 }
00219 
00220 /** Expand bounding box by axis-dependent distance.  Negative values causing
00221  *  reversal of the bounding box will cause the box to shrink to the
00222  *  empty box.
00223  */
00224 template <typename T, class MMP>
00225 void Aabb3D<T, MMP>::grow(TVector iDistance)
00226 {
00227     min_ -= iDistance;
00228     max_ += iDistance;
00229     if (max_.x < min_.x || max_.y < min_.y || max_.z < min_.z)
00230     {
00231         clear();
00232     }
00233     LASS_ASSERT(isValid());
00234 }
00235 
00236 
00237 /** Scale bounding box by scale iScale.  Fractions will shrink the bounding box.
00238  *  The origin of scaling is the center of the bounding box.  Negative values of the
00239  *  scale have same effect as positive ones.
00240  */
00241 template <typename T, class MMP>
00242 void Aabb3D<T, MMP>::scale(TParam iScale)
00243 {
00244     const TVector extra = size() * ((num::abs(iScale) - 1) / 2);
00245     min_ -= extra;
00246     max_ += extra;
00247     LASS_ASSERT(isValid());
00248 }
00249 
00250 
00251 
00252 /** Return the center point of the bounding box.
00253  *  We return a homogeneous point to avoid the division by two (that might not be supported
00254  *  by some types like integers)
00255  */
00256 template <typename T, class MMP>
00257 const typename Aabb3D<T, MMP>::TPointH
00258 Aabb3D<T, MMP>::center() const
00259 {
00260     LASS_ASSERT(isValid());
00261     return min_ + max_;
00262 }
00263 
00264 
00265 
00266 /** Return size of bounding box per axis, max - min.
00267  */
00268 template <typename T, class MMP>
00269 const typename Aabb3D<T, MMP>::TVector
00270 Aabb3D<T, MMP>::size() const
00271 {
00272     LASS_ASSERT(isValid());
00273     return max_ - min_;
00274 }
00275 
00276 
00277 
00278 /** Returns surface area of bounding box.
00279  *  the surface of a bounding box consists of three pair of rectangles
00280  */
00281 template <typename T, class MMP>
00282 const typename Aabb3D<T, MMP>::TValue
00283 Aabb3D<T, MMP>::area() const
00284 {
00285     const TVector result = size();
00286     return 2 * (result.x * result.y + result.y * result.z + result.z * result.x);
00287 }
00288 
00289 
00290 
00291 /** Returns volume of bounding box.
00292  */
00293 template <typename T, class MMP>
00294 const typename Aabb3D<T, MMP>::TValue
00295 Aabb3D<T, MMP>::volume() const
00296 {
00297     const TVector result = size();
00298     return result.x * result.y * result.z;
00299 }
00300 
00301 
00302 /** Classify if a point is in or outside the bounding box, or on its surface
00303  *  @return sInside, sSurface, sOutside
00304  */
00305 template <typename T, class MMP>
00306 const Side Aabb3D<T, MMP>::classify(const TPoint& point) const
00307 {
00308     LASS_ASSERT(isValid());
00309 
00310     if (point.x > min_.x && point.x < max_.x &&
00311         point.y > min_.y && point.y < max_.y &&
00312         point.z > min_.z && point.z < max_.z)
00313     {
00314         return sInside;
00315     }
00316 
00317     if (point.x < min_.x || point.x > max_.x ||
00318         point.y < min_.y || point.y > max_.y ||
00319         point.z < min_.z || point.z > max_.z)
00320     {
00321         return sOutside;
00322     }
00323 
00324     return sSurface;
00325 }
00326 
00327 
00328 
00329 /** Returns true if point is inside bounding box or on its surface.
00330  *  Is equivalent to this->classify(point) != sOutside, but might be faster.
00331  */
00332 template <typename T, class MMP>
00333 const bool Aabb3D<T, MMP>::contains(const TPoint& point) const
00334 {
00335     LASS_ASSERT(isValid());
00336     return  point.x >= min_.x && point.x <= max_.x &&
00337             point.y >= min_.y && point.y <= max_.y &&
00338             point.z >= min_.z && point.z <= max_.z;
00339 }
00340 
00341 
00342 
00343 /** Returns true if the AABB other is inside (or on its surface) this AABB.
00344  *  - Is equivalent to this->contains(other.min()) && this->contains(other.max()).
00345  *  - if other is an empty AABB, it will always return true (an empty set is always a part of
00346  *    any other set).
00347  */
00348 template <typename T, class MMP>
00349 template <class MMP2>
00350 const bool Aabb3D<T, MMP>::contains(const Aabb3D<T, MMP2>& other) const
00351 {
00352     LASS_ASSERT(isValid() && other.isValid());
00353     return other.min().x >= min_.x && other.max().x <= max_.x
00354         && other.min().y >= min_.y && other.max().y <= max_.y
00355         && other.min().z >= min_.z && other.max().z <= max_.z;
00356 }
00357 
00358 
00359 
00360 /** Check if two axis-aligned bounding boxes do intersect.
00361  *  @return @arg false      intersection of the AABBs is empty.
00362  *          @arg true       intersection of the AABBs is not empty.
00363  *
00364  *  @par FAQ: What's the difference between @c this->intersects(other) and @c this->collides(other) ?
00365  *      When two AABB are touching each other (surface to surface), the intersection isn't empty.
00366  *      i.e. the intersection is the line of points that belong to both the surfaces of the AABBs.
00367  *      In that case, the intersection is a degenerated AABB though, one with @c volume()==0.
00368  *      In collision detection however, you don't want this degenerated case of intersection to be
00369  *      considered as a collision.  Two bodies may touch, but the must not have an overlap thas has a
00370  *      non-zero volume.  That's why we have two methods: @c intersects returns true on touching
00371  *      AABBs, @c collides will return false.  Of course, in the non-degenerate cases, they behave the
00372  *      same.
00373  *
00374  *  Use the seperating axis test to test if two AABB's do intersect:
00375  *  GOMEZ M. (1999), <i>Simple Intersection Tests For Games</i>, Gamasutra,
00376  *  http://www.gamasutra.com,
00377  *  http://www.gamasutra.com/features/19991018/Gomez_3.htm
00378  */
00379 template <typename T, class MMP>
00380 template <class MMP2>
00381 const bool Aabb3D<T, MMP>::intersects(const Aabb3D<T, MMP2>& other) const
00382 {
00383     LASS_ASSERT(isValid() && other.isValid());
00384 
00385     // test if both AABB's do intersect by using the SEPERATING AXIS TEST.
00386     // notice that the weight of the homogenous points a.center() and b.center() is two,
00387     // so we can avond the division by two of doubleExtend.
00388     // that's why we also have to just take the sum of the sizes and not the half sum.
00389 
00390     LASS_ASSERT(center().weight() == 2 && other.center().weight() == 2);
00391     const TPointH doubleCenterToCenter = center() - other.center();
00392 
00393     LASS_ASSERT(doubleCenterToCenter.weight() == 0);
00394     const typename TPointH::TVector doubleCenterDistance =
00395         doubleCenterToCenter.position().transform(num::abs);
00396 
00397     const TVector doubleExtend = size() + other.size();
00398     return doubleCenterDistance.x <= doubleExtend.x && doubleCenterDistance.y <= doubleExtend.y 
00399         && doubleCenterDistance.z <= doubleExtend.z;
00400 }
00401 
00402 
00403 
00404 /** Check if two axis-aligned bounding boxes do dollide.
00405  *  @return @arg true       the AABBs do collide.
00406  *          @arg false      they don't.
00407  *
00408  *  @par FAQ: What's the difference between @c this->intersects(other) and @c this->collides(other) ?
00409  *      When two AABB are touching each other (surface to surface), the intersection isn't empty.
00410  *      i.e. the intersection is the line of points that belong to both the surfaces of the AABBs.
00411  *      In that case, the intersection is a degenerated AABB though, one with @c volume()==0.
00412  *      In collision detection however, you don't want this degenerated case of intersection to be
00413  *      considered as a collision.  Two bodies may touch, but the must not have an overlap thas has a
00414  *      non-zero volume.  That's why we have two methods: @c intersects returns true on touching
00415  *      AABBs, @c collides will return false.  Of course, in the non-degenerate cases, they behave the
00416  *      same.
00417  *
00418  *  Use the seperating axis test to test if two AABB's do intersect:
00419  *  GOMEZ M. (1999), <i>Simple Intersection Tests For Games</i>, Gamasutra,
00420  *  http://www.gamasutra.com,
00421  *  http://www.gamasutra.com/features/19991018/Gomez_3.htm
00422  */
00423 template <typename T, class MMP>
00424 template <class MMP2>
00425 const bool Aabb3D<T, MMP>::collides(const Aabb3D<T, MMP2>& other) const
00426 {
00427     LASS_ASSERT(isValid() && other.isValid());
00428 
00429     // test if both AABB's do intersect by using the SEPERATING AXIS TEST.
00430     // notice that the weight of the homogenous points a.center() and b.center() is two,
00431     // so we can avond the division by two of doubleExtend.
00432     // that's why we also have to just take the sum of the sizes and not the half sum.
00433 
00434     LASS_ASSERT(center().weight() == 2 && other.center().weight() == 2);
00435     const TPointH doubleCenterToCenter = center() - other.center();
00436 
00437     LASS_ASSERT(doubleCenterToCenter.weight() == 0);
00438     const typename TPointH::TVector doubleCenterDistance =
00439         doubleCenterToCenter.position().transform(num::abs);
00440 
00441     const TVector doubleExtend = size() + other.size();
00442     return doubleCenterDistance.x < doubleExtend.x && doubleCenterDistance.y < doubleExtend.y
00443         && doubleCenterDistance.z < doubleExtend.z;
00444 }
00445 
00446 
00447 
00448 
00449 
00450 
00451 /** Return a random point so that bounding box contains it.
00452  */
00453 template <typename T, class MMP>
00454 template <class RandomGenerator>
00455 const typename Aabb3D<T, MMP>::TPoint
00456 Aabb3D<T, MMP>::random(RandomGenerator& generator) const
00457 {
00458     LASS_ASSERT(isValid());
00459     num::DistributionUniform<TValue, RandomGenerator> uniform(generator);
00460     const TVector t(uniform(), uniform(), uniform());
00461     const TPoint result(min_ + t * (max_ - min_));
00462     LASS_ASSERT(contains(result));
00463     return result;
00464 }
00465 
00466 
00467 
00468 /** set AABB to an empty box
00469  */
00470 template <typename T, class MMP>
00471 void Aabb3D<T, MMP>::clear()
00472 {
00473     min_ = TPoint(TNumTraits::max, TNumTraits::max, TNumTraits::max);
00474     max_ = TPoint(TNumTraits::min, TNumTraits::min, TNumTraits::min);
00475     LASS_ASSERT(isValid() && isEmpty());
00476 }
00477 
00478 
00479 
00480 /** Return true if bounding box contains no points.
00481  *  i.e. this->contains(Point3<T>(x, y, z)) will return false for all possible values of
00482  *  x, y and z.
00483  */
00484 template <typename T, class MMP>
00485 const bool Aabb3D<T, MMP>::isEmpty() const
00486 {
00487     LASS_ASSERT(isValid());
00488     return min_.x > max_.x;
00489 }
00490 
00491 
00492 
00493 /** internal check to see if AABB is valid.
00494  *  There are two valid states for the AABB:
00495  *  @arg <tt>max_.x < min_.x</tt> which means the box is empty
00496  *  @arg <tt>max_.x >= min_.x && max_.y >= min_.y && max_.z >= min_.z</tt> which means the box is
00497  *      not empty.
00498  *  That gives us an invalid state as well:
00499  *  @arg <tt>max_.x >= min_.x && (max_.y < min_.y || max_.z < min_.z)</tt>.  This state would cause
00500  *      @c isEmpty() to yield false, while there's still nothing in it (there's no single point for
00501  *      which @c contains(p) would return true.
00502  *
00503  *  When the regular minmax policies are used (StrictMinMax and AutoMinMax), there's no way any AABB
00504  *  would become invalid, and this test counts as an invariant to the box.  However, when using the
00505  *  UncheckedMinMax policy, you're on your own.
00506  */
00507 template <typename T, class MMP>
00508 const bool Aabb3D<T, MMP>::isValid() const
00509 {
00510     return (min_.x <= max_.x && min_.y <= max_.y && min_.z <= max_.z) || (min_.x > max_.x);
00511 }
00512 
00513 
00514 
00515 /** swap two bounding boxes.
00516  */
00517 template <typename T, class MMP>
00518 template <typename MMP2>
00519 void Aabb3D<T, MMP>::swap(Aabb3D<T, MMP2>& other)
00520 {
00521     std::swap(min_, other.min_);
00522     std::swap(max_, other.max_);
00523 }
00524 
00525 
00526 
00527 // --- free ----------------------------------------------------------------------------------------
00528 
00529 /** join two AABBs
00530  *  @relates Aabb3D
00531  */
00532 template <typename T, class MMPa, class MMPb> inline
00533 const Aabb3D<T, MMPa> operator+(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
00534 {
00535     Aabb3D<T, MMPa> result(a);
00536     result += b;
00537     return result;
00538 }
00539 
00540 
00541 
00542 /** add a point to an AABB
00543  *  @relates Aabb3D
00544  */
00545 template <typename T, class MMP> inline
00546 const Aabb3D<T, MMP> operator+(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
00547 {
00548     Aabb3D<T, MMP> result(a);
00549     result += b;
00550     return result;
00551 }
00552 
00553 
00554 
00555 /** add a point to an AABB
00556  *  @relates Aabb3D
00557  */
00558 template <typename T, class MMP> inline
00559 const Aabb3D<T, MMP> operator+(const Point3D<T>& a, const Aabb3D<T, MMP>& b)
00560 {
00561     Aabb3D<T, MMP> result(b);
00562     result += a;
00563     return result;
00564 }
00565 
00566 
00567 
00568 /** @relates Aabb3D
00569  */
00570 template <typename T>
00571 const Aabb3D<T> aabb(const Point3D<T>& point)
00572 {
00573     return Aabb3D<T>(point, point);
00574 }
00575 
00576 
00577 
00578 /** distance between AABB and point
00579  *  @relates Aabb3D
00580  *  @param a   AABB
00581  *  @param b   point
00582  *  @return absolute distance between point and AABB.  If point is inside AABB, distance is 0.
00583  *  @pre @a a should not be empty.  Undefined behaviour if it is empty.
00584  */
00585 template <typename T, class MMP> inline
00586 T distance(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
00587 {
00588     LASS_ASSERT(!a.isEmpty());
00589     typedef Vector3D<T> TVector;
00590     return pointwiseMax(pointwiseMax(a.min() - b, b - a.max()), TVector()).norm();
00591 }
00592 
00593 
00594 
00595 /** distance between two AABBs
00596  *  @relates Aabb3D
00597  *  @param a   AABB
00598  *  @param b   AABB
00599  *  @return absolute distance.  If one AABB is completely inside the other, distance is 0.
00600  *  @pre @a a and @a b should not be empty.  Undefined behaviour if they are.
00601  */
00602 template <typename T, class MMPa, class MMPb> inline
00603 T distance(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
00604 {
00605     LASS_ASSERT(!a.isEmpty() && !b.isEmpty());
00606     typedef Vector3D<T> TVector;
00607     return pointwiseMax(pointwiseMax(a.min() - b.max(), b.min() - a.max()), TVector()).norm();
00608 }
00609 
00610 
00611 
00612 /** Calculate the intersection of two axis aligned bounding boxes.
00613  *  @relates lass::prim::Aabb3D
00614  *  @param a the first AABB :)
00615  *  @param b the second AABB
00616  *  @param result the intersection of @a a and @a b.  In contrary to other intersection
00617  *                 functions, this output argument will @e always be assigned, even if there's no
00618  *                 result.  By no result we mean: the intersection is empty.  For most other
00619  *                 intersection functions, we can't assign a meaning full value if there's no
00620  *                 intersection, so we don't.  However, in this case we can assign an @e empty AABB.
00621  *                 And that's exactly what we do.  So, the output argument is @e always valid, even
00622  *                 if the return value suggests otherwise (in fact, you don't have to bother the
00623  *                 return value this time)
00624  *  @return @arg rNone      intersection of the AABBs is empty.
00625  *                          @a result is an @e empty AABB.
00626  *          @arg rOne       intersection of the AABBs is not empty.
00627  *                          @a result contains intersection.
00628  */
00629 template <typename T, class MMPa, class MMPb, class MMPr>
00630 Result intersect(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b, Aabb3D<T, MMPr>& result)
00631 {
00632     LASS_ASSERT(a.isValid() && b.isValid());
00633 
00634     if (!a.intersects(b))
00635     {
00636         result = Aabb3D<T, MMPr>(); // empty box
00637         return rNone;
00638     }
00639 
00640     // by now, we're sure they are intersecting.  now, we only need the highest minimum
00641     // and lowest maximum.
00642     //
00643     result = Aabb3D<T, MMPr>(pointwiseMax(a.min(), b.min()), pointwiseMin(a.max(), b.max()));
00644     return rOne;
00645 }
00646 
00647 
00648 
00649 template <typename T, class MMPa, class MMPb> inline
00650 const bool intersects(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
00651 {
00652     return a.intersects(b);
00653 }
00654 
00655 
00656 
00657 /** @relates lass::prim::Aabb2D
00658  */
00659 template <typename T, typename MMP> inline
00660 const bool intersects(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
00661 {
00662     return a.contains(b);
00663 }
00664 
00665 
00666 
00667 /** @relates lass::prim::Aabb2D
00668  */
00669 template <typename T, typename MMP> inline
00670 const bool intersects(const Point3D<T>& a, const Aabb3D<T, MMP>& b)
00671 {
00672     return b.contains(a);
00673 }
00674 
00675 
00676 
00677 template <typename T, class MMPa, class MMPb> inline
00678 const bool collides(const Aabb3D<T, MMPa>& a, const Aabb3D<T, MMPb>& b)
00679 {
00680     return a.collides(b);
00681 }
00682 
00683 
00684 
00685 /** @relates lass::prim::Aabb2D
00686  */
00687 template <typename T, typename MMP> inline
00688 const bool collides(const Aabb3D<T, MMP>& a, const Point3D<T>& b)
00689 {
00690     typedef typename Aabb3D<T, MMP>::TPoint TPoint;
00691     const TPoint& min = a.min();
00692     const TPoint& max = a.max();
00693     return min.x < b.x && b.x < max.x && 
00694         min.y < b.y && b.y < max.y &&
00695         min.z < b.z && b.z < max.z;
00696 }
00697 
00698 
00699 
00700 /** @relates lass::prim::Aabb2D
00701  */
00702 template <typename T, typename MMP> inline
00703 const bool collides(const Point3D<T>& a, const Aabb3D<T, MMP>& b)
00704 {
00705     return collides(b, a);
00706 }
00707 
00708 
00709 
00710 /** @relates lass::prim::Aabb3D
00711  */
00712 template <typename T, class MMP>
00713 std::ostream& operator<<(std::ostream& stream, const Aabb3D<T, MMP>& aabb)
00714 {
00715     LASS_ENFORCE_STREAM(stream) << "{m=" << aabb.min() << ", M=" << aabb.max() << "}";
00716     return stream;
00717 }
00718 
00719 
00720 
00721 /** @relates lass::prim::Aabb3D
00722  */
00723 template<typename T, class MMP>
00724 io::XmlOStream& operator<<(io::XmlOStream& stream, const Aabb3D<T, MMP>& aabb)
00725 {
00726     LASS_ENFORCE_STREAM(stream)
00727         << "<Aabb3D>\n"
00728         << "<min>" << aabb.min() << "</min>\n"
00729         << "<max>" << aabb.max() << "</max>\n"
00730         << "</Aabb3D>\n";
00731 
00732     return stream;
00733 }
00734 
00735 
00736 
00737 }
00738 
00739 }
00740 
00741 #endif

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