misc.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *  misc.cpp
00003  *
00004  *  (C) 2006 AG Aktives Sehen <agas@uni-koblenz.de>
00005  *           Universitaet Koblenz-Landau
00006  *
00007  * Author: Frank Neuhaus
00008  *******************************************************************************/
00009 
00010 #include "vec2.h"
00011 #include "misc.h"
00012 #include <iostream>
00013 #include "math.h"
00014 #include <assert.h>
00015 #include "Obb2D.h"
00016 
00024 bool intersectRayCircle(const CVec2& m, float r, const CVec2& x, const CVec2& t, float& f)
00025 {
00026         //|x-m|=r
00027         //|x+r*t-m|=r
00028         //(x+r*t-m)^2=r^2
00029         //((x-m)+r*t)^2=r^2
00030         //(x-m)^2+2*(x-m)*r*t+r^2*t^2=r^2
00031         
00032         //r^2*t^2+r*2*(x-m)*t+(x-m)^2-r^2
00033         
00034         
00035         float invtSqr=1.0f/t.sqr();
00036         float p = 2.0f*((x-m)*t)*invtSqr;
00037         float q = ((m-x).sqr() - r*r)*invtSqr;  
00038         float diskr = p*p*0.25f - q;
00039         
00040         if (diskr < 0)
00041         {
00042                 return false;
00043         }
00044 
00045         diskr=sqrtf(diskr);
00046         f = -0.5f*p - diskr;
00047         
00048         if (f<0)
00049         {
00050                 f = -0.5f*p + diskr;
00051                 if (f>0)
00052                 {
00053                         return true;
00054                 }
00055                 else
00056                 {
00057                         return false;
00058                 }
00059         }
00060 /*      
00061         if (f<0)
00062         {
00063                 std::cout << "smaller"  << f << std::endl;
00064                 if (t*(m-x)>0)
00065                 {
00066                         f=0.001;
00067                         return true;
00068                 }
00069                 else
00070                         return false;
00071         }
00072         */
00073         return true;
00074 
00075 }
00076 
00077 
00078 bool intersectRayLineSegment(const CVec2& a, const CVec2& b, const CVec2& x, const CVec2& t, float&f)
00079 {
00080         CVec2 n=(b-a).getNormal();
00081         
00082         float denom=t*n;
00083                 
00084         if (fabs(denom)<0.000001f)
00085                 return false;
00086                 
00087         f=(n*a-n*x)/denom;
00088         
00089         if (f<0)
00090         {
00091                 return false;
00092         }
00093                 
00094         CVec2 pt=x+t*f;
00095         if ((a-pt)*(b-pt)<0)
00096                 return true;    
00097         return false;
00098 }
00099 
00100 float shortestDistanceToLineSegment(const CVec2& a, const CVec2& b, const CVec2& x)
00101 {
00102         CVec2 dir=b-a;
00103         
00104         if ( (dir*dir) < 0.00001 )
00105         {
00106                 float m1=(x-a).magnitude();
00107                 float m2=(x-b).magnitude();
00108                 if (m1<m2) return m1;
00109                 else return m2;
00110         }
00111                 
00112         float r=(dir*x-dir*a)/(dir*dir);
00113         if (r<=0.0f)
00114                 return (x-a).magnitude();
00115         if (r>=1.0f)
00116                 return (x-b).magnitude();
00117         
00118         return (a+r*dir-x).magnitude();
00119         
00120 }
00121 
00122 bool intersectRayCapsule(const CVec2& x, const CVec2& t, const CVec2& a, const CVec2& b, float radius, float& f)
00123 {
00124         f=99999999;
00125         float r;
00126         bool hadInt=false;
00127         if (intersectRayCircle(a,radius,x,t,r))
00128         {
00129                 if (r<f)
00130                         f=r;
00131                 hadInt=true;
00132         }
00133         if (intersectRayCircle(b,radius,x,t,r))
00134         {
00135                 if (r<f)
00136                         f=r;
00137                 hadInt=true;
00138         }
00139         CVec2 n=normalize(b-a).getNormal();
00140         if (intersectRayLineSegment(a+radius*n,b+radius*n,x,t,r))
00141         {
00142                 if (r<f)
00143                         f=r;
00144                 hadInt=true;
00145         }
00146         if (intersectRayLineSegment(a-radius*n,b-radius*n,x,t,r))
00147         {
00148                 if (r<f)
00149                         f=r;
00150                 hadInt=true;
00151         }
00152         return hadInt;
00153 }
00154 
00155 // c - punkt wo arc startet
00156 // p - zentrum des arcs
00157 // r0 - arc radius
00158 // hd - heading
00159 // m1 - kreiszentrum
00160 // r1 - kreisradius
00161 // angle - output
00162 bool intersectPathCircle(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& m1, float r1, float& angle)
00163 {
00164         CVec2 vec=p-m1;
00165         float s=vec.sqr();
00166         if (s>sqr(fabs(r0)+r1)) 
00167                 return false;
00168         
00169         if (s<sqr(fabs(r0)-r1))
00170                 return false;
00171         
00172         float d=sqrtf(s);
00173         
00174         float b=(r0*r0-r1*r1+s)/(2*d);
00175         
00176         CVec2 mid=p-vec*(b/d);
00177         
00178         float h=sqrtf(r0*r0-b*b);
00179         //std::cout << " h :  " << h << std::endl;
00180         
00181         CVec2 n=(vec*(h/d)).getNormal();
00182         
00183         
00184         //CVec2 pm=p-m1;
00185         
00186         CVec2 p1=(mid+n-p);
00187         CVec2 p2=(mid-n-p);
00188         
00189         CVec2 pc=normalize(c-p);
00190         
00191         float angle0=acosf(normalize(p1)*pc);
00192         float angle1=acosf(normalize(p2)*pc);
00193         
00194         //std::cout << "angle0: " << angle0 << std::endl;
00195         
00196         if ((p1*hd)<0) angle0=2*M_PI-angle0;
00197         if ((p2*hd)<0) angle1=2*M_PI-angle1;
00198         
00199         if (angle0<angle1) angle=angle0;
00200         else angle=angle1;
00201         
00202         //angle=angle0;
00203         
00204         return true;
00205         
00206 
00207 }
00208 
00209 bool intersectPathLine(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& p1, const CVec2& p2, float& angle)
00210 {
00211         CVec2 vec=p2-p1;
00212 
00213         
00214         /*
00215         float invtSqr=1.0f/t.sqr();
00216         float p = 2.0f*((x-m)*t)*invtSqr;
00217         float q = ((m-x).sqr() - r*r)*invtSqr;  
00218         float diskr = p*p*0.25f - q;
00219         */
00220         
00221         if (((p1-p).sqr()<r0*r0)&&((p2-p).sqr()<r0*r0))
00222                 return false;
00223         
00224         
00225         float invtSqr=1.0f/vec.sqr();
00226         float pa = 2.0f*((p1-p)*vec)*invtSqr;
00227         float qi = ((p-p1).sqr() - r0*r0)*invtSqr;      
00228         float diskr = pa*pa*0.25f - qi;
00229         
00230         if (diskr < 0)
00231         {
00232                 return false;
00233         }
00234         
00235         float sqrtfdiskr=sqrtf(diskr);
00236 
00237         float f1 = -0.5f*pa - sqrtfdiskr;
00238         float f2 = -0.5f*pa + sqrtfdiskr;
00239         
00240         if (f1>1) return false;
00241         if (f2<0) return false;
00242         
00243         //std::cout << "f1: " << f1 << " f2: " << f2 << std::endl;
00244         
00245         CVec2 int1=p1+f1*vec;
00246         CVec2 int2=p1+f2*vec;
00247         
00248         //assert((int2-int1).magnitude()<(p1-p2).magnitude());
00249         
00250         CVec2 pc=normalize(c-p);
00251         
00252         float angle0=acosf(normalize(int1-p)*pc);
00253         float angle1=acosf(normalize(int2-p)*pc);
00254         
00255         
00256         if ((int1-p)*hd<0)
00257         {
00258                 angle0=2*M_PI-angle0;
00259         }
00260         if ((int2-p)*hd<0)
00261         {
00262                 angle1=2*M_PI-angle1;
00263         }
00264         
00265         
00266         if (angle0<angle1) angle=angle0;
00267         else angle=angle1;
00268         
00269         if (f1<0) angle=angle1;
00270         if (f2>1) angle=angle0;
00271 
00272         
00273         
00274         return true;
00275         
00276 }
00277 
00278 // c - punkt wo arc startet
00279 // p - arc zentrum
00280 // r0 - radius des arcs
00281 // hd - heading
00282 // a - linienanfang
00283 // b - linienende
00284 // radius - linienradius
00285 // r [out] - wie weit ging der arc?
00286 
00287 bool intersectPathCapsule(const CVec2& c, const CVec2& p, float r0, const CVec2& hd, const CVec2& a, const CVec2& b, float radius, float& f)
00288 {
00289         f=99999999;
00290         float r;
00291         bool hadInt=false;
00292         if (intersectPathCircle(c,p,r0,hd,a,radius,r))
00293         {
00294                 if (r<f)
00295                         f=r;
00296                 hadInt=true;
00297         }
00298         if (intersectPathCircle(c,p,r0,hd,b,radius,r))
00299         {
00300                 if (r<f)
00301                         f=r;
00302                 hadInt=true;
00303         }
00304         CVec2 n=normalize(b-a).getNormal();
00305         if (intersectPathLine(c,p,r0,hd,a+radius*n,b+radius*n,r))
00306         {
00307                 if (r<f)
00308                         f=r;
00309                 hadInt=true;
00310         }
00311         if (intersectPathLine(c,p,r0,hd,a-radius*n,b-radius*n,r))
00312         {
00313                 if (r<f)
00314                         f=r;
00315                 hadInt=true;
00316         }
00317         return hadInt;
00318 }
00319 
00320 
00321 bool isInAABB(const std::pair<CVec2,CVec2>& aabb, const CVec2& p)
00322 {
00323         const CVec2& mins=aabb.first;
00324         const CVec2& maxs=aabb.second;
00325         if ((p[0]>mins[0]) &&(p[1]>mins[1])&&(p[0]<maxs[0]) &&(p[1]<maxs[1]))
00326                 return true;
00327         return false;
00328 }
00329 
00330 bool testAABBOverlap(const std::pair<CVec2,CVec2>& a, const std::pair<CVec2,CVec2>& b)
00331 {
00332         const CVec2& vMins=b.first;
00333         const CVec2& vMaxs=b.second;
00334         CVec2 B=(vMins+vMaxs)*0.5f;
00335         CVec2 A=(a.first+a.second)*0.5f;
00336         CVec2 E=a.second-A;
00337         CVec2 bE=vMaxs-B;
00338 
00339         const CVec2 T = B - A;//vector from A to B
00340         return fabs(T[0])  <= (E[0] + bE[0]) 
00341                         &&
00342                         fabs(T[1]) <= (E[1] + bE[1]);
00343 
00344 }
00345 
00346 float computeOBBIntersection(const CVec2& a, const CVec2& b, const CVec2& c, const CVec2& d, float size)
00347 {
00348         OBB2D g;
00349         CVec2 dab=normalize(b-a)*size;
00350         CVec2 nab=dab.getNormal();
00351         g[0]=a+nab-dab;
00352         g[1]=a-nab-dab;
00353         g[2]=b-nab+dab;
00354         g[3]=b+nab+dab;
00355         
00356         
00357         OBB2D h;
00358         CVec2 dcd=normalize(d-c)*size;
00359         CVec2 ncd=dcd.getNormal();
00360         h[0]=c+ncd-dcd;
00361         h[1]=c-ncd-dcd;
00362         h[2]=d-ncd+dcd;
00363         h[3]=d+ncd+dcd;
00364         
00365         std::pair<CVec2,CVec2> aabb=g.computeAABB();
00366         std::pair<CVec2,CVec2> aabb2=h.computeAABB();
00367         
00368         //static int all=0;
00369         //all++;
00370         
00371         
00372         if (!testAABBOverlap(aabb,aabb2))
00373         {
00374                 return 0;
00375         }
00376         
00377         //h.clip(g);
00378         /*
00379         static int clips=0;
00380         clips++;
00381         if (clips%10000==0)
00382                 std::cout<<"clips: " << clips << " rate: " << float(clips)/float(all) << std::endl;
00383         */
00384         return h.computeClippedArea(g)/(2*size*((a-b).magnitude()+2*size));
00385         
00386 }
00387 
00388 
00389 
00390 


robbie_architecture
Author(s): Viktor Seib
autogenerated on Mon Oct 6 2014 02:53:09