CoordGeom.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include <math.h>
00024 #include "CoordGeom.h"
00025 
00026 #define EPSILON (1e-7)
00027 #define BIGNUMBER (1e+9)
00028 #define IsZero(d) (fabs(d) < EPSILON)
00029 
00030 //
00031 // Vector
00032 //
00033 
00034 Vector::Vector(double x, double y, double z)
00035 {
00036         this->x = x;
00037         this->y = y;
00038         this->z = z;
00039 }
00040 
00041 void Vector::Set(double x, double y, double z)
00042 {
00043         this->x = x;
00044         this->y = y;
00045         this->z = z;
00046 }
00047 
00048 double Vector::Length()
00049 {
00050         return(sqrt(x * x + y * y + z * z));
00051 }
00052 
00053 double Vector::Sum()
00054 {
00055         return(x + y + z);
00056 }
00057 
00058 double Vector::CrossSum()
00059 {
00060         return(x*y + x*z + y*z);
00061 }
00062 
00063 Vector Vector::Cross()
00064 {
00065         return(Vector(x*y, x*z, y*z));
00066 }
00067 
00068 Vector Vector::Pow(double exp)
00069 {
00070         return(exp == 0 ? Vector(1, 1, 1) : exp == 1 ? *this : Vector(pow(x, exp), pow(y, exp), pow(z, exp)));
00071 }
00072 
00073 Vector Vector::Unit()
00074 {
00075         double l = Length();
00076         if(!l || l == 1) return(*this);
00077         return(*this * (1 / l));
00078 }
00079 
00080 Vector& Vector::Unitalize()
00081 {
00082         return(*this = Unit());
00083 }
00084 
00085 Vector Vector::Normal(Vector& a, Vector& b)
00086 {
00087         return((a - *this) % (b - a));
00088 }
00089 
00090 double Vector::Angle(Vector& a, Vector& b)
00091 {
00092         return(((a - *this).Unit()).Angle((b - *this).Unit()));
00093 }
00094 
00095 double Vector::Angle(Vector& a)
00096 {
00097         double angle = *this | a;
00098         return((angle > 1) ? 0 : (angle < -1) ? PI : acos(angle));
00099 }
00100 
00101 void Vector::Angle(double& u, double& v)
00102 {
00103         Vector n = Unit();
00104 
00105         u = asin(n.y);
00106 
00107         if(IsZero(n.z)) v = PI/2 * Sgn(n.x);
00108         else if(n.z > 0) v = atan(n.x / n.z);
00109         else if(n.z < 0) v = IsZero(n.x) ? PI : (PI * Sgn(n.x) + atan(n.x / n.z));
00110 }
00111 
00112 Vector Vector::Angle()
00113 {
00114         Vector ret;
00115         Angle(ret.x, ret.y);
00116         ret.z = 0;
00117         return(ret);
00118 }
00119 
00120 Vector& Vector::Min(Vector& a)
00121 {
00122         x = (x < a.x) ? x : a.x;
00123         y = (y < a.y) ? y : a.y;
00124         z = (z < a.z) ? z : a.z;
00125         return(*this);
00126 }
00127 
00128 Vector& Vector::Max(Vector& a)
00129 {
00130         x = (x > a.x) ? x : a.x;
00131         y = (y > a.y) ? y : a.y;
00132         z = (z > a.z) ? z : a.z;
00133         return(*this);
00134 }
00135 
00136 Vector Vector::Abs()
00137 {
00138         return(Vector(fabs(x), fabs(y), fabs(z)));
00139 }
00140 
00141 Vector Vector::Reflect(Vector& n)
00142 {
00143         return(n * ((-*this) | n) * 2 - (-*this));
00144 }
00145 
00146 Vector Vector::Refract(Vector& N, double nFront, double nBack, double* nOut)
00147 {
00148         Vector D = -*this;
00149 
00150         double N_dot_D = (N | D);
00151         double n = N_dot_D >= 0 ? (nFront / nBack) : (nBack / nFront);
00152 
00153         Vector cos_D = N * N_dot_D;
00154         Vector sin_T = (cos_D - D) * n;
00155 
00156         double len_sin_T = sin_T | sin_T;
00157 
00158         if(len_sin_T > 1) 
00159         {
00160                 if(nOut) {*nOut = N_dot_D >= 0 ? nFront : nBack;}
00161                 return((*this).Reflect(N));
00162         }
00163 
00164         double N_dot_T = sqrt(1.0 - len_sin_T);
00165         if(N_dot_D < 0) N_dot_T = -N_dot_T;
00166 
00167         if(nOut) {*nOut = N_dot_D >= 0 ? nBack : nFront;}
00168 
00169         return(sin_T - (N * N_dot_T));
00170 }
00171 
00172 Vector Vector::Refract2(Vector& N, double nFrom, double nTo, double* nOut)
00173 {
00174         Vector D = -*this;
00175 
00176         double N_dot_D = (N | D);
00177         double n = nFrom / nTo;
00178 
00179         Vector cos_D = N * N_dot_D;
00180         Vector sin_T = (cos_D - D) * n;
00181 
00182         double len_sin_T = sin_T | sin_T;
00183 
00184         if(len_sin_T > 1) 
00185         {
00186                 if(nOut) {*nOut = nFrom;}
00187                 return((*this).Reflect(N));
00188         }
00189 
00190         double N_dot_T = sqrt(1.0 - len_sin_T);
00191         if(N_dot_D < 0) N_dot_T = -N_dot_T;
00192 
00193         if(nOut) {*nOut = nTo;}
00194 
00195         return(sin_T - (N * N_dot_T));
00196 }
00197 
00198 double Vector::operator | (Vector& v)
00199 {
00200         return(x * v.x + y * v.y + z * v.z);
00201 }
00202 
00203 Vector Vector::operator % (Vector& v)
00204 {
00205         return(Vector(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x));
00206 }
00207 
00208 double& Vector::operator [] (int i)
00209 {
00210         return(!i ? x : (i == 1) ? y : z);
00211 }
00212 
00213 Vector Vector::operator - ()
00214 {
00215         return(Vector(-x, -y, -z));
00216 }
00217 
00218 bool Vector::operator == (const Vector& v) const
00219 {
00220         if(IsZero(x - v.x) && IsZero(y - v.y) && IsZero(z - v.z)) return(true);
00221         return(false);
00222 }
00223 
00224 bool Vector::operator != (const Vector& v) const
00225 {
00226         return((*this == v) ? false : true);
00227 }
00228 
00229 Vector Vector::operator + (double d)
00230 {
00231         return(Vector(x + d, y + d, z + d));
00232 }
00233 
00234 Vector Vector::operator + (Vector& v)
00235 {
00236         return(Vector(x + v.x, y + v.y, z + v.z));
00237 }
00238 
00239 Vector Vector::operator - (double d)
00240 {
00241         return(Vector(x - d, y - d, z - d));
00242 }
00243 
00244 Vector Vector::operator - (Vector& v)
00245 {
00246         return(Vector(x - v.x, y - v.y, z - v.z));
00247 }
00248 
00249 Vector Vector::operator * (double d)
00250 {
00251         return(Vector(x * d, y * d, z * d));
00252 }
00253 
00254 Vector Vector::operator * (Vector& v)
00255 {
00256         return(Vector(x * v.x, y * v.y, z * v.z));
00257 }
00258 
00259 Vector Vector::operator / (double d)
00260 {
00261         return(Vector(x / d, y / d, z / d));
00262 }
00263 
00264 Vector Vector::operator / (Vector& v)
00265 {
00266         return(Vector(x / v.x, y / v.y, z / v.z));
00267 }
00268 
00269 Vector& Vector::operator += (double d)
00270 {
00271         x += d; y += d; z += d;
00272         return(*this);
00273 }
00274 
00275 Vector& Vector::operator += (Vector& v)
00276 {
00277         x += v.x; y += v.y; z += v.z;
00278         return(*this);
00279 }
00280 
00281 Vector& Vector::operator -= (double d)
00282 {
00283         x -= d; y -= d; z -= d;
00284         return(*this);
00285 }
00286 
00287 Vector& Vector::operator -= (Vector& v)
00288 {
00289         x -= v.x; y -= v.y; z -= v.z;
00290         return(*this);
00291 }
00292 
00293 Vector& Vector::operator *= (double d)
00294 {
00295         x *= d; y *= d; z *= d;
00296         return(*this);
00297 }
00298 
00299 Vector& Vector::operator *= (Vector& v)
00300 {
00301         x *= v.x; y *= v.y; z *= v.z;
00302         return(*this);
00303 }
00304 
00305 Vector& Vector::operator /= (double d)
00306 {
00307         x /= d; y /= d; z /= d;
00308         return(*this);
00309 }
00310 
00311 Vector& Vector::operator /= (Vector& v)
00312 {
00313         x /= v.x; y /= v.y; z /= v.z;
00314         return(*this);
00315 }
00316 
00317 //
00318 // Ray
00319 //
00320 
00321 Ray::Ray(Vector& p, Vector& d)
00322 {
00323         this->p = p;
00324         this->d = d;
00325 }
00326 
00327 void Ray::Set(Vector& p, Vector& d)
00328 {
00329         this->p = p;
00330         this->d = d;
00331 }
00332 
00333 double Ray::GetDistanceFrom(Ray& r)
00334 {
00335         double t = (d | r.d);
00336         if(IsZero(t)) return(-BIGNUMBER); // plane is paralell to the ray, return -infinite
00337         return(((r.p - p) | r.d) / t);
00338 }
00339 
00340 double Ray::GetDistanceFrom(Vector& v)
00341 {
00342         double t = ((v - p) | d) / (d | d);
00343         return(((p + d*t) - v).Length());
00344 }
00345 
00346 Vector Ray::operator [] (double t)
00347 {
00348         return(p + d*t);
00349 }
00350 
00351 //
00352 // XForm
00353 //
00354 
00355 XForm::XForm(Ray& r, Vector& s, bool isWorldToLocal)
00356 {
00357         Initalize(r, s, isWorldToLocal);
00358 }
00359 
00360 void XForm::Initalize()
00361 {
00362         m.Initalize();
00363 }
00364 
00365 void XForm::Initalize(Ray& r, Vector& s, bool isWorldToLocal)
00366 {
00367         Initalize();
00368 
00369         if(m_isWorldToLocal = isWorldToLocal)
00370         {
00371                 *this -= r.p;
00372                 *this >>= r.d;
00373                 *this /= s;
00374 
00375         }
00376         else
00377         {
00378                 *this *= s;
00379                 *this <<= r.d;
00380                 *this += r.p;
00381         }
00382 }
00383 
00384 void XForm::operator *= (Vector& v)
00385 {
00386         Matrix s;
00387         s.mat[0][0] = v.x;
00388         s.mat[1][1] = v.y;
00389         s.mat[2][2] = v.z;
00390         m *= s;
00391 }
00392 
00393 void XForm::operator += (Vector& v)
00394 {
00395         Matrix t;
00396         t.mat[3][0] = v.x;
00397         t.mat[3][1] = v.y;
00398         t.mat[3][2] = v.z;
00399         m *= t;
00400 }
00401 
00402 void XForm::operator <<= (Vector& v)
00403 {
00404         Matrix x;
00405         x.mat[1][1] = cos(v.x); x.mat[1][2] = -sin(v.x);
00406         x.mat[2][1] = sin(v.x); x.mat[2][2] = cos(v.x);
00407 
00408         Matrix y;
00409         y.mat[0][0] = cos(v.y); y.mat[0][2] = -sin(v.y);
00410         y.mat[2][0] = sin(v.y); y.mat[2][2] = cos(v.y);
00411 
00412         Matrix z;
00413         z.mat[0][0] = cos(v.z); z.mat[0][1] = -sin(v.z);
00414         z.mat[1][0] = sin(v.z); z.mat[1][1] = cos(v.z);
00415 
00416         m = m_isWorldToLocal ? (m * y * x * z) : (m * z * x * y);
00417 }
00418 
00419 void XForm::operator /= (Vector& v)
00420 {
00421         Vector s;
00422         s.x = IsZero(v.x) ? 0 : 1 / v.x;
00423         s.y = IsZero(v.y) ? 0 : 1 / v.y;
00424         s.z = IsZero(v.z) ? 0 : 1 / v.z;
00425         *this *= s;
00426 }
00427 
00428 void XForm::operator -= (Vector& v)
00429 {
00430         *this += -v;
00431 }
00432 
00433 void XForm::operator >>= (Vector& v)
00434 {
00435         *this <<= -v;
00436 }
00437 
00438 Vector XForm::operator < (Vector& n)
00439 {
00440         Vector ret;
00441 
00442         ret.x = n.x * m.mat[0][0] +
00443                         n.y * m.mat[1][0] +
00444                         n.z * m.mat[2][0];
00445         ret.y = n.x * m.mat[0][1] +
00446                         n.y * m.mat[1][1] +
00447                         n.z * m.mat[2][1];
00448         ret.z = n.x * m.mat[0][2] +
00449                         n.y * m.mat[1][2] +
00450                         n.z * m.mat[2][2];
00451 
00452         return(ret);
00453 }
00454 
00455 Vector XForm::operator << (Vector& v)
00456 {
00457         Vector ret;
00458 
00459         ret.x = v.x * m.mat[0][0] +
00460                         v.y * m.mat[1][0] +
00461                         v.z * m.mat[2][0] +
00462                         m.mat[3][0];
00463         ret.y = v.x * m.mat[0][1] +
00464                         v.y * m.mat[1][1] +
00465                         v.z * m.mat[2][1] +
00466                         m.mat[3][1];
00467         ret.z = v.x * m.mat[0][2] +
00468                         v.y * m.mat[1][2] +
00469                         v.z * m.mat[2][2] +
00470                         m.mat[3][2];
00471 
00472         return(ret);
00473 }
00474 
00475 Ray XForm::operator << (Ray& r)
00476 {
00477         return(Ray(*this << r.p, *this < r.d));
00478 }
00479 
00480 //
00481 // XForm::Matrix
00482 //
00483 
00484 XForm::Matrix::Matrix()
00485 {
00486         Initalize();
00487 }
00488 
00489 void XForm::Matrix::Initalize()
00490 {
00491         mat[0][0] = 1; mat[0][1] = 0; mat[0][2] = 0; mat[0][3] = 0;
00492         mat[1][0] = 0; mat[1][1] = 1; mat[1][2] = 0; mat[1][3] = 0;
00493         mat[2][0] = 0; mat[2][1] = 0; mat[2][2] = 1; mat[2][3] = 0;
00494         mat[3][0] = 0; mat[3][1] = 0; mat[3][2] = 0; mat[3][3] = 1;
00495 }
00496 
00497 XForm::Matrix XForm::Matrix::operator * (Matrix& m)
00498 {
00499         Matrix ret;
00500 
00501         for(int i = 0; i < 4; i++)
00502         {
00503                 for(int j = 0; j < 4; j++)
00504                 {
00505                         ret.mat[i][j] = mat[i][0] * m.mat[0][j] +
00506                                                         mat[i][1] * m.mat[1][j] +
00507                                                         mat[i][2] * m.mat[2][j] +
00508                                                         mat[i][3] * m.mat[3][j];
00509 
00510                         if(IsZero(ret.mat[i][j])) ret.mat[i][j] = 0;
00511                 }
00512         }
00513 
00514         return(ret);
00515 }
00516 
00517 XForm::Matrix& XForm::Matrix::operator *= (XForm::Matrix& m)
00518 {
00519         return(*this = *this * m);
00520 }

Generated on Tue Dec 13 14:47:53 2005 for guliverkli by  doxygen 1.4.5