Skip to main content
GameDev.net gamedev.net
🔒 Locked

Intersection of two spheres and a plane

Started by Aken H Bosch Mar 11, 2007 at 5:24 PM 4 replies 4k views
Original Post
Aken H Bosch
Aken H Bosch
I am trying to find the intersection (x, y, z) of two spheres and a plane to use for a collision detection routine in my game. Help would be appreciated. Here are the specifics: One of the spheres is x2 + y2 + z2 = 1 The second sphere is (x - xt)2 + (y - yt)2 + (z - zt)2 = r2 The plane is ax + by + cz = 0 Additional constraints that do not directly affect (x, y, z) but place limits on the constants used to calculate it: (xt, yt, zt) lies on the sphere defined in the first equation. (a, b, c) lies on the sphere defined in the first equation. NOTE: (a, b, c) is calculated as an initial point satisfying the first equation crossed with the velocity vector, which is perpendicular to the first vector. See the note at the end of this post. r > 0, r <= 2 I have tried using various methods, including parameterization with vectors in terms of cosine and sine, but have not been able to get a working solution. If it helps, I have found the plane on which the intersection of the two spheres lies to be defined by the equation xtx + yty + ztz = 1 - (r2) / 2 An analytic solution is the only way that this will work. There should be 0, 1, or 2 solutions for any values satisfying the conditions. NOTE: I have tried parameterizing the vector of the point of intersection x as Icos(theta) + vsin(theta) / |v|, where I is the initial point and v is the initial velocity. In the end, what I need to know is the angle measure from the initial point to the point(s) of intersection, in the direction of v. This, however, gave me a quadratic-ish equation (I could use the quadratic formula to solve for cos2(theta), but it didn't work in-game, probably because it was a huge thing to work out and to copy into code and I could have made errors doing either.
Signature go here.
InetRoadkill
InetRoadkill
Maybe you could draw a picture? I'm not sure what you mean by the plane lying on the sphere of the first equation which is a sphere centered at the origin. The plane equation given will also pass thru the origin. Thus the plane simply bisects rather than lies on the first sphere equation using the normal (a,b,c).

Did you mean ax + by + cz = 1 instead?
Zipster
Zipster
It seems to me like you already have most of this problem solved. If you have the equation of the plane the circle is on, then intersect that with the plane ax + by + cz = 0 to get a line. Then you can intersect the line and the circle to get your intersection points.

This problem also lends itself naturally to a 2D approach. You've already calculated the circle plane, and you have the intersection plane. It's possible to then work entirely in the 2D sub-space defined by the two vectors u = (a, b, c) and v = (xt, yt, zt). In this subspace, the circle appears as a line segment (finite length), and the intersection plane appears as a line (infinite length). All we do is see if the line intersects the line segment. One major simplification you should make is if dot(u,v) < 0, let u = -u to make things easier later on. The radius of the circle is sqrt(r2 - r4/4), which is half the length of the line segment, which is now perpendicular and centered on the v-vector at a distance of 1 - r2/2 from the origin. The line segment will intersect the line if the angle between (a, b, c) and (xt, yt, zt) is large enough. If we let dot(u,v) be the dot product between these vectors, and let t = sqrt(1 - (1 - dot(u,v))2) * (1 - r2/2) / (1 - dot(u,v)), then there's an intersection if t2 ≤ r2 - r4/4. When the intersection plane and the circle plane are parallel, then dot(u,v) is 1, and 1 - dot(u,v) is 0, which gives a divide by 0 and t approaches ∞, which is clearly not less than some other quantity. In the case that the two planes are perpendicular then dot(u,v) will be 0, 1 - dot(u,v) will be 1, and t will be 0 which is always less than or equal to the right-hand quantity (hence a guaranteed intersection).

From this point we can geometrically construct the intersection points. Take the cross product of the two basis vectors and normalize it, cross(u,v)/|cross(u,v)|, and give it a name like n. Then take the cross product between this vector and the v-vector, cross(n,v)/|cross(n,v)|, and give it a name like s. Here comes some heavy vector math, required to go from the sub-space back to full 3D. The intersection points you're looking for will be:

pi = (1 - r2/2)*(xt, yt, zt) + t*s +/- sqrt(r2 - r4/4 - t2)*n

The +/- of the square-root gives you two solutions. If t2 = r2 - r4/4, then there is only one solution, as expected. It seems long and complicated, but it's really only a few cross products and square roots.

Hopefully I didn't make any mistakes either, I tend to lose my train of thought sometimes when dealing with a lot of math [smile]
nagromo
nagromo
First, find the intersection between your plane ax+by+cz=0 and the sphere-sphere plane xtx + yty + ztz = 1 - (r2) / 2

n1 = [a b c]
n2 = normalize([xt yt zt])

a = n1 cross n2

If a is 0, the planes are parallel, so there is no solution.

Now find a point p0 that is on both planes by saying x0 = 0 and solving the plane equations as a system. (You'll have to code a special case using y0 = 0 or z0 = 0 for when that doesn't work.)

Now you have an equation for a line the solution must be on:

s = p0 + t*a

where t is a scalar value.

Now just use a line-sphere intersection with the unit sphere to find the solutions.

sx = p0x + ax*t
sy = p0y + ay*t
sz = p0z + az*t
x2 + y2 + z2 = 1

Substitute and solve the resulting quadratic.
(p0x + ax*t)2 + (p0y + ay*t)2 + (p0z + az*t)2 = 1

(ax2+ay2+az2)t2 + 2(p0xax + p0yay + p0zaz)t + (p0x + p0y + p0z) - 1 = 0

Just use the quadratic formula on this to get your answer.

[edit] Oops, I was ninja'd by an hour. That's what I get for starting a post before dinner then doing laundry afterwards. Also, Zipster's solution doesn't require a corner case, so it's a cleaner solution.
Zipster
Zipster
Actually I think I might have made a mistake in the equation for t, and it should be t = dot(u,v) * (1 - r2/2) / sqrt(1 - dot(u,v)2). The idea is that you're not interested in the angle between u and v, but the angle between perp(u) and v. So if the dot product of two normalized vectors is cos(θ), then if you use the perpendicular of one of those vectors instead it's cos(θ +/- PI/2) (+/- depending on which produces an absolute angle of less than PI/2), which gives us sin(θ), or sqrt(1 - dot(u,v)2). I was instead just using 1 - dot(u,v).
Aken H Bosch
Aken H Bosch
Thanks for the help, although I did sort of resolve this on my own. What I did was I converted the ax + by + cz = 0 plane into parametric form, where one of the vectors was (a, b, c) x (1, 0, 0) and the other was that product x(a, b, c). I then used x, y, and z (which were then in terms of two parametric variables) in the equation for the plane of intersection of the two spheres. Then I solved the parametric equation for one of the parameters in terms of the other one. This gave me a linear equation: a vector plus a vector times a scalar. Then, I plugged this into my amazing Line-Sphere Intersector Of Science, to get the place where this line intersected the unit sphere. Now, it works (I think).

As for InetRoadKill's question, I said (a, b, c) lies on the sphere, not "the plane ax + by + cz = 0 lies on the sphere." The expression ax + by + cz is indeed equal to 0, not 1.





If you would like to know the Line-Sphere Intersector Of ScienceTM algorithm, it is as follows:

For a sphere (x - x0)2 + (y - y0)2 + (z - z0)2 = r2, and a line defined as x = x0 + tv,

let o be the vector from the origin to center of the circle, minus x0, and
let s be the unit vector parallel to v.

Then the value of t that satisfies the line equation is s dot o +or- sqrt((s dot o)2 + r2 - |o|2),

and the value of x can be found by evaluating the line equation with the calculated value of t.
Signature go here.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.