/*************************************************************************** * Copyright (C) 2004 by Samuele Catuzzi * * samuele_catuzzi@yahoo.it * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "bouncesegmentob.h" #include #include using namespace std; BounceSegmentOb::BounceSegmentOb() { vect_Dir.null(); vect_n.null(); A.null(); B.null(); } BounceSegmentOb::~BounceSegmentOb() { } /** No descriptions */ void BounceSegmentOb::setBounceLine(double Ax,double Ay,double Bx,double By) { samuele::Vector norm, J, P; A.x = Ax; A.y = Ay; A.z = 0.0 ; B.x = Bx; B.y = By; B.z = 0.0 ; // error check if (( Ax == Bx )&&( Ay == By )||( (B - A).abs() < 3 )) { cout<<"ERROR: TOO SMALL EDGE SEGMENT, LENGTH MUST BE > 3 "< r1 if (( a1*P.x + b1*P.y + c1 ) < 0 ) { if ( a1 != 0 ) a1 = -a1 ; // (if ..) prevent assignment " -0 " if ( b1 != 0 ) b1 = -b1 ; if ( c1 != 0 ) c1 = -c1 ; } // I want P < r2 if (( a2*P.x + b2*P.y + c2 ) > 0 ) { if ( a2 != 0 ) a2 = -a2 ; // (if ..) prevent assignment " -0 " if ( b2 != 0 ) b2 = -b2 ; if ( c2 != 0 ) c2 = -c2 ; } } /** No descriptions */ void BounceSegmentOb::setBounceDir(double xdir,double ydir) { samuele::Vector v1,P; vect_Dir.x = xdir; vect_Dir.y = ydir; vect_Dir.z = 0.0; if ( ! bounce_segment ) { cout<<"ERROR: FIRST SET BounceLine THEN SET BounceDirection"< 0 ) vect_n=v1; else { vect_n.x = - v1.x; vect_n.y = - v1.y; vect_n.z = 0.0 ; if ( vect_n.x == 0 ) vect_n.x = 0.0 ; // remove +0 -0 if ( vect_n.y == 0 ) vect_n.y = 0.0 ; } if ( (v1*(vect_Dir.unit())) == 0 ) { cout<<"ERROR: INVALID BOUNCE DIRECTION (BounceDir parallel to edge segment)"< r P = A + vect_Dir*10 ; if (( a*P.x + b*P.y + c ) < 0 ) { if ( a != 0 ) a = -a ; // (if ..) prevent assignment " -0 " if ( b != 0 ) b = -b ; if ( c != 0 ) c = -c ; } is_a_bouncer = true; } /** No descriptions */ double BounceSegmentOb::CPrediction(Ball * ball) { if ( !is_a_bouncer ) return -1; samuele::Vector P,K,J; double time,delta,deltax,deltay; double ak,bk,ck,my_sqrt; // vel = 0 , the ball is stopped if (( ball->vect_Vel.x == 0.0 )&&( ball->vect_Vel.y == 0.0 )) return -1 ; double dist; //usefull "dist" on debug operations dist=a*(ball->vect_Pos.x) + b*(ball->vect_Pos.y) + c ; if ( dist < 0 ) dist = -dist ; dist = dist/sqrt(a*a + b*b); // is come to this segment ? if (( (ball->vect_Vel.unit()*vect_n) > 0 )||(( a*(ball->vect_Pos.x) + b*(ball->vect_Pos.y) + c ) <= 0 )) return -1 ; P = ball->vect_Pos - ( vect_n*(ball->diameter/2) ) ; // rk from P position J = P + ball->vect_Vel ; ak = J.y - P.y ; bk = P.x - J.x ; ck = P.y*(J.x - P.x) - P.x*(J.y - P.y) ; delta = a*bk - b*ak ; if ( delta == 0 ) return -1; // rk parallel to r deltax = -c*bk + b*ck ; deltay = -a*ck + c*ak ; // K (a point on r) K.x = deltax/delta ; K.y = deltay/delta ; //if (( ball->ballnumber == 0 )&&(dist < 30)) cout<<" --- "<ballnumber == 0 )&&(dist < 30)) cout<<" edgenum="<= 0 )&&( ( a2*K.x + b2*K.y + c2 ) <= 0 )) { time = ((K - P).abs())/(ball->vect_Vel.abs()); } else { P = ball->vect_Pos ; // rk from ball->vect_Pos J = P + ball->vect_Vel ; ak = J.y - P.y ; bk = P.x - J.x ; ck = P.y*(J.x - P.x) - P.x*(J.y - P.y) ; // Bounce out from margin points Ak,Bk (near A,B points) my_sqrt = sqrt(ak*ak + bk*bk); if (( fabs(ak*Ak.x + bk*Ak.y + ck)/my_sqrt ) <= ((ball->diameter)/2) ) { J = Ak - P; time = (J.abs() - (ball->diameter)/2)/(ball->vect_Vel*(J.unit())); } else if (( fabs(ak*Bk.x + bk*Bk.y + ck)/my_sqrt ) <= ((ball->diameter)/2) ) { J = Bk - P; time = (J.abs() - (ball->diameter)/2)/(ball->vect_Vel*(J.unit())); } else time = -1 ; } //if (( ball->ballnumber == 0 )&&(dist < 30)) cout<<" edgenum="<vect_Pos.x) + b*(ball->vect_Pos.y) + c ; xvel=ball->vect_Vel.x; yvel=ball->vect_Vel.y; xhit=vect_Dir.x ; yhit=vect_Dir.y ; if (xhit != 0 || yhit != 0) // x & y direction == 0 -> no bounce { P = ball->vect_Pos ; n2 = (B - A).unit(); modhit=sqrt(xhit*xhit + yhit*yhit); projection=(xhit/modhit)*xvel + (yhit/modhit)*yvel; if ( projection < 0 ) // the ball direction is opposite of the edge one { if (( a1*(P.x) + b1*(P.y) + c1 ) <= 0 ) {// ball going to A point n2 = (P - A).unit(); // bounce out direction from A point projection = ball->vect_Vel*n2 ; if ( projection < 0 ) { xvel=xvel - 2*projection*(n2.x); yvel=yvel - 2*projection*(n2.y); //if ( (P - A).abs() < ( Ball_Physics::diameter / 2 ) ) // cout<<"P-A ="<<(P - A).abs()<vect_Vel*n2 ; if ( projection < 0 ) { xvel=xvel - 2*projection*(n2.x); yvel=yvel - 2*projection*(n2.y); //if ( (P - B).abs() < ( Ball_Physics::diameter / 2 ) ) // cout<<"P-B ="<<(P - B).abs()<