Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

CappedRectangle.cpp

Go to the documentation of this file.
00001 #include "CappedRectangle.h"
00002 #include "Simulator.h"
00003 #include "Circle.h"
00004 #include "Border.h"
00005 
00006 CappedRectangle::CappedRectangle(real l, real R,
00007      real x, real y, real alpha, 
00008      std::string label,
00009        int nSensorsLateral, int nSensorsSemicircle,
00010        real saturationForce,
00011        Color outlineColor, Color fillColor) : 
00012    nSensorsLateral(nSensorsLateral),
00013    nSensorsSemicircle(nSensorsSemicircle),
00014   PhysicalObject(label, 2*(nSensorsLateral+nSensorsSemicircle), 
00015                                     saturationForce, outlineColor, fillColor){
00016    this->l=l;
00017    this->R=R;
00018    r.x=x;
00019    r.y=y;
00020    this->alpha=alpha;
00021    computeMass();
00022    computeInertia();
00023    computeBox();
00024 }
00025 
00026 CappedRectangle::~CappedRectangle(){
00027 }
00028 
00029 void CappedRectangle::computeMass(real density){
00030    //rectangle 2l x 2R and 2 half-circles of radius R
00031    m = density * R * (4*l + (M_PI)*R);
00032 }
00033 
00034 void CappedRectangle::computeInertia(){
00035    I = m * (8.0*l*l + 5.0*R*R) / 6.0;
00036 }
00037 
00038 int CappedRectangle::getISensorSemicircle(Vector2& p, int sign){
00039    if(nSensorsSemicircle){
00040       real u, startAngle;
00041       unsigned iSensor;
00042       u = atan2(p.y, p.x); //-Pi..Pi
00043       if(sign>0){
00044          startAngle=3*M_PI/2;
00045          iSensor=2*nSensorsLateral+nSensorsSemicircle;
00046       } else {
00047          startAngle=M_PI/2;
00048          iSensor=nSensorsLateral;
00049       }
00050       u-=alpha+startAngle; //-5Pi..Pi
00051       u/=2*M_PI; //-5/2..1/2
00052       while (u<0) u+=1; 
00053       while (u>=1) u-=1;   // [0..1)
00054       return (unsigned)(floor(u*nSensorsSemicircle))+iSensor;
00055    } else {
00056       return -1;
00057    }
00058 }
00059 
00060 
00061 void CappedRectangle::setISensorLateral(int& i1, int& i2, Vector2& p, real e1, real e2){
00062    real side=getLateralSide(p);
00063    i1=getISensorLateral(side, e1);
00064    i2=getISensorLateral(side, e2);
00065 }
00066 
00067 int CappedRectangle::getISensorLateral(Vector2& p, real e){
00068    real side=getLateralSide(p);
00069    return getISensorLateral(side, e);
00070 }
00071 
00072 int CappedRectangle::getISensorLateral(real side, real e){
00073    assert(-l<=e && e<=l);
00074    if(nSensorsLateral){
00075       int i;
00076       if(side>0){
00077          //top side
00078          i=floor((l-e)/2/l*nSensorsLateral);
00079          if(i==nSensorsLateral) i--;
00080       } else {
00081          //bottom side
00082          i=floor((l+e)/2/l*nSensorsLateral);
00083          if(i==nSensorsLateral) i--;
00084          i+=nSensorsLateral+nSensorsSemicircle;
00085       }
00086       return i;
00087    } else {
00088       return -1;
00089    }
00090 }
00091 
00092 bool CappedRectangle::detectContacts(Border* border, GlobalContactInfoVector* contacts){
00093    real d1, d2, delta, delta1, delta2, ut;
00094    Vector2 p;
00095    ContactInfo* contact1;
00096    ContactInfo* contact2;
00097    real penetration=0.0f;
00098    bool isContact=false;
00099    
00100    //capsule - border contact
00101    d1=   (r.x+l*cosAlpha-border->r.x)*border->normal.x+
00102          (r.y+l*sinAlpha-border->r.y)*border->normal.y;
00103    delta1=d1-R;
00104    d2=   (r.x-l*cosAlpha-border->r.x)*border->normal.x+
00105          (r.y-l*sinAlpha-border->r.y)*border->normal.y;
00106    delta2=d2-R;
00107    delta1<delta2 ? delta=delta1 : delta=delta2;
00108    if (delta<ThyrixParameters::epsilonContact){
00109       isContact=true;
00110       //contact1: of the capsule
00111       p=border->normal;
00112       p*=-R;
00113       
00114       
00115       if(delta1<ThyrixParameters::epsilonContact && delta2<ThyrixParameters::epsilonContact){
00116          /* Parallel case: the capsule is parallel to the border.
00117          */
00118          
00119          /*
00120          real qt=(delta2-delta1)/(EPSILONCONTACT*2)*l;
00121          if(qt<-l) qt=-l; else if(qt>l) qt=l;
00122          p.x+=qt*cosAlpha;
00123          p.y+=qt*sinAlpha;
00124          */
00125 
00126          if (delta < 0) {
00127             penetration=-delta*l;
00128          }
00129          
00130          int im, ip;
00131          setISensorLateral(im, ip, p, -l, l);
00132 
00133          if(contacts!=NULL){
00134             Vector2 pt;
00135             pt=p;
00136             pt.x+=l*cosAlpha;
00137             pt.y+=l*sinAlpha;
00138             contact1=new ContactInfo(this, 1, pt, border->normal, ip, im);
00139             pt.setToZero();
00140             contact2=new ContactInfo(border, -1, pt, border->normal);
00141             contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00142 
00143             pt=p;
00144             pt.x-=l*cosAlpha;
00145             pt.y-=l*sinAlpha;
00146             contact1=new ContactInfo(this, 1, pt, border->normal, im, ip);
00147             pt.setToZero();
00148             contact2=new ContactInfo(border, -1, pt, border->normal);
00149             contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00150          }
00151          
00152       } else {
00153          int sign;
00154          Vector2 p0(p);
00155          if(delta1<delta2) {
00156             p.x+=l*cosAlpha;
00157             p.y+=l*sinAlpha;
00158             sign=1;
00159          } else {
00160             p.x-=l*cosAlpha;
00161             p.y-=l*sinAlpha;
00162             sign=-1;
00163          }
00164          if(delta<0){
00165             ut=R*R-sqr(d1<d2 ? d1 : d2);
00166             if(ut>0)
00167                penetration=-delta*sqrt(ut);
00168             else
00169                penetration=0.0;
00170          }
00171 
00172          if(contacts!=NULL){
00173             contact1=new ContactInfo(this, 1, p, border->normal, getISensorSemicircle(p0, sign));
00174 
00175             //contact2: of the border
00176             p.setToZero();
00177             contact2=new ContactInfo(border, -1, p, border->normal);
00178 
00179             contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00180          }
00181 
00182       }
00183       
00184    }  //if contact
00185    return isContact;
00186 }
00187 
00188 
00189 bool CappedRectangle::detectContacts(Circle* circle, GlobalContactInfoVector* contacts){
00190    real d, delta, ut;
00191    Vector2 rt,rtt;
00192    ContactInfo* contact1;
00193    ContactInfo* contact2;
00194    real penetration=0.0f;
00195    bool isContact=false;
00196 
00197    real kContact;
00198    int iSensor=-1;
00199    rt=circle->r;
00200    rt-=r;
00201    d=fabs(rt.x*sinAlpha-rt.y*cosAlpha);
00202    delta=d-R-circle->R;
00203    if (delta<ThyrixParameters::epsilonContact){
00204       real k=rt.x*cosAlpha+rt.y*sinAlpha;
00205       //TODO: de optimizat inmultirile
00206       if(k>l){
00207          rtt.setXY(rt.x-l*cosAlpha,rt.y-l*sinAlpha);
00208          d=rtt.getModule();
00209          delta=d-R-circle->R;
00210          if(delta<ThyrixParameters::epsilonContact){
00211             isContact=true;
00212             kContact=l;
00213             
00214             //set iSensor of the capsule
00215             iSensor=getISensorSemicircle(rtt,1);
00216             
00217             //set penetration
00218             if(delta<0){
00219                if(d>1e-6){
00220                   ut=(-d+circle->R-R)*(-d-circle->R+R)*(-delta)*(-d+circle->R+R);
00221                   if(ut>0)
00222                      penetration=-delta*sqrt(ut)/(2.0*d);
00223                   else
00224                      penetration=0.0;
00225                } else {
00226                   penetration=M_PI*circle->R*R;
00227                }
00228             }
00229 
00230          }
00231       } else if(k<-l) {
00232          rtt.setXY(rt.x+l*cosAlpha,rt.y+l*sinAlpha);
00233          d=rtt.getModule();
00234          delta=d-R-circle->R;
00235          if(delta<ThyrixParameters::epsilonContact){
00236             isContact=true;
00237             kContact=-l;
00238 
00239             //set iSensor of the capsule
00240             iSensor=getISensorSemicircle(rtt,-1);
00241             
00242             //set penetration
00243             if(delta<0){
00244                if(d>1e-6){
00245                   ut=(-d+circle->R-R)*(-d-circle->R+R)*(-delta)*(-d+circle->R+R);
00246                   if(ut>0)
00247                      penetration=-delta*sqrt(ut)/(2.0*d);
00248                   else
00249                      penetration=0.0;
00250                } else {
00251                   penetration=M_PI*circle->R*R;
00252                }
00253             }
00254 
00255          }
00256       } else {
00257          isContact=true;
00258          kContact=k;
00259 
00260          //set iSensor of the capsule
00261          iSensor=getISensorLateral(rt, k);
00262 
00263          //set penetration
00264          if(delta<0){
00265             ut=sqr(circle->R)-sqr(d-R);
00266             if(ut>0)
00267                penetration=-delta*sqrt(ut);
00268             else
00269                penetration=0.0;
00270          }
00271             
00272       }
00273       if(isContact && contacts!=NULL){
00274          //simulator->outText("Found capsule-circle contact\n");
00275          Vector2 n;
00276          n=r;
00277          n.x+=kContact*cosAlpha;
00278          n.y+=kContact*sinAlpha;
00279          n-=circle->r;
00280          n.normalize();
00281 
00282          //contact1: of the capsule
00283          rt=n;
00284          rt*=-R;
00285          rt.x+=kContact*cosAlpha;
00286          rt.y+=kContact*sinAlpha;
00287          contact1=new ContactInfo(this, 1, rt, n, iSensor);
00288 
00289          //contact2: of the circle
00290          rt=n;
00291          rt*=circle->R;
00292          contact2=new ContactInfo(circle, -1, rt, n, circle->getISensor(n));
00293          contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00294       }
00295    }
00296    return isContact;
00297 }
00298 
00299 bool CappedRectangle::detectContacts(CappedRectangle* capsule, GlobalContactInfoVector* contacts){ 
00300    real d, delta;
00301    Vector2 rt;
00302    ContactInfo* contact1;
00303    ContactInfo* contact2;
00304    real penetration=0.0f;
00305    bool isContact=false;
00306    bool wasContactCreated=false;
00307    real& R1=R;
00308    real& R2=capsule->R;
00309    real& l1=l;
00310    real& l2=capsule->l;
00311 
00312    rt = r - capsule->r;
00313    if(rt.getSquaredModule()<sqr(R1+l1+R2+l2+ThyrixParameters::epsilonContact)){
00314       //contact possibility      
00315       int iSensor1, iSensor2;
00316       real& sinAlpha1=sinAlpha;
00317       real& cosAlpha1=cosAlpha;
00318       real& sinAlpha2=capsule->sinAlpha;
00319       real& cosAlpha2=capsule->cosAlpha;
00320       real p=cosAlpha1*cosAlpha2+sinAlpha1*sinAlpha2;
00321       int sigma, sigma1, sigma2;
00322       Vector2 u;
00323       Vector2 p1, p2, n;
00324       Vector2 rtt;
00325       real ut;
00326       real ru1, ru2, rtu;
00327       real dperp;
00328       real contactLength;
00329       
00330       if(1-fabs(p)<1e-4){
00331          //parallel case
00332          int iSensor1a, iSensor1b, iSensor2a, iSensor2b;
00333          sigma = (p > 0) ? 1 : -1;
00334          u.setXY((cosAlpha1+sigma*cosAlpha2)/2,(sinAlpha1+sigma*sinAlpha2)/2);
00335          dperp=fabs(rt.x*u.y-rt.y*u.x);
00336          d=dperp;
00337          delta=d-R1-R2;
00338          if(delta<ThyrixParameters::epsilonContact){
00339             real ru1p, ru1m, ru2p, ru2m;
00340             ru1=r*u;
00341             ru2=capsule->r*u;
00342             rtu=ru1-ru2;
00343             ru1p=ru1+l1;
00344             ru1m=ru1-l1;
00345             ru2p=ru2+l2;
00346             ru2m=ru2-l2;
00347             // segment 1: () ; segment 2: []
00348             if(ru1m>ru2p){
00349                //case a ()[]
00350                d=sqrt(sqr(ru1m-ru2p)+sqr(dperp));
00351                delta=d-R1-R2;
00352                if(delta<ThyrixParameters::epsilonContact){
00353                   isContact=true;
00354                   n.setXY(-l1*cosAlpha1-l2*cosAlpha2,-l1*sinAlpha1-l2*sinAlpha2); 
00355                   n+=rt;
00356                   n.normalize();
00357                   p1=n; p1*=-R1; 
00358                   iSensor1=getISensorSemicircle(p1,-1);
00359                   rtt.setXY(-l1*cosAlpha1,-l1*sinAlpha1); 
00360                   p1+=rtt;
00361                   p2=n; p2*=R2; 
00362                   iSensor2=capsule->getISensorSemicircle(p2,sigma);
00363                   rtt.setXY(l2*cosAlpha2,l2*sinAlpha2); 
00364                   p2+=rtt;
00365                   
00366                   
00367                   //compute penetration surface
00368                   if(delta<0){
00369                      if(d>1e-6){
00370                         ut=(-d+R2-R1)*(-d-R2+R1)*(-delta)*(-d+R2+R1);
00371                         if(ut>0)
00372                            penetration=-delta*sqrt(ut)/(2.0*d);
00373                         else
00374                            penetration=0.0;
00375                      } else {
00376                         penetration=M_PI*R1*R2;
00377                      }
00378                   }
00379 
00380                }
00381             } else if(ru1p>ru2m){
00382                //case b [ ) && ( ]
00383                //parallel contact
00384                Vector2 p1a, p1b, p2a, p2b;
00385                //simulator->outText("Parallel case b\n");
00386 
00387                //compute the normal n
00388                n=u; n*=-(rt*u); n+=rt;
00389                ut=n.getModule();
00390                if(ut==0.0){
00391                   n=rt;
00392                   n.normalize();
00393                } else {
00394                   n/=ut;
00395                }
00396 
00397                real lambda1a, lambda1b, lambda2a, lambda2b;
00398                
00399                if(ru1p>ru2p) {
00400                   // [ ] ) && ( ]
00401                   if(ru1m>ru2m){
00402                      // case b1: [ ( ] )
00403                      contactLength=(ru2+l2)-(ru1-l1);
00404                      lambda1a=-l1;
00405                      lambda1b=-l1+contactLength;
00406                      lambda2a=l2-contactLength;
00407                      lambda2b=l2;
00408                   } else {
00409                      // case b2: ( [ ] )
00410                      contactLength=l2*2;
00411                      lambda1a=-rtu-l2;
00412                      lambda1b=-rtu+l2;
00413                      lambda2a=-l2;
00414                      lambda2b=l2;
00415                   }
00416                } else {
00417                   // [ ) ] && ( ]
00418                   if(ru1m>ru2m){
00419                      // case b3: [ ( ) ]
00420                      contactLength=l1*2;
00421                      lambda1a=-l1;
00422                      lambda1b=l1;
00423                      lambda2a=rtu-l;
00424                      lambda2b=rtu+l;
00425                   } else {
00426                      // case b4: ( [ ) ]
00427                      contactLength=(ru1+l1)-(ru2-l2);
00428                      lambda1a=l1-contactLength;
00429                      lambda1b=l1;
00430                      lambda2a=-l2;
00431                      lambda2b=-l2+contactLength;
00432                   }
00433                }
00434 
00435                p1=n; p1*=-R1; 
00436                p1a=p1b=p1;
00437                p2=n; p2*=R2; 
00438                p2a=p2b=p2;
00439 
00440                rtt=u; rtt*=lambda1a; p1a+=rtt;
00441                rtt=u; rtt*=lambda1b; p1b+=rtt;
00442                setISensorLateral(iSensor1a, iSensor1b, p1, lambda1a, lambda1b);
00443                
00444                rtt=u; rtt*=lambda2a; p2a+=rtt;
00445                rtt=u; rtt*=lambda2b; p2b+=rtt;
00446                capsule->setISensorLateral(iSensor2a, iSensor2b, p2, sigma*lambda2a, 
00447                                                    sigma*lambda2b);
00448 
00449                if(delta<0)
00450                   penetration=-delta*contactLength/2;
00451 
00452                isContact=true;
00453                wasContactCreated=true;
00454 
00455                if(contacts!=NULL){
00456                   //parallel contact
00457                   contact1=new ContactInfo(this, 1, p1a, n, iSensor1a, iSensor1b);
00458                   contact2=new ContactInfo(capsule, -1, p2a, n, iSensor2a, iSensor2b);
00459                   contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00460 
00461                   contact1=new ContactInfo(this, 1, p1b, n, iSensor1b, iSensor1a);
00462                   contact2=new ContactInfo(capsule, -1, p2b, n, iSensor2b, iSensor2a);
00463                   contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00464                }
00465 
00466             } else {
00467                //case c
00468                d=sqrt(sqr(ru2m-ru1p)+sqr(dperp));
00469                delta=d-R-R2;
00470                if(delta<ThyrixParameters::epsilonContact){
00471                   isContact=1;
00472                   //simulator->outText("Parallel case c\n");
00473                   n.setXY(l*cosAlpha1+l2*cosAlpha2,l*sinAlpha1+l2*sinAlpha2); 
00474                   n+=rt;
00475                   n.normalize();
00476                   p1=n; p1*=-R1; 
00477                   iSensor1=getISensorSemicircle(p1,1);
00478                   rtt.setXY(l*cosAlpha1,l*sinAlpha1); p1+=rtt;
00479                   p2=n; p2*=R2; 
00480                   iSensor2=capsule->getISensorSemicircle(p2,-sigma);
00481                   rtt.setXY(-l2*cosAlpha2,-l2*sinAlpha2); p2+=rtt;
00482                   
00483                   if(delta<0){
00484                      if(d>1e-6){
00485                         ut=(-d+R2-R)*(-d-R2+R)*(-delta)*(-d+R2+R);
00486                         if(ut>0)
00487                            penetration=-delta*sqrt(ut)/(2.0*d);
00488                         else
00489                            penetration=0.0;
00490                      } else {
00491                         penetration=M_PI*R2*R;
00492                      }
00493                   }
00494                }
00495             }
00496          }
00497          
00498       } else {
00499          //non-parallel case
00500          ru1=rt.x*cosAlpha1+rt.y*sinAlpha1;
00501          ru2=rt.x*cosAlpha2+rt.y*sinAlpha2;
00502          real lambda1, lambda2, lambda1m, lambda2m, lambda1mp, lambda2mp, dp;
00503          ut=p*p-1.0;
00504          lambda1=(ru1-p*ru2)/ut;
00505          lambda2=(p*ru1-ru2)/ut;
00506          if(lambda1>-l1 && lambda1<l1 && lambda2>-l2 && lambda2<l2){
00507             //intersection case
00508             isContact=true;
00509             //simulator->outText("Intersection case\n");
00510             lambda1<0 ? sigma1=1 : sigma1=-1;
00511             lambda2<0 ? sigma2=1 : sigma2=-1;
00512             n.setXY(sigma1*cosAlpha1-sigma2*cosAlpha2,sigma1*sinAlpha1-sigma2*sinAlpha2);
00513             n.normalize();
00514             p1.setXY(lambda1*cosAlpha1,lambda1*sinAlpha1);
00515             p2.setXY(lambda2*cosAlpha2,lambda2*sinAlpha2);
00516             rtt.setXY(-sigma1*cosAlpha1,-sigma1*sinAlpha1);
00517             iSensor1=getISensorSemicircle(rtt,-sigma1);
00518             rtt.setXY(sigma2*cosAlpha2,sigma2*sinAlpha2);
00519             iSensor2=capsule->getISensorSemicircle(rtt,-sigma2);
00520             penetration=4*R*R2/sqrt(-ut);
00521          } else {
00522             //non-intersection case
00523             lambda1>0 ? sigma1=1 : sigma1=-1;
00524             lambda2>0 ? sigma2=1 : sigma2=-1;
00525 
00526             bool e1, e2, e1p, e2p; //indicate whether the contact is at end (true) or in the middle (false)
00527 
00528             lambda1m=sigma1*l; e1=true;
00529             lambda2m=-(lambda1-lambda1m)*p+lambda2;
00530             if(lambda2m<-l2) {
00531                lambda2m=-l2;
00532                e2=true;
00533             } else if(lambda2m>l2) {
00534                lambda2m=l2;
00535                e2=true;
00536             } else {
00537                e2=false;
00538             }
00539 
00540             rtt.setXY(lambda1m*cosAlpha1-lambda2m*cosAlpha2,lambda1m*sinAlpha1-lambda2m*sinAlpha2);
00541             rtt+=rt;
00542             d=rtt.getModule();
00543             
00544             lambda2mp=sigma2*l2; e2p=true;
00545             lambda1mp=-(lambda2-lambda2mp)*p+lambda1;
00546             if(lambda1mp<-l) {
00547                lambda1mp=-l; 
00548                e1p=true;
00549             } else if(lambda1mp>l) {
00550                lambda1mp=l;            
00551                e1p=true;
00552             } else {
00553                e1p=false;
00554             }
00555             rtt.setXY(lambda1mp*cosAlpha1-lambda2mp*cosAlpha2,lambda1mp*sinAlpha1-lambda2mp*sinAlpha2);
00556             rtt+=rt;
00557             dp=rtt.getModule();
00558             
00559             if(dp<d){
00560                lambda1m=lambda1mp;
00561                lambda2m=lambda2mp;
00562                d=dp;
00563                e1=e1p;
00564                e2=e2p;
00565             }
00566             delta=d-R-R2;
00567             if(delta<ThyrixParameters::epsilonContact){
00568                isContact=true;
00569                //simulator->outText("Non-intersection case\n");
00570                n.setXY(lambda1m*cosAlpha1-lambda2m*cosAlpha2,lambda1m*sinAlpha1-lambda2m*sinAlpha2);
00571                n+=rt;
00572                n.normalize();
00573                p1.setXY(lambda1m*cosAlpha1,lambda1m*sinAlpha1); 
00574                rtt=n; rtt*=-R; p1+=rtt;
00575                if(e1){
00576                   iSensor1=getISensorSemicircle(rtt, lambda1m>0?1:-1);
00577                } else {
00578                   iSensor1=getISensorLateral(p1, lambda1m);
00579                }
00580                p2.setXY(lambda2m*cosAlpha2,lambda2m*sinAlpha2); 
00581                rtt=n; rtt*=R2; p2+=rtt;
00582                if(e2){
00583                   iSensor2=capsule->getISensorSemicircle(rtt, lambda2m>0?1:-1);
00584                } else {
00585                   iSensor2=capsule->getISensorLateral(p2, lambda2m);
00586                }
00587 
00588                if(delta<0){
00589                   if(d>1e-6){
00590                      ut=(-d+R2-R)*(-d-R2+R)*(-delta)*(-d+R2+R);
00591                      if(ut>0)
00592                         penetration=-delta*sqrt(ut)/(2.0*d);
00593                      else
00594                         penetration=0.0;
00595                   } else {
00596                      penetration=M_PI*R2*R;
00597                   }
00598                }
00599                   //only circle-circle case considered for penetration, for simplicity
00600                   //TODO: verify in which case we are, add circle - rectangle case
00601             }
00602          }
00603       }
00604       if (isContact && !wasContactCreated && contacts!=NULL) {
00605          //simulator->outText("Found capsule-capsule contact\n");
00606          
00607          //contact1: of this capsule
00608          contact1=new ContactInfo(this, 1, p1, n, iSensor1);
00609    
00610          //contact2: of the other capsule
00611          contact2=new ContactInfo(capsule, -1, p2, n, iSensor2);
00612          contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));
00613       }
00614    }
00615    return isContact;
00616 }
00617 
00618 bool CappedRectangle::detectMouseContact(const Vector2& rMouse, Vector2& p, PhysicalObject*& object){
00619    Vector2 rt=rMouse;
00620    rt-=r;
00621    real d=fabs(rt.x*sinAlpha-rt.y*cosAlpha);
00622    if (d<=R){
00623       real k=rt.x*cosAlpha+rt.y*sinAlpha;
00624       Vector2 rtt;
00625       if(k>l){
00626          rtt.setXY(rt.x-l*cosAlpha,rt.y-l*sinAlpha);
00627          d=rtt.getModule();
00628          if(d>R){
00629             return false;
00630          }
00631       } else if(k<-l){
00632          rtt.setXY(rt.x+l*cosAlpha,rt.y+l*sinAlpha);
00633          d=rtt.getModule();
00634          if(d>R){
00635             return false;
00636          }
00637       }
00638       rt.rotate(-alpha);
00639       p=rt;
00640       object=this;
00641       return true;
00642    } else {
00643       return false;
00644    }
00645 }
00646 
00647 void CappedRectangle::setSensor(ContactInfo* contact){
00648    if(contact->iSensor>=0){
00649       real f;
00650       if(contact->type!=contactTypeForceParallel){
00651          //single point contact
00652          f=contact->force/saturationForce+activations[contact->iSensor];
00653          if(f>1) f=1.0;
00654          activations[contact->iSensor]=f;
00655       } else {
00656          
00657          //parallel contact
00658          assert(contact->iSensor>=0 && contact->iSensor2>=0);
00659          int n=contact->iSensor2-contact->iSensor;
00660          int sign;
00661          if(n>0){
00662             sign=1;
00663          } else {
00664             sign=-1;
00665             n=-n;
00666          }
00667          n++;
00668          int i=0, j;
00669          real k=contact->force/saturationForce*0.5/n/(n-1);
00670          for(i=0;i<n;i++){
00671             j=contact->iSensor+i*sign;
00672             assert(j>=0);
00673             assert(j<nSensors);
00674             f=i*k+activations[j];
00675             if(f>1) f=1.0;
00676             activations[j]=f;
00677          }
00678          
00679       }
00680    }
00681 }
00682 
00683 void CappedRectangle::draw(GUI *gui){
00684    gui->setPenColor(outlineColor);
00685    gui->setBrushColor(fillColor);
00686    gui->drawCappedRectangle(r.x, r.y, l, R, alpha);
00687    //gui->setPenColor(GUI::RED);
00688    //drawContactForces(gui);
00689    //drawSensors(gui);
00690    //gui->setPenColor(GUI::BLACK);
00691 }
00692 
00693 void CappedRectangle::drawSensors(GUI *gui){
00694    if(nSensors){
00695       //gui->setPenColor(GUI::RED);
00696       int i, i0;
00697       real x, y, dx, dy;
00698       real h=0.5; //==R;
00699 
00700 
00701       if(nSensorsSemicircle){
00702          real u;  
00703          i0=2*nSensorsLateral+nSensorsSemicircle;
00704          x=r.x+l*cosAlpha;
00705          y=r.y+l*sinAlpha;
00706          for(i=0; i<nSensorsSemicircle; i++){
00707             u=alpha+3*M_PI/2+(i+0.5)*2*M_PI/nSensorsSemicircle;
00708             dx=cos(u);
00709             dy=sin(u);
00710             gui->drawLine(x+R*dx, y+R*dy, x+(R-h*activations[i+i0])*dx, 
00711                y+(R-h*activations[i+i0])*dy);
00712          }
00713          i0=nSensorsLateral;
00714          x=r.x-l*cosAlpha;
00715          y=r.y-l*sinAlpha;
00716          for(i=0; i<nSensorsSemicircle; i++){
00717             u=alpha+M_PI/2+(i+0.5)*2*M_PI/nSensorsSemicircle;
00718             dx=cos(u);
00719             dy=sin(u);
00720             gui->drawLine(x+R*dx, y+R*dy, x+(R-h*activations[i+i0])*dx, 
00721                y+(R-h*activations[i+i0])*dy);
00722          }
00723       }
00724       //gui->setPenColor(GUI::GREEN);
00725       
00726       if(nSensorsLateral){
00727          real e;
00728          i0=0;
00729          dx=-sinAlpha; dy=cosAlpha;
00730          for(i=0;i<nSensorsLateral; i++){
00731             e=(0.5-(i+0.5)/nSensorsLateral)*2*l;
00732             x=r.x+e*cosAlpha; y=r.y+e*sinAlpha;
00733             gui->drawLine(x+R*dx, y+R*dy, x+dx*(R-h*activations[i+i0]), y+dy*(R-h*activations[i+i0]));
00734          }
00735          i0=nSensorsLateral+nSensorsSemicircle;
00736          dx=-dx;dy=-dy;
00737          for(i=0;i<nSensorsLateral; i++){
00738             e=((i+0.5)/nSensorsLateral-0.5)*2*l;
00739             x=r.x+e*cosAlpha; y=r.y+e*sinAlpha;
00740             gui->drawLine(x+R*dx, y+R*dy, x+dx*(R-h*activations[i+i0]), y+dy*(R-h*activations[i+i0]));
00741          }
00742       }
00743       
00744    }
00745 }

Thyrix homepageUsers' guide

(C) Arxia 2004-2005