Sirikata
|
00001 /* Sirikata Utilities -- Math Library 00002 * BoundingSphere.hpp 00003 * 00004 * Copyright (c) 2009, Daniel Reiter Horn 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are 00009 * met: 00010 * * Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * * Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in 00014 * the documentation and/or other materials provided with the 00015 * distribution. 00016 * * Neither the name of Sirikata nor the names of its contributors may 00017 * be used to endorse or promote products derived from this software 00018 * without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 00021 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00022 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00023 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 00024 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 */ 00032 #ifndef _SIRIKATA_BOUNDING_SPHERE_HPP 00033 #define _SIRIKATA_BOUNDING_SPHERE_HPP 00034 namespace Sirikata { 00035 template <typename real> class BoundingSphere { 00036 Vector3<real> mCenter; 00037 float32 mRadius; 00038 public: 00039 00040 static BoundingSphere<real> null() { 00041 return BoundingSphere<real>(Vector3<real>(0,0,0),0); 00042 } 00043 BoundingSphere() 00044 : mRadius(-1) 00045 {} 00046 BoundingSphere(const Vector3<real>¢er, float radius){ 00047 mCenter=center; 00048 mRadius=radius; 00049 } 00050 float32 radius()const{ 00051 return mRadius; 00052 } 00053 Vector3<real> center() const { 00054 return mCenter; 00055 } 00056 BoundingSphere<real> recenter(const Vector3<real>&newCenter) { 00057 mRadius+=(newCenter-mCenter).length(); 00058 mCenter=newCenter; 00059 } 00060 BoundingSphere& mergeIn(const BoundingSphere& rhs) { 00061 *this = merge(rhs); 00062 return *this; 00063 } 00064 00065 BoundingSphere merge(const BoundingSphere& rhs) const { 00066 if (rhs.invalid()) 00067 return *this; 00068 00069 if (this->invalid()) 00070 return rhs; 00071 00072 // Check if one is entirely contained within the other 00073 Vector3<real> to_other_center = rhs.mCenter - mCenter; 00074 real center_dist = to_other_center.length(); 00075 if (center_dist + mRadius <= rhs.mRadius) 00076 return rhs; 00077 if (center_dist + rhs.mRadius <= mRadius) 00078 return *this; 00079 00080 real new_radius2 = (mRadius + center_dist + rhs.mRadius); 00081 real new_radius = new_radius2 * 0.5; 00082 if (center_dist > 1e-08) { 00083 Vector3<real> to_other_center_normalized = to_other_center / center_dist; 00084 Vector3<real> farthest_point_from_other = mCenter - (mRadius * to_other_center_normalized); 00085 Vector3<real> half_new_span = to_other_center_normalized * new_radius; 00086 Vector3<real> new_center = farthest_point_from_other + half_new_span; 00087 return BoundingSphere(new_center, new_radius); 00088 } 00089 else { 00090 return BoundingSphere(mCenter, new_radius); 00091 } 00092 } 00093 00094 bool contains(const BoundingSphere& other) const { 00095 real centers_len = (mCenter - other.mCenter).length(); 00096 return (mRadius >= centers_len + other.mRadius); 00097 } 00098 00099 bool contains(const BoundingSphere& other, real epsilon) const { 00100 real centers_len = (mCenter - other.mCenter).length(); 00101 return (mRadius + epsilon >= centers_len + other.mRadius); 00102 } 00103 00104 bool contains(const Vector3<real>& pt) const { 00105 return ( (mCenter-pt).lengthSquared() <= mRadius*mRadius ); 00106 } 00107 00108 bool invalid() const { 00109 return (mRadius < 0); 00110 } 00111 00112 bool degenerate() const { 00113 return ( mRadius <= 0 ); 00114 } 00115 00116 real volume() const { 00117 if (degenerate()) return 0.0; 00118 real Pi = 3.1415926536;//cannot initialize in class due to nonintegral type VC++ err 00119 return 4.0 / 3.0 * Pi * mRadius * mRadius * mRadius; 00120 } 00121 00122 bool operator==(const BoundingSphere& rhs) { 00123 return (mCenter == rhs.mCenter && mRadius == rhs.mRadius); 00124 } 00125 bool operator!=(const BoundingSphere& rhs) { 00126 return (mCenter != rhs.mCenter || mRadius != rhs.mRadius); 00127 } 00128 }; 00129 00130 template<typename scalar> 00131 inline std::ostream& operator <<(std::ostream& os, const BoundingSphere<scalar> &rhs) { 00132 os << '<' << rhs.center() << ',' << rhs.radius() << '>'; 00133 return os; 00134 } 00135 00136 } 00137 #endif