diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-10-02 16:19:30 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-10-02 16:19:30 -0400 |
| commit | 26ce765feb702c6d40f89a8cf50274869cdc35b4 (patch) | |
| tree | 7da69540057e9bcfa89d462f301dc215fbc21734 | |
| parent | a59cd43105f938a5acb84d30dc9aaa92f675c966 (diff) | |
| download | balls-26ce765feb702c6d40f89a8cf50274869cdc35b4.zip | |
ball collisions
| -rw-r--r-- | balls.cpp | 13 | ||||
| -rw-r--r-- | balls.h | 17 | ||||
| -rw-r--r-- | collision.cpp | 28 | ||||
| -rw-r--r-- | geometry.cpp | 95 |
4 files changed, 149 insertions, 4 deletions
@@ -6,7 +6,7 @@ using namespace std; -#define VMAX_INIT 0.15 +#define VMAX_INIT 0.05 /* max initial velocity [m/s] */ #define RMIN 0.05 #define RMAX 0.10 @@ -183,9 +183,14 @@ volume(double radius) { void animate(int v) { - for (Ball& ball : balls) { - ball.p = ptAddVec(ball.p, ball.v); - collideWall(&ball, bounds); + size_t i, j; + + /* TODO: parallel */ + for (i = 0; i < balls.size(); i++) { + for (j = i+1; j < balls.size(); j++) + collideBall(&balls[i], &balls[j]); + balls[i].p = ptAddVec(balls[i].p, balls[i].v); + collideWall(&balls[i], bounds); } display(); @@ -19,13 +19,30 @@ typedef struct { double m; /* mass [kg] */ } Ball; +Point addPt(Point p, Point q); +Point subPt(Point p, Point q); Point ptAddVec(Point p, Vector v); +Point ptSubVec(Point p, Vector v); +Point ptMulS(Point p, double s); +Point ptDivS(Point p, double s); Point Pt(double x, double y); + +Vector addVec(Vector v1, Vector v2); +Vector subVec(Vector v1, Vector v2); +Vector vecMulS(Vector v, double s); +Vector vecDivS(Vector v, double s); +double vecDot(Vector v1, Vector v2); +Vector unitNorm(Vector v); +double vecLen(Vector v); +Vector Vec(double x, double y); +Vector VecPt(Point p, Point q); + Rectangle insetRect(Rectangle r, double n); Point randPtInRect(Rectangle r); int isCollision(Point p1, double r1, Point p2, double r2); void collideWall(Ball *b, Rectangle wall); +void collideBall(Ball *b1, Ball *b2); int randInt(int lo, int hi); double randDouble(double lo, double hi); diff --git a/collision.cpp b/collision.cpp index 1ffe957..5f0725e 100644 --- a/collision.cpp +++ b/collision.cpp @@ -27,6 +27,34 @@ collideWall(Ball *b, Rectangle wall) { } } +void +collideBall(Ball *b1, Ball *b2) { + Point midpt; + Vector n, distv; + double mrat, coef; + + if (!isCollision(b1->p, b1->r, b2->p, b2->r)) + return; + + /* set position of collision */ + midpt = ptDivS(addPt(b1->p, b2->p), 2); + n = unitNorm(VecPt(b1->p, b2->p)); + b1->p = ptSubVec(midpt, vecMulS(n, b1->r)); + b2->p = ptAddVec(midpt, vecMulS(n, b2->r)); + + /* reaction velocity */ + + mrat = 2.0 * b2->m / (b1->m + b2->m); + distv = VecPt(b2->p, b1->p); + coef = vecDot(subVec(b1->v, b2->v), distv) / (vecLen(distv)*vecLen(distv)); + b1->v = subVec(b1->v, vecMulS(distv, mrat*coef)); + + mrat = 2.0 * b1->m / (b1->m + b2->m); + distv = VecPt(b1->p, b2->p); + coef = vecDot(subVec(b2->v, b1->v), distv) / (vecLen(distv)*vecLen(distv)); + b2->v = subVec(b2->v, vecMulS(distv, mrat*coef)); +} + static double clamp(double v, double lo, double hi) { return min(hi, max(v, lo)); diff --git a/geometry.cpp b/geometry.cpp index 2bdad8c..542c08d 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1,6 +1,22 @@ +#include <math.h> + #include "balls.h" Point +addPt(Point p, Point q) { + p.x += q.x; + p.y += q.y; + return p; +} + +Point +subPt(Point p, Point q) { + p.x -= q.x; + p.y -=q.y; + return p; +} + +Point ptAddVec(Point p, Vector v) { p.x += v.x; p.y += v.y; @@ -8,11 +24,90 @@ ptAddVec(Point p, Vector v) { } Point +ptSubVec(Point p, Vector v) { + p.x -= v.x; + p.y -= v.y; + return p; +} + +Point +ptMulS(Point p, double s) { + p.x *= s; + p.y *= s; + return p; +} + +Point +ptDivS(Point p, double s) { + p.x /= s; + p.y /=s; + return p; +} + +Point Pt(double x, double y) { Point p = {x, y}; return p; } +Vector +addVec(Vector v1, Vector v2) { + v1.x += v2.x; + v1.y += v2.y; + return v1; +} + +Vector +subVec(Vector v1, Vector v2) { + v1.x -= v2.x; + v1.y -= v2.y; + return v1; +} + +Vector +vecMulS(Vector v, double s) { + v.x *= s; + v.y *= s; + return v; +} + +Vector +vecDivS(Vector v, double s) { + v.x /= s; + v.y /= s; + return v; +} + +double +vecDot(Vector v1, Vector v2) { + return v1.x*v2.x + v1.y*v2.y; +} + +Vector +unitNorm(Vector v) { + return vecDivS(v, vecLen(v)); +} + +double +vecLen(Vector v) { + return sqrt(v.x*v.x + v.y*v.y); +} + +Vector +Vec(double x, double y) { + Vector v = {x, y}; + return v; +} + +Vector +VecPt(Point p, Point q) { + double dx, dy; + + dx = q.x - p.x; + dy = q.y - p.y; + return Vec(dx, dy); +} + Rectangle insetRect(Rectangle r, double n) { r.min.x += n; |