#include using namespace std; #include "TH2F.h" #include "TLine.h" #include "TCanvas.h" namespace pars { const float g=9.81; // gravity acc const float k=1.2; // spring k const float l_0=5.; // spring rest lenght const float dt=0.1; // intervallo di tempo } class Vec2d { public: // costruttore con parametri di default 0.,0. Vec2d(float x=0., float y=0.) : theX(x), theY(y) { } // ritorna le due componenti float x() const {return theX; } float y() const {return theY; } // modulo quadro e modulo float mod2() const { return x()*x()+y()*y(); } float mod() const { return sqrt(mod2()); } // operatoro unario di inversione di segno (-v) Vec2d operator-() const { return Vec2d(-x(),-y()); } // aggiungo v a questo vettore Vec2d operator+=(const Vec2d& v) { // prima cambio le componenti theX+=v.x(); theY+=v.y(); // poi ritorno me stesso modificato return *this; } // cambia il segno di una componente (per i rimbalzi) void invertX() { theX=-theX; } void invertY() { theY=-theY; } private: // le due componenti float theX, theY; }; // somma vettoriale Vec2d operator+(const Vec2d& a, const Vec2d& b) { return Vec2d(a.x()+b.x(),a.y()+b.y()); } // differenza vettoriae, implementata in termini di somma e operatore - Vec2d operator-(const Vec2d& a, const Vec2d& b) { return a+(-b); } // prodotto per scalare s*v Vec2d operator*(const float& s, const Vec2d& a) { return Vec2d(s*a.x(),s*a.y()); } // per avere prodotto commutativo Vec2d operator*(const Vec2d& a, const float& s) { return s*a; } ostream& operator<<(ostream& out, const Vec2d& v) { out << "(" << v.x() << "," << v.y() << ")" ; return out; } class Palla { public: Palla(const float& m=0., const Vec2d& pos = Vec2d() , const Vec2d& vel = Vec2d() ) : theM(m), thePos(pos), theVel(vel) { } float mass() const { return theM; } Vec2d pos() const {return thePos; } Vec2d vel() const {return theVel; } // evolvi la palla data una forza. // qui c'e' tutta la cinematica void evolvi( const Vec2d& f) { using namespace pars; // accelerazione Vec2d a=f*(1./mass()); // velocita' cambia di theVel+=a*dt; // pos cambia di thePos+=vel()*dt; } // controlla se la palla ha raggiunto il bordo e nel caso inverti la // relativa componente della velocita' void controllaBordi(float minX, float maxX, float minY, float maxY) { if (pos().x()<=minX || pos().x() >= maxX ) theVel.invertX(); if (pos().y()<=minY || pos().y() >= maxY ) theVel.invertY(); } private: float theM; Vec2d thePos; Vec2d theVel; }; ostream& operator<<(ostream& out, const Palla& p) { out << "M: " << p.mass() << " Pos: " << p.pos() << " Vel: " << p.vel() ; return out; } class Scatola { public: Scatola(float x=30., float y=30.) : dimX(x), dimY(y) { theP1 = Palla(1.,Vec2d(10.,20.)); theP2 = Palla(8.,Vec2d(20.,10.)); display(); } // ritorna la palla 1 const Palla& p1() const { return theP1; } // versione non const Palla& p1() { return theP1; } // ditto per P2 const Palla& p2() const { return theP2; } Palla& p2() { return theP2; } // fa evolvere il tempo void evolvi() { display(); using namespace pars; //calcolo forza risultante su palla 1 Vec2d F1(0.,-p1().mass()*g); // ci metto subito la gravita' // forza elastica // NB la forza e' un vettore, devo calcolare le due componenti Vec2d dist=p1().pos()-p2().pos(); // p1-p2 Vec2d Fel1=-k*(dist)*(dist.mod()-l_0)*(1./dist.mod()); // F=-k * (x-x_0) (F e x sono vettori) F1+=Fel1; //calcolo forza risultante su palla 2 Vec2d F2(0,-p2().mass()*g); // ci metto subito la gravita' Vec2d Fel2=-Fel1; // Fel2=-Fel1 F2+=Fel2; //faccio evolvere palla 1 p1().evolvi(F1); //faccio evolvere palla 2 p2().evolvi(F2); // controllo se ho colpito il bordo, nel caso inverto la componente // veolocita' della palla che ha urtato p1().controllaBordi(0., dimX, 0., dimY); p2().controllaBordi(0., dimX, 0., dimY); } // mostra lo stato void display() { cout << "P1 " << p1() << " | P2 " << p2() << endl; TH2F histo("fff","Tavolo",40,0,dimX,40,0,dimY); histo.Fill(p1().pos().x(), p1().pos().y(), p1().mass()); histo.Fill(p2().pos().x(), p2().pos().y(), p2().mass()); histo.DrawCopy("col"); TLine theSpring(p1().pos().x(), p1().pos().y(), p2().pos().x(), p2().pos().y()); theSpring.DrawClone(); } private: Palla theP1, theP2; float dimX, dimY; }; void Rimbalzo(int iterMax=10) { Scatola s; TCanvas * canvas = new TCanvas(); for (int i=0; iUpdate(); } return; }