PF_API 0.52
|
00001 00002 // Copyright (C) 2004-2011 Dylan Blair 00003 // 00004 // email: dblair@alumni.cs.utexas.edu 00005 // 00006 // This library is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // Lesser General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU Lesser General Public 00017 // License along with this library; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 00021 #ifndef MPOINT_H 00022 #define MPOINT_H 00023 00024 #include <string.h> //for memset() 00025 #include <algorithm> //for max() 00026 00027 #include "MFun.h" 00028 00029 namespace OpenSkyNet { 00030 namespace Math { 00032 template<class T=float, unsigned char U=3> 00033 class Point { 00034 const unsigned char _numDimensions; 00035 public: 00036 T _dimensions[U]; 00037 00038 Point(const T& x_=0, const T& y_=0, const T& z_=0) : _numDimensions(U) { 00039 assert(U >= 1); 00040 memset(_dimensions,0,sizeof(T)*U); 00041 switch (_numDimensions) { 00042 case 1: 00043 _dimensions[0] = x_; 00044 break; 00045 case 2: 00046 _dimensions[0] = x_; 00047 _dimensions[1] = y_; 00048 break; 00049 default: 00050 _dimensions[0] = x_; 00051 _dimensions[1] = y_; 00052 _dimensions[2] = z_; 00053 break; 00054 } 00055 } 00056 00057 Point(const Point<T>& p_) : _numDimensions(U) { 00058 for (unsigned char i = 0; i < _numDimensions; ++i) 00059 _dimensions[i] = p_._dimensions[i]; 00060 } 00061 00064 inline unsigned char getNumDimensions() const { return _numDimensions; } 00065 inline T& x() { return _dimensions[0]; } 00066 inline T& y() { return _dimensions[1]; } 00067 inline T& z() { return _dimensions[2]; } 00068 inline T& r() { return _dimensions[0]; } 00069 inline T& g() { return _dimensions[1]; } 00070 inline T& b() { return _dimensions[2]; } 00071 inline T& a() { return _dimensions[3]; } 00072 inline T& operator[](int i_) { return _dimensions[i_]; } 00073 inline const T& x() const { return _dimensions[0]; } 00074 inline const T& y() const { return _dimensions[1]; } 00075 inline const T& z() const { return _dimensions[2]; } 00076 inline const T& r() const { return _dimensions[0]; } 00077 inline const T& g() const { return _dimensions[1]; } 00078 inline const T& b() const { return _dimensions[2]; } 00079 inline const T& a() const { return _dimensions[3]; } 00080 inline const T& operator[](int i_) const { return _dimensions[i_]; } 00082 00086 inline Point<T> operator-() const { 00087 Point<T> result(*this); 00088 for (unsigned char i = 0; i < result._numDimensions; ++i) 00089 result._dimensions[i] = -result._dimensions[i]; 00090 return result; 00091 } 00092 00094 inline Point<T> getAbs() const { 00095 Point<T> result(*this); 00096 for (unsigned char i = 0; i < result._numDimensions; ++i) 00097 if (result._dimensions[i] < 0) 00098 result._dimensions[i] = -result._dimensions[i]; 00099 return result; 00100 } 00101 00103 inline T getComponentSum() const { 00104 T sum = 0; 00105 for (unsigned char i = 0; i < _numDimensions; ++i) 00106 sum += _dimensions[i]; 00107 return sum; 00108 } 00109 00111 inline T getMax() const { 00112 T max = _dimensions[0]; 00113 for (unsigned char i = 1; i < _numDimensions; ++i) 00114 if (_dimensions[i] > max) 00115 max = _dimensions[i]; 00116 return max; 00117 } 00118 00120 inline T getMin() const { 00121 T min = _dimensions[0]; 00122 for (unsigned char i = 1; i < _numDimensions; ++i) 00123 if (_dimensions[i] < min) 00124 min = _dimensions[i]; 00125 return min; 00126 } 00127 00129 inline T getLenSqrd() const { 00130 T length = 0; 00131 for (unsigned char i = 0; i < _numDimensions; ++i) 00132 length += _dimensions[i]*_dimensions[i]; 00133 return length; 00134 } 00135 00137 inline T getLength() const { return (static_cast<T>(sqrt(getLenSqrd()))); } 00138 00140 inline void normalize() { 00141 T lensqrd = getLenSqrd(); 00142 if (lensqrd) { 00143 T len = static_cast<T>(sqrt(lensqrd)); 00144 for (unsigned char i = 0; i < _numDimensions; ++i) 00145 _dimensions[i] /= len; 00146 } 00147 } 00149 00153 inline bool equals(const Point<T>& rhs_, T radiusSqrd_) const { 00154 if ((rhs_ - *this).getLenSqrd() > radiusSqrd_) 00155 return false; 00156 return true; 00157 } 00158 00160 inline Point<T,U>& operator=(const Point<T,U>& rhs_) { 00161 for (unsigned char i = 0; i < _numDimensions; ++i) 00162 _dimensions[i] = rhs_._dimensions[i]; 00163 return *this; 00164 } 00165 00167 inline Point<T>& operator+=(const Point<T>& rhs_) { 00168 for (unsigned char i = 0; i < rhs_._numDimensions; ++i) 00169 _dimensions[i] = _dimensions[i] + rhs_._dimensions[i]; 00170 return *this; 00171 } 00172 00174 inline Point<T>& operator+=(const T& rhs_) { 00175 for (unsigned char i = 0; i < _numDimensions; ++i) 00176 _dimensions[i] = _dimensions[i] + rhs_; 00177 return *this; 00178 } 00179 00181 inline Point<T>& operator-=(const Point<T>& rhs_) { return (*this)+=(-rhs_); } 00182 00184 inline Point<T>& operator-=(const T& rhs_) { 00185 for (unsigned char i = 0; i < _numDimensions; ++i) 00186 _dimensions[i] = _dimensions[i] - rhs_; 00187 return *this; 00188 } 00189 00191 inline Point<T>& operator*=(const T& rhs_) { 00192 for (unsigned char i = 0; i < _numDimensions; ++i) 00193 _dimensions[i] = _dimensions[i] * rhs_; 00194 return *this; 00195 } 00196 00198 inline Point<T> getCross3(const Point<T>& rhs_) const { 00199 return Point<T>(y()*rhs_.z() - z()*rhs_.y(), z()*rhs_.x() - x()*rhs_.z(), x()*rhs_.y() - y()*rhs_.x()); 00200 } 00201 00203 inline T getDot3(const Point<T>& rhs_) const { 00204 return (x()*rhs_.x() + y()*rhs_.y() + z()*rhs_.z()); 00205 } 00206 00208 inline Point<T> getReflection3(const Point<T>& n_) const { 00209 Point<T> projection(n_ * getDot3(n_)); 00210 return *this - (projection * 2.f); 00211 } 00213 }; 00214 00215 extern const Math::Point<> g_origin; 00216 extern const Math::Point<> g_xAxis; 00217 extern const Math::Point<> g_yAxis; 00218 extern const Math::Point<> g_zAxis; 00219 00221 template<class T, class U> 00222 inline bool operator==(const Point<T>& lhs_, const Point<U>& rhs_) { 00223 bool result = true; 00224 for (unsigned char i = 0; i < lhs_.getNumDimensions(); ++i) { 00225 if (lhs_._dimensions[i] != rhs_._dimensions[i]) { 00226 result = false; 00227 break; 00228 } 00229 } 00230 return result; 00231 } 00232 00234 template<class T, class U> 00235 inline bool operator!=(const Point<T>& lhs_, const Point<U>& rhs_) { return (!(lhs_ == rhs_)); } 00236 00238 template<class T, class U> 00239 inline Point<T> operator+(const Point<T>& lhs_, const Point<U>& rhs_) { 00240 unsigned char dimensToAdd = lhs_.getNumDimensions(); 00241 Point<T> result; 00242 for (unsigned char i = 0; i < dimensToAdd; ++i) 00243 result._dimensions[i] = lhs_._dimensions[i] + rhs_._dimensions[i]; 00244 return result; 00245 } 00246 00248 template<class T, class U> 00249 inline Point<T> operator-(const Point<T>& lhs_, const Point<U>& rhs_) { return (lhs_ + -rhs_); } 00250 00252 template<class T, class U> 00253 inline Point<T> operator*(const Point<T>& lhs_, const Point<U>& rhs_) { 00254 unsigned char dimensToMul = lhs_.getNumDimensions(); 00255 Point<T> result; 00256 for (unsigned char i = 0; i < dimensToMul; ++i) 00257 result._dimensions[i] = lhs_._dimensions[i] * rhs_._dimensions[i]; 00258 return result; 00259 } 00260 00262 template<class T, class U> 00263 inline Point<T> operator/(const Point<T>& lhs_, const Point<U>& rhs_) { 00264 unsigned char dimensToDiv = lhs_.getNumDimensions(); 00265 Point<T> result; 00266 for (unsigned char i = 0; i < dimensToDiv; ++i) 00267 result._dimensions[i] = lhs_._dimensions[i] / rhs_._dimensions[i]; 00268 return result; 00269 } 00270 00272 template<class T, class U> 00273 inline Point<T> operator*(const Point<T>& lhs_, const U& rhs_) { 00274 Point<T> result; 00275 for (unsigned char i = 0; i < lhs_.getNumDimensions(); ++i) 00276 result._dimensions[i] = lhs_._dimensions[i] * rhs_; 00277 return result; 00278 } 00279 00281 template<class T, class U> 00282 inline Point<T> operator/(const Point<T>& lhs_, const U& rhs_) { 00283 Point<T> result; 00284 for (unsigned char i = 0; i < lhs_.getNumDimensions(); ++i) 00285 result._dimensions[i] = lhs_._dimensions[i] / rhs_; 00286 return result; 00287 } 00288 00290 template<class T, class U> 00291 inline T getLength(const Point<T>& lhs_, const Point<U>& rhs_) { return (rhs_ - lhs_).getLength(); } 00292 00298 template<class T, class U> 00299 inline Point<T> interpolate(const Point<T>& lhs_, const Point<U>& rhs_, float amount_) { 00300 Math::clamp<float>(amount_); 00301 return Point<T>((lhs_ * (1.0f - amount_)) + (rhs_ * amount_)); 00302 } 00303 00311 inline Point<float,2> RandPointInOrOnCircle(float radius_) { 00312 Point<float,2> p; 00313 const float radiusSqrd = radius_ * radius_; 00314 00315 //the probability of needing more than k tries is (1-PI/4)^k. For k=20, this is ~ 0.00000000000004 00316 for (int n = 0; n < 20; ++n) { 00317 p.x() = radius_ * randNeg1Pos1(); 00318 p.y() = radius_ * randNeg1Pos1(); 00319 if (p.getLenSqrd() <= radiusSqrd) 00320 return p; 00321 } 00322 00323 float rads = 2.0f * PI * rand01(); 00324 float dist = rand01() + rand01(); 00325 if (dist > 1.f) 00326 dist = 2.f - dist; 00327 00328 p.x() = radius_ * dist * cosf(rads); 00329 p.y() = radius_ * dist * sinf(rads); 00330 00331 return p; 00332 } 00333 } 00334 } 00335 00336 #endif //MPOINT_H