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

Circle.cpp

Go to the documentation of this file.
00001 #include "Circle.h"
00002 #include "Simulator.h"
00003 #include "ContactInfo.h"
00004 #include "GlobalContactInfo.h"
00005 
00006 
00007 Circle::Circle(real R, real x, real y, std::string label, int nSensors,
00008             real sensorsStartAngle, real saturationForce,
00009              Color outlineColor, Color fillColor) : 
00010     PhysicalObject(label, nSensors, saturationForce, outlineColor, fillColor), 
00011       sensorsStartAngle(sensorsStartAngle)
00012 {
00013    r.x=x;
00014    r.y=y;
00015    this->R=R;
00016    computeMass();
00017    computeInertia();
00018    computeBox();
00019 }
00020 
00021 
00022 Circle::~Circle(){
00023 }
00024 
00025 
00026 
00027 void Circle::setRadius (real R){
00028    this->R=R;
00029    computeMass();
00030    computeInertia();
00031    computeBox();
00032 }
00033 
00034 void Circle::computeMass(real density){
00035    m=density*(real)(M_PI)*R*R;
00036 }
00037 
00038 void Circle::computeInertia(){
00039    I=m*R*R/2.0;
00040 }
00041 
00042 
00043 bool Circle::detectContacts(Border* border, GlobalContactInfoVector* contacts){
00044    real d, delta, ut;
00045    Vector2 p;
00046    ContactInfo* contact1;
00047    ContactInfo* contact2;
00048    real penetration=(real)0.0;
00049    bool isContact=false;
00050    
00051    /*compute the distance between the circle and the border, as 
00052    (r_border-r_circle)*normal-R  */
00053    d= (r.x-border->r.x)*border->normal.x+
00054       (r.y-border->r.y)*border->normal.y;
00055    delta=d-R;
00056 
00057    if (delta<=ThyrixParameters::epsilonContact) {
00058       isContact=true;
00059       //contact1: of the circle
00060       p=border->normal;
00061       p*=-R;
00062       contact1=new ContactInfo(this, 1, p, border->normal, getISensor(p));
00063 
00064       //contact2: of the border
00065       p.setToZero();
00066       contact2=new ContactInfo(border, -1, p, border->normal);
00067 
00068       if(delta<0){
00069          ut=R*R-d*d;
00070          if(ut>0)
00071             penetration=-delta*sqrt(ut);
00072          else
00073             penetration=0.0;
00074       }
00075       if(contacts)
00076          contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));      
00077    }  //if contact
00078    return isContact;
00079 }
00080 
00081 bool Circle::detectContacts(Circle* circle, GlobalContactInfoVector* contacts){
00082    real penetration=0.0;
00083   real dx = circle->r.x - r.x;
00084    real dy = circle->r.y - r.y;
00085   real d2 = sqr(dx) + sqr(dy);
00086    real d = sqrt(d2);
00087    bool isContact=false;
00088 
00089    real delta = d - R - circle->R;
00090    if (delta <= ThyrixParameters::epsilonContact) {
00091       isContact=true;
00092       Vector2 n = r - circle->r;
00093       n.normalize();
00094 
00095       //contact1: of this circle
00096       Vector2 p = n * (-R);
00097       ContactInfo* contact1 = new ContactInfo(this, 1, p, n, getISensor(p));
00098 
00099       //contact2: of the other circle
00100       p = n * circle->R;
00101       ContactInfo* contact2 = new ContactInfo(circle, -1, p, n, circle->getISensor(p));
00102 
00103 
00104       if(delta<0){
00105          if(d>1e-6){
00106             real ut=(-d+circle->R-R)*(-d-circle->R+R)*(-delta)*(-d+circle->R+R);
00107             if(ut>0)
00108                penetration=-delta*sqrt(ut)/(2.0*d);
00109             else
00110                penetration=0.0;
00111          } else {
00112             penetration=M_PI*circle->R*R;
00113          }
00114       }
00115       if(contacts)
00116          contacts->push_back(GlobalContactInfo(contact1, contact2, penetration));      
00117    }  //if contact
00118    return isContact;
00119 }
00120 
00121 bool Circle::detectMouseContact(const Vector2& rMouse, Vector2& p, PhysicalObject*& object){
00122    p=rMouse;
00123    p-=r;
00124    if(p.getSquaredModule()<=R*R){
00125       p.rotate(-alpha);
00126       /* The rotation of the vector representing the relative position of the dragging point is needed
00127       because the dragged object will rotate and the dragging point, which is fixed on the object, will
00128       rotate along with the object. Thus, p should be necessarily expressed in the object reference system.
00129       */
00130       object=this;
00131       return true;
00132    } else {
00133       return false;
00134    }
00135 }
00136 
00137 int Circle::getISensor(Vector2& p){
00138    if(nSensors){
00139       real u;
00140       u = atan2(p.y, p.x); //-Pi..Pi
00141       u-=alpha+sensorsStartAngle; //-5Pi..Pi
00142       u/=2*M_PI; //-5/2..1/2
00143       while (u<0) u+=1; 
00144       while (u>=1) u-=1;   // [0..1)
00145       return (int)(floor(u*nSensors));
00146    } else {
00147       return -1;
00148    }
00149 }
00150 
00151 void Circle::setSensor(ContactInfo* contact){
00152    if(contact->iSensor>=0){
00153       real f=contact->force/saturationForce+activations[contact->iSensor];
00154       if(f>1) f=1.0;
00155       activations[contact->iSensor]=f;
00156    }
00157 }
00158 
00159 
00160 void Circle::draw(GUI *gui) {
00161    gui->setPenColor(outlineColor);
00162    gui->setBrushColor(fillColor);
00163    gui->drawCircle(r.x, r.y, R);
00164    //gui->setPenColor(GUI::GREEN);
00165    //drawContactForces(gui);
00166    //drawSensors(gui);
00167    //gui->setPenColor(GUI::BLACK);
00168 }
00169 
00170 void Circle::drawSensors(GUI *gui){
00171    if(nSensors){
00172       //gui->setPenColor(GUI::RED);
00173       real u, dx, dy;
00174       int i;
00175       for(i=0; i<nSensors; i++){
00176          u=alpha+sensorsStartAngle+(i+0.5)*2*M_PI/nSensors;
00177          dx=R*cos(u);
00178          dy=R*sin(u);
00179          gui->drawLine(r.x+dx, r.y+dy, r.x+dx*(1-activations[i]), 
00180             r.y+dy*(1-activations[i]));
00181       }
00182    }
00183 }

Thyrix homepageUsers' guide

(C) Arxia 2004-2005