I've been working on getting Catmull-Rom splines working for a side project and am having difficulty getting it to do what I need. I tried the following two implementations and both didn't work for me, and I was unable to track down any errors in my code relative to theirs (which I have to assume has been tested). I'll call theirs the "ABC" solution:
Catmull-rom curve with no cusps and no self-intersections
https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
I then implemented the following solution (that I call the "Matrix" solution) and it did work using the edited version 3 posts down: https://www.opengl.org/discussion_boards/showthread.php/159518-catmull-rom-spline
However, this Matrix solution just implements Catmull-Rom with a 0.5 'a' value built into the matrix. I'd like to get Chordal working, and thus I need 'a' == 1.
Given that my solution for the ABC version was causing problems, I've attempted to use the matrix here (http://algorithmist.net/docs/catmullrom.pdf) to pass in my own 'a'. Here's the original 0.5 code followed by my modified code that's passing in a user specified 'a'.
Original Code:
float u2 = u * u;
float u3 = u2 * u;
return ((2 * x1) +
(-x0 + x2) * u +
(2*x0 - 5*x1 + 4*x2 - x3) * u2 +
(-x0 + 3*x1 - 3*x2 + x3) * u3) * 0.5f;
Modified Code:
float u2 = u * u;
float u3 = u2 * u;
static float a = 0.5f;
return ((1.0f * x1) +
((-a*x0) + (a*x2)) * u +
((2.0f*a)*x0 + (a-3.0f)*x1 + (3.0f-(2.0f*a))*x2 + (-a*x3)) * u2 +
((-a*x0) + (2.0f-a)*x1 + (a-2.0f)*x2 + (a*3.0f)) * u3) * 0.5f;
This of course doesn't work. However, I'm not seeing why. At the bottom of page 4 in the pdf it shows the matrix with 'a' in it. I've substituted that in the above modified code and triple checked it, yet the spline is screwed up. It should have given me the same answer. What's doubly confusing is that his results on page 5 take that resulting matrix and multiply it by 0.5 which drops all the /2's off the matrix entries. The final matrix uses THESE values, but the original matrix on page 4 is not 0.5 * matrix, it's just "matrix". Why was this 0.5 arbitrarily added and why does everything break without it?
Anyway, does anyone know what I might be doing wrong with my equation? Can I use this matrix form to pass in my own 'a' from 0-1 and create uniform, centripetal and chordal splines or will I have to use the ABC form?
Thanks in advance!
I think the matrix with 'a' in page 4 of the pdf file is still for uniform Catmull-Rom (CR) spline. The parameter 'a' is the tension parameter. In the Wiki page (https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline), it also use a 'alpha' for controlling the knot sequences assigned to each point. Don't confuse the tension parameter 'a' with this 'alpha'.
A "standard" uniform CR spline will have alpha=0.0 (which will result in a=0.5). You will need to use alpha=1.0 for chordal CR spline and alpha=0.5 for centripetal CR spline. Their corresponding matrix form will both involve the knot sequences of the points. So, using a=1.0 in the matrix form for uniform CR spline will not result in a chordal CR spline but a uniform CR spline with stronger tangents at the data points, which typically will cause undesired spline shape.
Related
I can't quite figure this one out.
I am trying to approximate the location (latitude / longitude) of a beacon based on 3 distance measurements from 3 fixed locations. However the distance readings available may have an error of up to 1 km.
Similar questions regarding trilateration have been asked here (with precise measurements), here, here (distance measurement errors in Java, but not in lat/lon coordinates and no answers) as well as others. I also managed to dig up this paper dealing with imperfect measurement data, however it for one assumes a cartesian coordinate system and is also rather mathematical than close to a usable implementation.
So none of above links and answers are really applicable to the following problem:
All available distance measurements are approximated in km (where data most frequently contains readings in-between 1 km and 100 km, in case this matters)
Measurement errors of up to 1 km are possible.
3 distance measurements are performed based on 3 fixed (latitude / longitude known) positions.
target approximation should also be a latitude / longitude combination.
So far I have adapted this Answer to C#, however I noticed that due to the measurement inaccuracies this algorithm does not work (as the algorithm assumes the 3 distance-circles to perfectly intersect with each other):
public static class Trilateration
{
public static GeoLocation Compute(DistanceReading point1, DistanceReading point2, DistanceReading point3)
{
// not my code :P
// assuming elevation = 0
const double earthR = 6371d;
//using authalic sphere
//if using an ellipsoid this step is slightly different
//Convert geodetic Lat/Long to ECEF xyz
// 1. Convert Lat/Long to radians
// 2d. Convert Lat/Long(radians) to ECEF
double xA = earthR * (Math.Cos(Radians(point1.GeoLocation.Latitude)) * Math.Cos(Radians(point1.GeoLocation.Longitude)));
double yA = earthR * (Math.Cos(Radians(point1.GeoLocation.Latitude)) * Math.Sin(Radians(point1.GeoLocation.Longitude)));
double zA = earthR * Math.Sin(Radians(point1.GeoLocation.Latitude));
double xB = earthR * (Math.Cos(Radians(point2.GeoLocation.Latitude)) * Math.Cos(Radians(point2.GeoLocation.Longitude)));
double yB = earthR * (Math.Cos(Radians(point2.GeoLocation.Latitude)) * Math.Sin(Radians(point2.GeoLocation.Longitude)));
double zB = earthR * (Math.Sin(Radians(point2.GeoLocation.Latitude)));
double xC = earthR * (Math.Cos(Radians(point3.GeoLocation.Latitude)) * Math.Cos(Radians(point3.GeoLocation.Longitude)));
double yC = earthR * (Math.Cos(Radians(point3.GeoLocation.Latitude)) * Math.Sin(Radians(point3.GeoLocation.Longitude)));
double zC = earthR * Math.Sin(Radians(point3.GeoLocation.Latitude));
// a 64 bit Vector3 implementation :)
Vector3_64 P1 = new(xA, yA, zA);
Vector3_64 P2 = new(xB, yB, zB);
Vector3_64 P3 = new(xC, yC, zC);
//from wikipedia
//transform to get circle 1 at origin
//ransform to get circle 2d on x axis
Vector3_64 ex = (P2 - P1).Normalize();
double i = Vector3_64.Dot(ex, P3 - P1);
Vector3_64 ey = (P3 - P1 - i * ex).Normalize();
Vector3_64 ez = Vector3_64.Cross(ex, ey);
double d = (P2 - P1).Length;
double j = Vector3_64.Dot(ey, P3 - P1);
//from wikipedia
//plug and chug using above values
double x = (Math.Pow(point1.DistanceKm, 2d) - Math.Pow(point2.DistanceKm, 2d) + Math.Pow(d, 2d)) / (2d * d);
double y = ((Math.Pow(point1.DistanceKm, 2d) - Math.Pow(point3.DistanceKm, 2d) + Math.Pow(i, 2d) + Math.Pow(j, 2d)) / (2d * j)) - ((i / j) * x);
// only one case shown here
double z = Math.Sqrt(Math.Pow(point1.DistanceKm, 2d) - Math.Pow(x, 2d) - Math.Pow(y, 2d));
//triPt is a vector with ECEF x,y,z of trilateration point
Vector3_64 triPt = P1 + x * ex + y * ey + z * ez;
//convert back to lat/long from ECEF
//convert to degrees
double lat = Degrees(Math.Asin(triPt.Z / earthR));
double lon = Degrees(Math.Atan2(triPt.Y, triPt.X));
return new GeoLocation(lat, lon);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double Radians(double degrees) =>
degrees * Math.Tau / 360d;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double Degrees(double radians) =>
radians * 360d / Math.Tau;
}
Above code most often than not does not work in my case, and instead only returns "Not a number" as it tries to take the square root of a negative number when calculating the final z value (due to measurement inaccuracies).
In my case measurements may return data like this (visualized with some random online tool):
where only 2 or even none of the distance circles intersect:
What I am looking for is the an algorithm returning the best possible approximation of the target location based on three distance measurements with a known maximum error of 1 km or further approaches I could take.
I have also thought of iterating over points on the circles to then determining the minimum average distance to all the points on the other circles but the 3-dimensional sphere geometry of the earth is giving me a headache. Also there's probably a way better and simpler approach to this which I just can't figure out right now.
As this is more of an algorithmic problem, rather than any language-specific thing, I appreciate any help in whatever programming language, pseudo code or natural language.
If you have access to a scientific computing library which provides non-linear optimization utilities, then you could try finding the point which minimizes the following:
(||x - p_1|| - r_1)^2 + (||x - p_2|| - r_2)^2 + (||x - p_3|| - r_3)^2 + (||x - p_earth|| - r_earth)^2
where p_i is the location (in Cartesian coordinates) of the ith location you measure from, r_i is the corresponding distance reading, p_earth is the location of the Earth, r_earth is the radius of the earth, and ||a|| denotes the norm/length of the vector a.
Each term in the expression is trying to minimize the residual radius error.
This can of course be modified to suit your needs - e.g. if constrained optimization is available, you could encode the requirement that the point be on the surface on the earth as a constraint rather than a term to optimize for. If spherical earth model isn't accurate enough, you could define an error from the Earth's surface, or just project your result onto the Earth if that is accurate enough.
The problem is as follows:
Given two different points P1 = (x1,y1), P2 = (x2,y2) and point G=(a,b), find c and d such that G'=(c,d) is the reflection of G about the line P1P2
What I am looking for is a method to do this quickly. Since I am working on floating point numbers, I'd also like to use a method which minimizes the absolute value of the exponent in scientific notation, but that is second priority.
What I have tried: let R be the vector which is the projection of vector (G-P1) onto vector (P2-P1). Then, the reflection is achieved by taking Q = P1 + R, which is the projection of G onto the line, and then G' = 2Q-G. Now this is all cool and dandy, but calculating the projection is the hard part here.
How I calculate the projection of vector A onto B:
The scalar product of A and B is |A|*|B|*cos(theta), where theta is the directed angle from A to B. You can obtain the value of the scalar product by taking xAxB + yAyB. But the projection is of length |A|*cos(theta), so we have to divide the scalar product by |B|. Now, we have the length, but not the direction. The direction is along vector B, so we must multiply by the unit vector along B, which is B/|B|. Ultimately, we get the formula (xAxB + yAyB)*B/|B|2.
The actual problem:
This is kind of a roundabout way to do this, and I am looking for a more direct formula from the coordinates. Additionally (although less important), calculating the length of a vector as I need to do in computing the projection and scalar product is problematic, when the numbers I am working on are big, because I may get a floating point overflow or something like that.
If this is of any significance, I am working in OCaml.
Thanks in advance
Formulas are really very simple.
Projection (for line AB and point P) seems similar to yours:
L = A + AB * ScalarProduct(AB, AP) / ScalarProduct(AB, AB)
Reflection point
P' = P + 2*(L-P) = 2*L-P
Working Python example:
def refl(x1, y1, x2, y2, xp, yp):
x12 = x2 - x1
y12 = y2 - y1
xxp = xp - x1
yyp = yp - y1
dotp = x12 * xxp + y12 * yyp
dot12 = x12 * x12 + y12 * y12
coeff = dotp / dot12
lx = x1 + x12 * coeff
ly = y1 + y12 * coeff
return 2*lx-xp, 2*ly-yp
print(refl(0, 0, 2, 2, 0, 1))
>>> (1.0, 0.0)
I'm trying to deduct the 2D-transformation parameters from the result.
Given is a large number of samples in an unknown X-Y-coordinate system as well as their respective counterparts in WGS84 (longitude, latitude). Since the area is small, we can assume the target system to be flat, too.
Sadly I don't know which order of scale, rotate, translate was used, and I'm not even sure if there were 1 or 2 translations.
I tried to create a lengthy equation system, but that ended up too complex for me to handle. Basic geometry also failed me, as the order of transformations is unknown and I would have to check every possible combination order.
Is there a systematic approach to this problem?
Figuring out the scaling factor is easy, just choose any two points and find the distance between them in your X-Y space and your WGS84 space and the ratio of them is your scaling factor.
The rotations and translations is a little trickier, but not nearly as difficult when you learn that the result of applying any number of rotations or translations (in 2 dimensions only!) can be reduced to a single rotation about some unknown point by some unknown angle.
Suddenly you have N points to determine 3 unknowns, the axis of rotation (x and y coordinate) and the angle of rotation.
Calculating the rotation looks like this:
Pr = R*(Pxy - Paxis_xy) + Paxis_xy
Pr is your rotated point in X-Y space which then needs to be converted to WGS84 space (if the axes of your coordinate systems are different).
R is the familiar rotation matrix depending on your rotation angle.
Pxy is your unrotated point in X-Y space.
Paxis_xy is the axis of rotation in X-Y space.
To actually find the 3 unknowns, you need to un-scale your WGS84 points (or equivalently scale your X-Y points) by the scaling factor you found and shift your points so that the two coordinate systems have the same origin.
First, finding the angle of rotation: take two corresponding pairs of points P1, P1' and P2, P2' and write out
P1' = R(P1-A) + A
P2' = R(P2-A) + A
where I swapped A = Paxis_xy for brevity. Subtracting the two equations gives:
P2'-P1' = R(P2-P1)
B = R * C
Bx = cos(a) * Cx - sin(a) * Cy
By = cos(a) * Cx + sin(a) * Cy
By + Bx = 2 * cos(a) * Cx
(By + Bx) / (2 * Cx) = cos(a)
...
(By - Bx) / (2 * Cy) = sin(a)
a = atan2(sin(a), cos(a)) <-- to get the right quadrant
And you have your angle, you can also do a quick check that cos(a) * cos(a) + sin(a) * sin(a) == 1 to make sure either you got all the calculations correct or that your system really is an orientation-preserving isometry (consists only of translations and rotations).
Now that we know a we know R and so to find A we do:
P1` = R(P1-A) + A
P1' - R*P1 = (I-R)A
A = (inverse(I-R)) * (P1' - R*P1)
where the inversion of a 2x2 matrix is easy.
EDIT: There is an error in the above, or more specifically one case that needs to be treated separately.
There is one combination of translations and rotations that does not reduce to a single rotation and that is a single translation. You can think of it in terms of fixed points (how many points are unchanged after the operation).
A translation has no fixed points (all points are changed) and a rotation has 1 fixed point (the axis doesn't change). It turns out that two rotations leave 1 fixed point and a translation and a rotation leaves 1 fixed point, which (with a little proof that says the number of fixed points tells you the operation performed) is the reason that arbitrary combinations of these result in a single rotation.
What this means for you is that if your angle comes out as 0 then using the method above will give you A = 0 as well, which is likely incorrect. In this case you have to do A = P1' - P1.
If I understood the question correctly, you have n points (X1,Y1),...,(Xn,Yn), the corresponding points, say, (x1,y1),...,(xn,yn) in another coordinate system, and the former are supposedly obtained from the latter by rotation, scaling and translation.
Note that this data does not determine the fixed point of rotation / scaling, or the order in which the operations "should" be applied. On the other hand, if you know these beforehand or choose them arbitrarily, you will find a rotation, translation and scaling factor that transform the data as supposed to.
For example, you can pick an any point, say, p0 = [X1, Y1]T (column vector) as the fixed point of rotation & scaling and subtract its coordinates from those of two other points to get p2 = [X2-X1, Y2-Y1]T, and p3 = [X3-X1, Y3-Y1]T. Also take the column vectors q2 = [x2-x1, y2-y1]T, q3 = [x3-x1, y3-y1]T. Now [p2 p3] = A*[q2 q3], where A is an unknwon 2x2 matrix representing the roto-scaling. You can solve it (unless you were unlucky and chose degenerate points) as A = [p2 p3] * [q2 q3]-1 where -1 denotes matrix inverse (of the 2x2 matrix [q2 q3]). Now, if the transformation between the coordinate systems really is a roto-scaling-translation, all the points should satisfy Pk = A * (Qk-q0) + p0, where Pk = [Xk, Yk]T, Qk = [xk, yk]T, q0=[x1, y1]T, and k=1,..,n.
If you want, you can quite easily determine the scaling and rotation parameter from the components of A or combine b = -A * q0 + p0 to get Pk = A*Qk + b.
The above method does not react well to noise or choosing degenerate points. If necessary, this can be fixed by applying, e.g., Principal Component Analysis, which is also just a few lines of code if MATLAB or some other linear algebra tools are available.
I am extracting in OpenGL the Model Matrix with
glGetFloatv (GL_MODELVIEW_MATRIX, (float*)x)
And would like to extract from the resulting 4x4 matrix the x,y and z axis rotations. How Can I do that ?
Thanks !
First you should know, that x,y,z axis rotations, called Euler Angles suffer from serious numerical problems. Also they're not unambigous. So either you store a rotation angle and the rotation axis, thus effectively forming a quaternion in disguise, or you stick with the full rotation matrix.
Find the quaternion from a rotation matrix is called an eigenvalue problem. Technically you're determining the eigenvector of the rotation matrix, which is the axis and the magnitude designates the angle.
I'm writing a CAD-like app, so I understand your problem, we 'in the business' know how awful Euler angles are for linear transformations - but the end-user finds them far more intuitive than matrices or quaternions.
For my app I interpreted Ken Shoemake's wonderful algorithm, it's one of the very few that support arbitrary rotation orders. It's from '93, so it's in pure C code - not for the faint hearted!
http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/
Something like this should give you what you're after.
final double roll = Math.atan2(2 * (quat.getW() * quat.getX() + quat.getY() * quat.getZ()),
1 - 2 * (quat.getX() * quat.getX() + quat.getY() * quat.getY()));
final double pitch = Math.asin(2 * (quat.getW() * quat.getY() - quat.getZ() * quat.getY()));
final double yaw = Math.atan2(2 * (quat.getW() * quat.getZ() + quat.getX() * quat.getY()), 1 - 2 * (quat.getY()
* quat.getY() + quat.getZ() * quat.getZ()));
I use this as a utility function to print out camera angles when I'm using SLERP to interpolate between 2 quaternions that I've derived from 2 4x4 matrices (i.e. camera movement between 2 3D points).
I am going to develop a 2-d ball game where two balls (circles) collide. Now I have the problem with determining the colliding point (in fact, determining whether they are colliding in x-axis/y-axis). I have an idea that when the difference between the y coordinate of 2 balls is greater than the x coordinate difference then they collide in their y axis, otherwise, they collide in their x axis. Is my idea correct? I implemented this thing in my games. Normally it works well, but sometimes, it fails. Can anyone tell me whether my idea is right? If not, then why, and is any better way?
By collision in the x axis, I mean the circle's 1st, 4th, 5th, or 8th octant, y axis means the circle's 2nd, 3rd, 6th, or 7th octant.
Thanks in advance!
Collision between circles is easy. Imagine there are two circles:
C1 with center (x1,y1) and radius r1;
C2 with center (x2,y2) and radius r2.
Imagine there is a line running between those two center points. The distance from the center points to the edge of either circle is, by definition, equal to their respective radii. So:
if the edges of the circles touch, the distance between the centers is r1+r2;
any greater distance and the circles don't touch or collide; and
any less and then do collide.
So you can detect collision if:
(x2-x1)^2 + (y2-y1)^2 <= (r1+r2)^2
meaning the distance between the center points is less than the sum of the radii.
The same principle can be applied to detecting collisions between spheres in three dimensions.
Edit: if you want to calculate the point of collision, some basic trigonometry can do that. You have a triangle:
(x1,y1)
|\
| \
| \ sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2
|y2-y1| | \
| \
| X \
(x1,y2) +------+ (x2,y2)
|x2-x1|
The expressions |x2-x1| and |y2-y1| are absolute values. So for the angle X:
|y2 - y1|
sin X = -------
r1 + r2
|x2 - x1|
cos X = -------
r1 + r2
|y2 - y1|
tan X = -------
|x2 - x1|
Once you have the angle you can calculate the point of intersection by applying them to a new triangle:
+
|\
| \
b | \ r2
| \
| X \
+-----+
a
where:
a
cos X = --
r2
so
a = r2 cos X
From the previous formulae:
|x2 - x1|
a = r2 -------
r1 + r2
Once you have a and b you can calculate the collision point in terms of (x2,y2) offset by (a,b) as appropriate. You don't even need to calculate any sines, cosines or inverse sines or cosines for this. Or any square roots for that matter. So it's fast.
But if you don't need an exact angle or point of collision and just want the octant you can optimize this further by understanding something about tangents, which is:
0 <= tan X <= 1 for 0 <= X <= 45 degrees;
tan X >= 1 for 45 <= X <= 90
0 >= tan X >= -1 for 0 >= X => -45;
tan X <= -1 for -45 >= X => -90; and
tan X = tan (X+180) = tan (X-180).
Those four degree ranges correspond to four octants of the cirlce. The other four are offset by 180 degrees. As demonstrated above, the tangent can be calculated simply as:
|y2 - y1|
tan X = -------
|x2 - x1|
Lose the absolute values and this ratio will tell you which of the four octants the collision is in (by the above tangent ranges). To work out the exact octant just compare x1 and x2 to determine which is leftmost.
The octant of the collision on the other single is offset (octant 1 on C1 means octant 5 on C2, 2 and 6, 3 and 7, 4 and 8, etc).
As cletus says, you want to use the sum of the radii of the two balls. You want to compute the total distance between the centers of the balls, as follows:
Ball 1: center: p1=(x1,y1) radius: r1
Ball 2: center: p2=(x2,y2) radius: r2
collision distance: R= r1 + r2
actual distance: r12= sqrt( (x2-x1)^2 + (y2-y1)^2 )
A collision will happen whenever (r12 < R). As Artelius says, they shouldn't actually collide on the x/y axes, they collide at a particular angle. Except, you don't actually want that angle; you want the collision vector. This is the difference between the centers of the two circles when they collide:
collision vector: d12= (x2-x1,y2-y1) = (dx,dy)
actual distance: r12= sqrt( dx*dx + dy*dy )
Note that you have already computed dx and dy above when figuring the actual distance, so you might as well keep track of them for purposes like this. You can use this collision vector for determining the new velocity of the balls -- you're going to end up scaling the collision vector by some factors, and adding that to the old velocities... but, to get back to the actual collision point:
collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) )
To figure out how to find the new velocity of the balls (and in general to make more sense out of the whole situation), you should probably find a high school physics book, or the equivalent. Unfortunately, I don't know of a good web tutorial -- suggestions, anyone?
Oh, and if still want to stick with the x/y axis thing, I think you've got it right with:
if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis }
As for why it might fail, it's hard to tell without more information, but you might have a problem with your balls moving too fast, and passing right by each other in a single timestep. There are ways to fix this problem, but the simplest way is to make sure they don't move too fast...
This site explains the physics, derives the algorithm, and provides code for collisions of 2D balls.
Calculate the octant after this function calculates the following: position of collision point relative to centre of mass of body a; position of collision point relative to centre of mass of body a
/**
This function calulates the velocities after a 2D collision vaf, vbf, waf and wbf from information about the colliding bodies
#param double e coefficient of restitution which depends on the nature of the two colliding materials
#param double ma total mass of body a
#param double mb total mass of body b
#param double Ia inertia for body a.
#param double Ib inertia for body b.
#param vector ra position of collision point relative to centre of mass of body a in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
#param vector rb position of collision point relative to centre of mass of body b in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
#param vector n normal to collision point, the line along which the impulse acts.
#param vector vai initial velocity of centre of mass on object a
#param vector vbi initial velocity of centre of mass on object b
#param vector wai initial angular velocity of object a
#param vector wbi initial angular velocity of object b
#param vector vaf final velocity of centre of mass on object a
#param vector vbf final velocity of centre of mass on object a
#param vector waf final angular velocity of object a
#param vector wbf final angular velocity of object b
*/
CollisionResponce(double e,double ma,double mb,matrix Ia,matrix Ib,vector ra,vector rb,vector n,
vector vai, vector vbi, vector wai, vector wbi, vector vaf, vector vbf, vector waf, vector wbf) {
double k=1/(ma*ma)+ 2/(ma*mb) +1/(mb*mb) - ra.x*ra.x/(ma*Ia) - rb.x*rb.x/(ma*Ib) - ra.y*ra.y/(ma*Ia)
- ra.y*ra.y/(mb*Ia) - ra.x*ra.x/(mb*Ia) - rb.x*rb.x/(mb*Ib) - rb.y*rb.y/(ma*Ib)
- rb.y*rb.y/(mb*Ib) + ra.y*ra.y*rb.x*rb.x/(Ia*Ib) + ra.x*ra.x*rb.y*rb.y/(Ia*Ib) - 2*ra.x*ra.y*rb.x*rb.y/(Ia*Ib);
double Jx = (e+1)/k * (Vai.x - Vbi.x)( 1/ma - ra.x*ra.x/Ia + 1/mb - rb.x*rb.x/Ib)
- (e+1)/k * (Vai.y - Vbi.y) (ra.x*ra.y / Ia + rb.x*rb.y / Ib);
double Jy = - (e+1)/k * (Vai.x - Vbi.x) (ra.x*ra.y / Ia + rb.x*rb.y / Ib)
+ (e+1)/k * (Vai.y - Vbi.y) ( 1/ma - ra.y*ra.y/Ia + 1/mb - rb.y*rb.y/Ib);
Vaf.x = Vai.x - Jx/Ma;
Vaf.y = Vai.y - Jy/Ma;
Vbf.x = Vbi.x - Jx/Mb;
Vbf.y = Vbi.y - Jy/Mb;
waf.x = wai.x - (Jx*ra.y - Jy*ra.x) /Ia;
waf.y = wai.y - (Jx*ra.y - Jy*ra.x) /Ia;
wbf.x = wbi.x - (Jx*rb.y - Jy*rb.x) /Ib;
wbf.y = wbi.y - (Jx*rb.y - Jy*rb.x) /Ib;
}
I agree with provided answers, they are very good.
I just want to point you a small pitfall: if the speed of balls is high, you can just miss the collision, because circles never intersect for given steps.
The solution is to solve the equation on the movement and to find the correct moment of the collision.
Anyway, if you would implement your solution (comparisons on X and Y axes) you'd get the good old ping pong! http://en.wikipedia.org/wiki/Pong
:)
The point at which they collide is on the line between the midpoints of the two circles, and its distance from either midpoint is the radius of that respective circle.