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 homepage Users' guide
(C) Arxia 2004-2005