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