Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

trigo.h

Go to the documentation of this file.
00001 /* ***********************************************************************************
00002         Writer:         Sebastien Bloc
00003         Copyright:      2003-2004
00004         eMail:          sebastien.bloc@free.fr
00005         URL:            http://mignonsoft.free.fr
00006 
00007         This program is free software; you can redistribute it and/or
00008         modify it under the terms of the GNU General Public License
00009         as published by the Free Software Foundation; either version 2
00010         of the License, or (at your option) any later version.
00011 
00012         This program is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016         http://www.gnu.org/copyleft/gpl.html
00017 *********************************************************************************** */
00018 
00023 #ifndef INCLUDE_TRIGO_H
00024 #define INCLUDE_TRIGO_H
00025 
00026 #include <math.h>
00027 #include <windows.h> // POINT
00028 
00029 #define PI                              3.1415926535f
00030 #define DOUBLE_PI               (PI*2.0f)
00031 #define HALF_PI                 (PI/2.0f)
00032 #define PRECISION               0.0001      // pour les calculs de IsOnXXXXX() : valeur par defaut
00033 #define DEGTORAD(ang) ((ang) * PI / 180.0)
00034 #define RADTODEG(ang) ((ang) * 180.0/ PI) 
00035 
00036 double  Bound2_PI(double angle);
00037 BOOL    GetTrigoSens(POINT *pt);
00038 BOOL    GetTrigoSens(POINT *pt,int nbPoints);
00039 void    ChangeTrigoSens(POINT *pt,int nbPoints);
00040 int             GetNearExp2(int num);
00041 
00042 template <class T> class Point3D; 
00046 template <class T> class Point1D 
00047 {
00048 public:
00049         T value;
00050 
00051 public:
00052         Point1D() { Zero(); }
00053         Point1D(T _value) { value=_value; }
00054         void Zero() { value=0; }
00055         BOOL operator==(Point1D<T> &src) { return (value==src.value); }
00056         void operator=(Point1D<T> &src) { value=src.value; }
00057         void operator=(T _value) { value=_value; }
00058         //void operator+=(T _value) { value+=_value; }
00059         //void operator-=(T _value) { value-=_value; }
00060         //void operator/=(T _value) { value/=_value; }
00061         //void operator*=(T _value) { value*=_value; }
00062         T operator+(T _value) { T t; t = value+_value; return t; }
00063         T operator-(T _value) { T t; t = value-_value; return t; }
00064         double operator/(double coef) { return value/coef; }
00065         double operator*(double coef) { return value*coef; }
00066         operator T() const { return value; }
00067         double LinearInterpolation(T value1,T value2,double alpha);
00068 };
00069 
00073 template <class T> class Point2D 
00074 {
00075 public:
00076         T x;
00077         T y;
00078 
00079 public:
00080         Point2D() { Zero(); }
00081         Point2D(T _x,T _y) { Set(_x,_y); }
00082         void Set (T _x,T _y) { x=_x; y=_y; }
00083         void Zero() { x=0; y=0; }
00084         BOOL operator==(Point2D<T> &src) { return (x==src.x)&&(y==src.y); }
00085         BOOL operator!=(Point2D<T> &src) { return !((x==src.x)&&(y==src.y)); }
00086         void operator=(Point3D<T> &src);
00087         void operator=(Point2D<T> &src) { x=src.x; y=src.y; }
00088         void operator+=(Point2D<T> &src) { x+=src.x; y+=src.y; }
00089         Point2D<T> operator-(Point2D<T> &src);
00090         Point2D<T> operator+(Point2D<T> &src);
00091         Point2D<T> operator*(double coef);
00092         Point2D<T> operator/(double coef);
00093         void operator/=(double coef) { x/=coef; y/=coef;        }
00094         void operator*=(double coef) { x*=coef; y*=coef;        }
00095         double Power() { return sqrt(x*x+y*y); }
00096 
00097         BOOL IsOnSegment(Point2D<T> &a,Point2D<T> &b,double *alpha=NULL);
00098         BOOL IsOnLine(Point2D<T> &a,Point2D<T> &b,double *alpha=NULL,double precision=PRECISION);
00099         BOOL IsOnTriangle(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,double *alphaBC,double *alphaAPP,Point2D<T> *pp=NULL);
00100         BOOL IsOnQuadrilatere(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *alphaX=NULL,double *alphaY=NULL);
00101         BOOL IsOnRectangle(Point2D<T> &a,Point2D<T> &c,double *alphaX=NULL,double *alphaY=NULL);
00102 
00103         BOOL GetRelativePtOnQuadrilatere(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *deltaX,double *deltaY);
00104         BOOL GetRelativePtOn2Lines(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *alpha);
00105 
00106         void ToNormalVector(BOOL asTrigo=TRUE);
00107 };
00108 
00109 
00110 #include "include/quaternion.h"
00111 
00116 template <class T> class Point3D 
00117 {
00118 public:
00119         T x;
00120         T y;
00121         T z;
00122 
00123 public:
00124         Point3D() { Zero(); }
00125         Point3D(T _x,T _y,T _z) { Set(_x,_y,_z); }
00126 
00127         void Set (T _x,T _y,T _z=0) { x=_x; y=_y; z=_z; }
00128         void Zero() { x=0; y=0; z=0; }
00129         BOOL IsEqual(T _x,T _y,T _z) { return (x==_x)&&(y==_y)&&(z==_z); }
00130         BOOL operator==(Point3D<T> &src) { return (x==src.x)&&(y==src.y)&&(z==src.z); }
00131         void operator=(Point3D<T> &src);
00132         void Add(T _x,T _y,T _z);
00133         void operator+=(Point3D<T> &src);
00134         void operator/=(double divide);
00135 
00136         void glRotated(double ratio);
00137         void glRotated();
00138         void glTranslated(double ratio);
00139         void glTranslated();
00140         void glRasterPos() { glRasterPos3d(x,y,z); }
00141         void glScale() { glScaled(x,y,z); }
00142 
00143         double Power() { return sqrt(x*x+y*y+z*z); }
00144         Point3D<T> QuaternionRotate (Point3D<T> &rotate);
00145         void operator=(Point2D<T> &src);
00146         BOOL IsOnTriangle(Point3D<T> &a,Point3D<T> &b,Point3D<T> &c);
00147         BOOL IsNotNull() { return (x||y||z)?TRUE:FALSE; }
00148 };
00149 
00161 template <class T> 
00162 class LinearEqu2D
00163 {
00164 private:
00165         void Compute()
00166         {
00167                 a=pt1.y-pt2.y;
00168                 b=pt2.x-pt1.x;
00169                 c=-(pt1.x*a+pt1.y*b); // <=> xa(yb-ya)-ya(xb-xa)
00170         }
00171 
00172         double a,b,c;
00173         Point2D<T> pt1,pt2;
00174 
00175 public:
00176         LinearEqu2D() { Zero(); }
00177         LinearEqu2D(Point2D<T> &_pt1,Point2D<T> &_pt2) { Set(_pt1,_pt2); }
00178 
00179         void Zero()
00180         {
00181                 pt1.Zero();
00182                 pt2.Zero();
00183                 a=b=c=0;
00184         }
00185 
00186         void Set(Point2D<T> &_pt1,Point2D<T> &_pt2)
00187         {
00188                 pt1=_pt1;
00189                 pt2=_pt2;
00190                 Compute();
00191         }
00192 
00193         BOOL IsPoint() { return a||b?TRUE:FALSE; }
00194         BOOL IsVertical() { return a&&!b?TRUE:FALSE; }
00195         BOOL IsHorizontal() { return !a&&b?TRUE:FALSE; }
00196 
00197         BOOL GetCrossPtFromVertical(T x,Point2D<T> *pt=NULL)
00198         {       // donne le point a l'intesections de la ligne en cours et une vertical donnée
00199                 Point2D<T> ptv1(x,0);
00200                 Point2D<T> ptv2(x,10);          
00201                 LinearEqu2D<T> vertEqu(ptv1,ptv2);
00202                 return GetCrossPtFromLine(vertEqu,pt);
00203         }
00204 
00205         BOOL GetCrossPtFromHorizontal(T y,Point2D<T> *pt=NULL)
00206         {       // donne le point a l'intesections de la ligne en cours et une vertical donnée
00207                 Point2D<T> pth1(0,y);
00208                 Point2D<T> pth2(10,y);          
00209                 LinearEqu2D<T> horiEqu(pth1,pth2);
00210                 return GetCrossPtFromLine(horiEqu,pt);
00211         }
00231         BOOL GetCrossPtFromLine(LinearEqu2D<T> &equ,Point2D<T> *pt=NULL)
00232         {   // donne le point a l'interections des 2 lignes definis par leurs equation
00233                 Point2D<T> _pt;
00234                 if (!pt) pt=&_pt;
00235                 if (!ComputePtFromeLine(*this,equ,pt)) 
00236                         return ComputePtFromeLine(equ,*this,pt);
00237                 else return TRUE;
00238                 return TRUE;
00239         }
00240 
00241 private:
00242         BOOL ComputePtFromeLine(LinearEqu2D<T> &equ1,LinearEqu2D<T> &equ2,Point2D<T> *pt)
00243         {
00244                 T denominateur = ((equ2.a*equ1.b)-(equ1.a*equ2.b));
00245                 if (!denominateur) return FALSE; // pas de solution
00246                 pt->y = ((equ1.a*equ2.c)-(equ2.a*equ1.c))/denominateur;
00247                 if (!equ2.a) return FALSE;// la 2 eme equations et horizontal donc une infinité de solution sur equ
00248                 pt->x = ((equ2.b*pt->y)+equ2.c)/-equ2.a;
00249                 return TRUE;
00250         }
00251 };
00252 
00253 // Point1D implementation ********************************************************
00254 
00255 template <class T>
00256 double Point1D<T>::LinearInterpolation(T value1,T value2,double alpha)
00257 {
00258         value= value1+(double)(value2-value1)*alpha;
00259         return value;
00260 }
00261 
00262 // Point2D implementation ********************************************************
00263 
00264 template <class T>
00265 Point2D<T> Point2D<T>::operator-(Point2D<T> &src)
00266 {
00267         Point2D<T> pt;
00268         pt.x=x-src.x;
00269         pt.y=y-src.y;
00270         return pt;
00271 }
00272 
00273 template <class T>
00274 Point2D<T> Point2D<T>::operator+(Point2D<T> &src)
00275 {
00276         Point2D<T> pt;
00277         pt.x=x+src.x;
00278         pt.y=y+src.y;
00279         return pt;
00280 }
00281 
00282 template <class T>
00283 Point2D<T> Point2D<T>::operator*(double coef)
00284 {
00285         Point2D<T> pt;
00286         pt.x=(T)(x*coef);
00287         pt.y=(T)(y*coef);
00288         return pt;
00289 }
00290 
00291 template <class T>
00292 Point2D<T> Point2D<T>::operator/(double coef)
00293 {
00294         Point2D<T> pt;
00295         pt.x=(T)(x/coef);
00296         pt.y=(T)(y/coef);
00297         return pt;
00298 }
00299 
00300 template <class T>
00301 void Point2D<T>::operator=(Point3D<T> &src)
00302 {
00303         x=src.x;
00304         y=src.y;
00305 }
00306 
00307 /* Determine si un point (p) est sur la tragectoire d'un segment [ab] ******************
00308 Si un pointeur alhpa est donnée, et si il y a interesection, donne le pourcentage
00309 de la position d'intersection par rapport ou point (a)
00310 Ex.:
00311 alpha = 0; p = a
00312 alpha = 1; p = b
00313 alpha = 0.5; p.x= (b.x+a.x)/2; p.y = (b.y+a.y)/2
00314 ************************************************************************************* */
00315 
00316 template <class T>
00317 BOOL Point2D<T>::IsOnSegment(Point2D<T> &a,Point2D<T> &b,double *alpha)
00318 {
00319         double _alpha;
00320         if (!alpha) alpha=&_alpha;
00321         if (IsOnLine(a,b,alpha)) return ((*alpha>=0)&&(*alpha<=1))?TRUE:FALSE;
00322         return FALSE;
00323 }
00324 
00325 template <class T>
00326 BOOL Point2D<T>::IsOnLine(Point2D<T> &a,Point2D<T> &b,double *alpha,double precision)
00327 {
00328         double dx = b.x-a.x;
00329         double dy = b.y-a.y;
00330         if (!dx&&!dy)
00331         {       // a et b sont confondu
00332                 if (a==*this)
00333                 {
00334                         if (alpha) *alpha = 0; // en fait infinit de solution car les 2 points sont confondu
00335                         return TRUE;
00336                 }
00337                 return FALSE;
00338         }
00339 
00340         double dxap = x-a.x;
00341         double dyap = y-a.y;
00342         double reste=dxap*dy-dyap*dx;
00343         if (fabs(reste)<=precision)
00344         {
00345                 if (alpha) 
00346                 {
00347                         if (dx) *alpha = dxap/dx;
00348                         else if (dy) *alpha = dyap/dy;
00349                         else *alpha = 0; // en fait infinit de solution car les 2 points sont confondu
00350                 }
00351                 return TRUE;
00352         }
00353         return FALSE;
00354 }
00355 
00356 /* consitere le point comme un vecteur, on peut alors en faire une rotation a 90° ******
00357 en sens trigonometirque ou horaire
00358 ************************************************************************************* */
00359 
00360 template <class T>
00361 void Point2D<T>::ToNormalVector(BOOL asTrigo)
00362 {
00363         T temp = x;
00364         if (asTrigo)
00365         {
00366                 x = -y;
00367                 y = temp;
00368         }
00369         else 
00370         {
00371                 x = y;
00372                 y = -temp;
00373         }
00374 }
00375 
00392 template <class T>
00393 BOOL Point2D<T>::IsOnTriangle(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,double *alphaBC,double *alphaAPP,Point2D<T> *pp)
00394 {
00395         Point2D<T> _pp;
00396         Point1D<T> interpolation;
00397         double _alphaBC,_alphaAPP;
00398         if (!alphaAPP) alphaAPP=&_alphaAPP;
00399         if (!alphaBC) alphaBC=&_alphaBC;
00400         if (!pp) pp=&_pp;
00401 
00402         // etape 1: calcul du point PP
00403         LinearEqu2D<T> equAP(a,*this);  // equation de [AP]
00404         LinearEqu2D<T> equBC(b,c);              // equation de [BC]
00405         if (!equAP.GetCrossPtFromLine(equBC,pp)) return FALSE;
00406         // etape 2: calcul de l'alpha de P' sur segment [BC]
00407         if (!pp->IsOnSegment(b,c,alphaBC)) return FALSE;
00408         // etape 3: calcul de l'alpha de P sur segment [AP']
00409         if (!IsOnSegment(a,*pp,alphaAPP)) return FALSE;
00410         return TRUE;
00411 }
00412 
00414 
00415 template <class T>
00416 BOOL Point2D<T>::IsOnRectangle(Point2D<T> &a,Point2D<T> &c,double *alphaX,double *alphaY)
00417 {
00418         Point2D<T> b(c.x,a.y),Point2D<T> d(a.x,c.y);
00419         return IsOnQuadrilatere(a,b,c,d,alphaX,alphaY);
00420 }
00421 
00423 
00424 template <class T>
00425 BOOL Point2D<T>::IsOnQuadrilatere(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *alphaX,double *alphaY)
00426 {
00427         double _alphaX,_alphaY;
00428         if (!alphaX) _alphaX=&alphaX;
00429         if (!alphaY) _alphaY=&alphaY;
00430         BOOL res = GetRelativePtOnQuadrilatere(a,b,c,d,&_alphaX,&_alphaY);
00431         return (!res||*alphaX<0||*alphaY<0)?FALSE:TRUE; 
00432 }
00433 
00459 template <class T>
00460 BOOL Point2D<T>::GetRelativePtOnQuadrilatere(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *alphaX,double *alphaY)
00461 {
00462         double _alphaX,_alphaY;
00463         if (!alphaX) alphaX=&_alphaX;
00464         if (!alphaY) alphaY=&_alphaY;
00465 
00466         // calcul de alpha
00467         if (!GetRelativePtOn2Lines(a,b,d,c,alphaX)) return FALSE;
00468         if (!GetRelativePtOn2Lines(a,d,b,c,alphaY)) return FALSE;
00469         return TRUE;
00470 }
00471 
00472 template <class T>
00473 BOOL Point2D<T>::GetRelativePtOn2Lines(Point2D<T> &a,Point2D<T> &b,Point2D<T> &c,Point2D<T> &d,double *alpha)
00474 {
00475         double _alpha;
00476         if (!alpha) alpha=&_alpha;
00477 
00478         // calcul des constante de l'eqation: _a*alpha^2+_b*alpha+_c=0
00479         double _a,_b,_c;
00480         _a = 
00481                 (a.y-b.y)*(d.x-c.x)
00482                 -(a.x-b.x)*(d.y-c.y);
00483         _b = 
00484                 (a.y-b.y)*(c.x-a.x)
00485                 -(a.x-b.x)*(c.y-a.y)
00486                 +(a.x-b.x-c.x+d.x)*(y-a.y)
00487                 -(a.y-b.y-c.y+d.y)*(x-a.x);
00488         _c = 
00489                 (y-a.y)*(c.x-a.x)
00490                 -(x-a.x)*(c.y-a.y);
00491 
00492         // resolution des eventuel solution de alpha
00493         if (!_a) 
00494         {       // l'equation n'est plus du 2°degrée donc un solution simple
00495                 if (!_b) return FALSE;
00496                 *alpha=-_c/_b;
00497         }
00498         else
00499         {       // l'eqution est du 2°degrée 
00500                 // solution1 donne P inclus dans [P1,P2]
00501                 // solution2 donné apres intersection des 2 droites
00502                 double delta=_b*_b-4.0*_a*_c;
00503                 if (delta<0) return FALSE; // pas de solution
00504                 double alpha1,alpha2;
00505                 double sqrtdelta = sqrt(delta);
00506                 alpha1 = (-_b-sqrtdelta)/(2.0*_a); 
00507                 alpha2 = (-_b+sqrtdelta)/(2.0*_a); 
00508 
00509                 if (fabs(alpha1)<fabs(alpha2)) *alpha=alpha1;
00510                 else *alpha=alpha2;
00511                 //Point2D<double> p1((b.x-a.x)*alpha1+a.x,(b.y-a.y)*alpha1+a.y);
00512                 //Point2D<double> p2((d.x-c.x)*alpha1+c.x,(d.y-c.y)*alpha1+c.y);
00513                 //if (IsOnLine(p1,p2)) *alpha = alpha1; 
00514                 //else *alpha = alpha2;
00515                 /*
00516                 // test alpha pour savoir si P1=P2
00517                 double precision_rest = 0.000001;
00518                 double restX = alpha1*(b.x-a.x-d.x+c.x)-c.x+a.x;
00519                 double restY = alpha1*(b.y-a.y-d.y+c.y)-c.y+a.y;
00520                 if (fabs(restX)<precision_rest&&fabs(restY)<precision_rest) 
00521                          *alpha = alpha2; // alpha1 fait que P1=P2
00522                 else *alpha = alpha1; // alpha2 fait que P1=P2
00523                 */
00524         }
00525         return TRUE;
00526 }
00527 
00528 
00529 // Point3D implementation ********************************************************
00530 
00531 template <class T>
00532 Point3D<T> Point3D<T>::QuaternionRotate (Point3D<T> &rotate)
00533 {               
00534         return *this;   
00535         Quaternion qbase,qrotate;
00536 
00537         qbase.from_euler(*this);
00538         qrotate.from_euler(rotate);
00539         qbase*=qrotate;
00540         return qbase.to_euler();
00541 }
00542 
00543 template <class T>
00544 BOOL Point3D<T>::IsOnTriangle(Point3D<T> &a,Point3D<T> &b,Point3D<T> &c)
00545 {
00546         Point2D<T> _p,_a,_b,_c,_pp;
00547         double alphaBC,alphaAPP;
00548         _p=this;
00549         _a=a;
00550         _b=b;
00551         _c=c;
00552         if (!_p.IsOnTriangle(_a,_b,_c,&alphaBC,&alphaAPP,&_pp)) return FALSE;
00553         Point3D pp;
00554         pp=_pp;
00555         pp.z.LinearInterpolation(b.z,c.z,alphaBC);
00556         z.LinearInterpolation(a.z,pp.z,alphaAPP);
00557         return TRUE;
00558 }
00559 
00560 template <class T>
00561 void Point3D<T>::operator= (Point2D<T> &src)
00562 {
00563         x=src.x;
00564         y=src.y;
00565         z=0;
00566 }
00567 
00568 template <class T>
00569 void Point3D<T>::operator=(Point3D<T> &src)
00570 {
00571         x=src.x;
00572         y=src.y;
00573         z=src.z;
00574 }
00575 
00576 template <class T>
00577 void Point3D<T>::Add(T _x,T _y,T _z)
00578 {
00579         x+=_x;
00580         y+=_y;
00581         z+=_z;
00582 }
00583 
00584 template <class T>
00585 void Point3D<T>::operator+=(Point3D<T> &src)
00586 {
00587         x+=src.x;
00588         y+=src.y;
00589         z+=src.z;
00590 }
00591 
00592 template <class T>
00593 void Point3D<T>::operator/=(double divide)
00594 {
00595         x/=divide;
00596         y/=divide;
00597         z/=divide;
00598 }
00599 
00600 template <class T>
00601 void Point3D<T>::glRotated(double ratio)
00602 {
00603         if (!ratio) return;
00604         if (ratio==1) glRotated();
00605         else
00606         {
00607                 if (x) ::glRotated(x*ratio,1,0,0);
00608                 if (y) ::glRotated(y*ratio,0,1,0);
00609                 if (z) ::glRotated(z*ratio,0,0,1);
00610         }
00611 }
00612 
00613 template <class T>
00614 void Point3D<T>::glRotated()
00615 {
00616         if (x) ::glRotated(x,1,0,0);
00617         if (y) ::glRotated(y,0,1,0);
00618         if (z) ::glRotated(z,0,0,1);
00619 }
00620 
00621 template <class T>
00622 void Point3D<T>::glTranslated(double ratio)
00623 {
00624         if (!ratio) return;
00625         if (x||y||z) ::glTranslated(x*ratio,y*ratio,z*ratio);
00626 }
00627 
00628 template <class T>
00629 void Point3D<T>::glTranslated()
00630 {
00631         if (x||y||z) ::glTranslated(x,y,z);
00632 }
00633 
00634 #endif

Generated on Fri Aug 20 19:19:51 2004 for 3d Controls by doxygen 1.3.6