This blog post is going to be more code then text as the code has plenty of comments and typing it again would be overly redundant. To determine collision between two spheres in a given time step we calculate the "next" position of each spheres and pass both of them in addition to the "current" position of the sphere to the function. With that we have the following algorithm:
This snippet relies on quite a bit of framework, namely the Vector class, here it is:
Create four Vector position pointers (which represent the beginning and ending positions of two spheres) and pass them to the function to determine if the two spheres will collide during their movement in that "timestep". Thanks for reading. Feel free to ask questions, offer guidance, pointers, criticisms, etc...
--KYA
bool Vector::hasCollision(Vector* oneStart, Vector* oneEnd, Vector* twoStart, Vector* twoEnd)
{
/*A simple way to check for collision between two spheres given the start and end position for a given time frame
is to see the smallest distance between them--ever
d^2 = a^2-(A*B)^2/b^2
lower case letters are the magnitude of each vector where the upper case are the actual vectors
Given two spheres P and Q with two points P1, Q1, etc... we have two vectors A and B where
A = P1-Q1
B = (P2-P1)-(Q2-Q1)
if distance < (rp+rq)^2, there is a collision (r is the radius of each respective sphere)
*/
double distance, t = 0;
double rOne = 10, rTwo = 15; //example radii, most likely will be passed as parameters
Vector* A = new Vector();
Vector* B = new Vector();
//Calculate A and B vectors
*A = *oneStart - *twoStart;
*B = (*oneEnd - *oneStart)-(*twoEnd - *twoStart);
distance = pow(A->getMagnitude(), 2.0) - ((pow(A->numericalDotProduct(B),2.0))/pow(B->getMagnitude(),2.0));
//get time (collision between t0 and t1 timesteps):
//quadratic equation equivalent if t is between 0 and 1 that is collision time within the timestamp
t = -(A->numericalDotProduct(B));
cout << "t: " << t << endl;
t -= sqrt((pow(A->numericalDotProduct(B),2.0)) - ((pow(B->getMagnitude(),2.0))*(pow(A->getMagnitude(),2.0)-(pow(rOne+rTwo,2.0)))));
cout << "t: " << t << endl;
t/= pow(B->getMagnitude(),2.0);
cout << "t: " << t << endl;
//clean up
delete A, B;
if (distance < pow(rOne + rTwo, 2.0))
return true;
else
return false;
}
This snippet relies on quite a bit of framework, namely the Vector class, here it is:
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
using std::ostream;
class Vector {
private:
double x, y, z;
public:
Vector() { x = y = z = 0; };
Vector(double pX, double pY, double pZ) { x = pX; y = pY; z = pZ; };
~Vector() {};
void setX(double pX) { x = pX; };
void setY(double pY) { y = pY; };
void setZ(double pZ) { z = pZ; };
double getX() { return x; };
double getY() { return y; };
double getZ() { return z; };
double getMagnitude();
Vector normalize();
Vector crossProduct(Vector*, Vector*);
Vector dotProduct(Vector*);
double numericalDotProduct(Vector*);
Vector scalarMultiplication(double);
void gravitationalAcceleration(Vector*);
bool hasCollision(Vector*, Vector*, Vector*, Vector*);
Vector operator+(Vector&);
Vector operator-(Vector&);
Vector operator=(Vector&);
friend ostream& operator<< (ostream& os, Vector& vect)
{
os << "[" << vect.getX() << ", " << vect.getY() << ", " <<
vect.getZ() << "]";
return os;
}
};
#endif
//corresponding cpp file:
#include <iostream>
#include <cmath>
#include "Vector.h"
using namespace std;
double Vector::getMagnitude()
{
double magnitude = sqrt(x*x+y*y+z*z);
return magnitude;
}
Vector Vector::normalize()
{
double length = this->getMagnitude();
Vector temp;
temp.setX(this->getX()/length);
temp.setY(this->getY()/length);
temp.setZ(this->getZ()/length);
return temp;
}
Vector Vector::crossProduct(Vector* vectOne, Vector* vectTwo)
{
Vector temp;
temp.setX(vectOne->getY()*vectTwo->getZ()-vectOne->getZ()*vectTwo->getY());
temp.setY(vectOne->getZ()*vectTwo->getX()-vectOne->getX()*vectTwo->getZ());
temp.setZ(vectOne->getX()*vectTwo->getY()-vectOne->getY()*vectTwo->getX());
return temp;
}
Vector Vector::dotProduct(Vector* vectTwo)
{
Vector temp;
temp.setX(this->getX()*vectTwo->getX());
temp.setY(this->getY()*vectTwo->getY());
temp.setZ(this->getZ()*vectTwo->getZ());
return temp;
}
double Vector::numericalDotProduct(Vector* vectTwo)
{
double temp = 0;
temp = this->getX()*vectTwo->getX()+ this->getY()*vectTwo->getY()+ this->getZ()*vectTwo->getZ();
return temp;
}
Vector Vector::scalarMultiplication(double num)
{
Vector temp;
temp.setX(this->getX()*num);
temp.setY(this->getY()*num);
temp.setZ(this->getZ()*num);
return temp;
}
void Vector::gravitationalAcceleration(Vector* vInit)
{
//given the gravity vector Earth [0, 0, -9.81] and the particle initial position (the vector itself)
// and the velocity desired we can calculate where it moves in 't' timesteps, a second for example
//as long as the velocity is not parallel to the gravity, the result will be parabolic
//*************Equation*******************
// p(t) = pInit + vInit*(t-tInit) + (1/2)*gravity*(t-tInit)^2
//****************************************
//This example assumes a start time of 0, so we begin with the position at t = 1
Vector* curPosition = new Vector();
Vector* gravity = new Vector(0, 0, -9.81);
for(int i = 1; i <= 10; i++) //10 moments in time
{
*curPosition = *this + vInit->scalarMultiplication(i);
*curPosition = *curPosition + gravity->scalarMultiplication(0.5*(pow(i,2.0)));
cout << *curPosition << endl;
}
delete curPosition, gravity;
}
bool Vector::hasCollision(Vector* oneStart, Vector* oneEnd, Vector* twoStart, Vector* twoEnd)
{
/*A simple way to check for collision between two spheres given the start and end position for a given time frame
is to see the smallest distance between them--ever
d^2 = a^2-(A*B)^2/b^2
lower case letters are the magnitude of each vector where the upper case are the actual vectors
Given two spheres P and Q with two points P1, Q1, etc... we have two vectors A and B where
A = P1-Q1
B = (P2-P1)-(Q2-Q1)
if distance < (rp+rq)^2, there is a collision (r is the radius of each respective sphere)
*/
double distance, t = 0;
double rOne = 10, rTwo = 15; //example radii, most likely will be passed as parameters
Vector* A = new Vector();
Vector* B = new Vector();
//Calculate A and B vectors
*A = *oneStart - *twoStart;
*B = (*oneEnd - *oneStart)-(*twoEnd - *twoStart);
distance = pow(A->getMagnitude(), 2.0) - ((pow(A->numericalDotProduct(B),2.0))/pow(B->getMagnitude(),2.0));
//get time (coliision between t0 and t1 timesteps):
//quadratic equation equivalent if t is between 0 and 1 that is collision tiem within the timestamp
t = -(A->numericalDotProduct(B));
cout << "t: " << t << endl;
t -= sqrt((pow(A->numericalDotProduct(B),2.0)) - ((pow(B->getMagnitude(),2.0))*(pow(A->getMagnitude(),2.0)-(pow(rOne+rTwo,2.0)))));
cout << "t: " << t << endl;
t/= pow(B->getMagnitude(),2.0);
cout << "t: " << t << endl;
//clean up
delete A, B;
if (distance < pow(rOne + rTwo, 2.0))
return true;
else
return false;
}
Vector Vector::operator+(Vector& rhs)
{
Vector temp;
temp.setX(this->getX() + rhs.getX());
temp.setY(this->getY() + rhs.getY());
temp.setZ(this->getZ() + rhs.getZ());
return temp;
}
Vector Vector::operator-(Vector& rhs)
{
Vector temp;
temp.setX(this->getX() - rhs.getX());
temp.setY(this->getY() - rhs.getY());
temp.setZ(this->getZ() - rhs.getZ());
return temp;
}
Vector Vector::operator=(Vector& rhs)
{
this->setX(rhs.getX());
this->setY(rhs.getY());
this->setZ(rhs.getZ());
return *this;
}
Create four Vector position pointers (which represent the beginning and ending positions of two spheres) and pass them to the function to determine if the two spheres will collide during their movement in that "timestep". Thanks for reading. Feel free to ask questions, offer guidance, pointers, criticisms, etc...
--KYA
0 Comments On This Entry
← January 2022 →
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |
Tags
My Blog Links
Recent Entries
Recent Comments
Search My Blog
19 user(s) viewing
19 Guests
0 member(s)
0 anonymous member(s)
0 member(s)
0 anonymous member(s)



Leave Comment









|