gleicher@CS.CMU.EDU (Michael Gleicher) (11/16/90)
Help! I can't seem to find a good way to do this. I have 2 circles in the plane (x1,y1,r1) and (x2,y2,r2), I know they aren't the same. I would like to know how many intersection points they have (0,1 or 2) and where these intersection points are. I'd like an analytic solution (closed form). I believe that one should exist, but i can't seem to work out the geometry. Any help would be GREATLY appreciated (a reference, a sketch of a proof, an equation, some C code, ...). Thanks, Mike
stam@dgp.toronto.edu (Jos Stam) (11/17/90)
In article <GLEICHER.90Nov16004901@OREO.GRAPHICS.CS.CMU.EDU> gleicher@CS.CMU.EDU (Michael Gleicher) writes: > >Help! I can't seem to find a good way to do this. > >I have 2 circles in the plane (x1,y1,r1) and (x2,y2,r2), I know they aren't >the same. >I would like to know how many intersection points they have (0,1 or 2) and >where these intersection points are. I'd like an analytic solution (closed >form). I believe that one should exist, but i can't seem to work out the >geometry. Any help would be GREATLY appreciated (a reference, a sketch of a >proof, an equation, some C code, ...). > >Thanks, > Mike Your problem can be stated more generally as: find the intersections (common roots) of two algebraic curves: F(x,y) = 0 G(x,y) = 0 If F is of degree n and G is of degree m, then there are nm solutions by Bezout's theorem (counting complex roots and roots "at infinity"). Of course assuming F and G have no common components... There are several methods to solve the above system, one way is to calculate the resultant, which can be given by the determinant of the Sylvester matrix of F and G. Kajiya has applied this stuff to ray-trace parametric patches: J.T. Kajiya, "Ray Tracing Parametric Patches", SIGGRAPH 82 Proceedings, 245-259. In the case of your circles, the resultant will be a polynomial of degree 4 in y (or x). Solving the polynomial will give you y_1 and y_2 (you are only interested in real solutions I assume...). Plugging these values back in the circle equations will give you the corresponding x_1 and x_2. As I'm lazy I will not calculate the resultant for you. good luck. Jos (there is probably a more clever way to do things for your special case...)
ph@miro.Berkeley.EDU (Paul Heckbert) (11/17/90)
In article gleicher@CS.CMU.EDU (Michael Gleicher) writes: >I have 2 circles in the plane (x1,y1,r1) and (x2,y2,r2). >I would like to [find their intersection points]. Hi Mike. A simple approach is to first rotate and translate to a new coordinate system (u,v) where circle 1 is centered at (0,0) and circle 2 is centered at (u2,0), where u2 is the distance between circle centers: u2^2=(x2-x1)^2+(y2-y1)^2. Now we solve u^2+v^2=r1^2, (u-u2)^2+v^2=r2^2. Subtracting these two equations, the u^2 and v^2 terms drop and we're left with a linear equation for u: u = u2/2 + (r1^2-r2^2)/(2*u2). v can then be found as +-sqrt(r1^2-u^2) and you'll get 0, 1, or 2 intersection points when r1^2-u^2 is <0, =0, or >0, respectively. It should be possible to do the transformations without trig. A second, nearly equivalent way to set up the problem is to note that you know the three side lengths of the triangle defined by the two centers and one of the intersection points, so you could use the law of cosines to find the angles and do a little trig to compute the answer. A third approach is to crank through the algebra explicitly from the original equations: (x-x1)^2+(y-y1)^2=r1^2, (x-x2)^2+(y-y2)^2=r2^2. Solve for y in one equation, substitute into the other, expand the squares, move the remaining sqrt term to one side of the equation, yielding sqrt(quadratic in x)=(linear in x), so if you square both sides you'll get a quadratic equation which you can solve for x. Paul Heckbert, Computer Science Dept. 570 Evans Hall, UC Berkeley INTERNET: ph@miro.berkeley.edu Berkeley, CA 94720 UUCP: ucbvax!miro.berkeley.edu!ph ps: we don't need no stinkin' resultants.
gleicher@CS.CMU.EDU (Michael Gleicher) (11/18/90)
Thanks to everyone who responded. I sorta feel silly though. Immediately after posting I found an extremely simple solution. Thats what I get for posting in frustration. My office was covered with picture of intersecting circles, I just needed to look at the diagrams a little differently. I'm sorry if I wasted people's time. The following morning I recieved a few responses, one of which was the very same solution, some others were simple variants. In case you're curious Here's my solution. It's nice since it uses no trig, and didn't require me to solve any non-linear equations. Given and x1,y1,r1,x2,y2,r2 Determine whether or not the circles intersect by comparing the distance between the centers and the sum and differences of the radii. The distance must fall between these two quantities. Assuming they do intersect: let c and d be the centers * mark the intersections, and p be the point where the segment connecting the intersection points meet. * r1/|\r2 let V be the vector c->d / | \ let d be |V| c--p--d let a be the distance from 1 to p, \ | / the distance 2 to p is d-p \|/ let b be the distance from an intersection to p * so p^2 = r1^2 - a^2 = r2^2 - (d-a)^2, a little algrebra leaves: a = (r1^2 - r2^2 + d^2) / (2*d) then b can be computed: b = sqrt(r1^2-a^2) So, p = c + a/d V, and the intersections are: i1 = p + b/d N and i2 = p - b/d N (where N is the normal vector, perpedicular to V) or, in code (with a test driver for an SGI Iris): (BTW: this is C++, though there's nothing magic being used) #include "stdio.h" #include "math.h" typedef float Real; inline Real ABS(const Real x) { return( ((x) >= 0) ? (x) : -(x)); } const Real CI_TOLL = .03; /* don't put intersections closer than this */ int circInters(Real x1, Real y1, Real r1, Real x2, Real y2, Real r2, Real& p1x, Real& p1y, Real& p2x, Real& p2y) { /* the vector between the centers */ Real vx = x2-x1; Real vy = y2-y1; /* its length */ Real d = hypot(vx,vy); if ((ABS(r1-r2) > d) || ( (r1+r2) < d) ) return 0; /* a unit vector along v */ Real uvx = vx / d; Real uvy = vy / d; /* compute the distance along v where the line between the points is */ Real a = (r1*r1 - r2*r2 + d*d) / (2 * d); if (a==0) return 0; /* infinite # of intersections */ /* compute the point A */ Real ax = x1 + uvx*a; Real ay = y1 + uvy*a; /* compute the distance from A to the intersections */ Real ad = sqrt(r1*r1 - a*a); if (ad < CI_TOLL) { p1x = p2x = ax; p1y = p2y = ay; return 1; } /* the unit normal vector */ Real nx = uvy; Real ny = -uvx; /* the points of intersection */ p1x = ax + ad*nx; p1y = ay + ad*ny; p2x = ax - ad*nx; p2y = ay - ad*ny; return 2; } #ifdef TESTDRIVE /* a test driver (for an iris) */ #include "gl.h" main() { Real x1,y1,r1,x2,y2,r2,p1x,p1y,p2x,p2y; int n; keepaspect(1,1); foreground(); winopen("circles"); gconfig(); ortho2(-5,5,-5,5); color(WHITE); clear(); while(x1 != -999) { printf("x1 y1 r1 x2 y2 z2 ?\n"); scanf("%f %f %f %f %f %f",&x1,&y1,&r1,&x2,&y2,&r2); n = circInters(x1,y1,r1,x2,y2,r2,p1x,p1y,p2x,p2y); printf("%d intersections (%5.2f %5.2f) (%5.2f %5.2f)\n", n,p1x,p1y,p2x,p2y); color(WHITE); clear(); color(BLUE); linewidth(3); circ(x1,y1,r1); circ(x2,y2,r2); color(RED); if (n>0) sboxf(p1x-.1,p1y-.1,p1x+.1,p1y+.1); if (n>1) sboxf(p2x-.1,p2y-.1,p2x+.1,p2y+.1); } } #endif ------------------
nujy@vax5.cit.cornell.edu (11/18/90)
The number of intersections is easy. Given the circles (x1,y1) radius r1 and (x2,y2) radius r2 (where r2 > r1), then the distance between the centers is d=sqrt((x2-x1)^2+(y2-y1)^2) and: abs(d-r2) > r1 --> 0 intersections abs(d-r2) = r1 --> 1 intersection (2 degenerate intersections) abs(d-r2) < r1 --> 2 intersections abs(d-r2) is the distance from the center of the smaller circle to the nearest point on the larger circle. Finding the actual intersections is a bit harder. The points must lie on a line (Lp) perpendicular to the line connecting the centers of the circles (Lc). / <-- C2 ___ | + : center of a circle C1 --> _-- -*_ * : intersection / |! ! : perpendicular line (Lp) | +-|!--|-------+ _ |!_/ ^--- Lc That's not too confusing, is it? --___-* | Fig. 1 Furthermore these points are the same distance from Lc, call it h. This proof is left as an exercise for the reader (LEFR). Now all we need to find is the location of the intersection of Lp and Lc (x',y'), and h. Figure 2 shows the geometry of one case. We need to solve for p1. *_ r1 /! --__ r2 / !h --__ +-------------+ Fig. 2 |p1|<---p2--->| |<-----d----->| r1^2 - p1^2 = h^2 (1) Pythagorean Thm. r2^2 - p2^2 = h^2 (2) Ditto p1^2 - p2^2 = r1^2 - r2^2 (3) from 1 & 2 p1 - p2 = (r1^2 - r2^2) / d (4) from 3 and p1+p2=d p1 = (d^2 + r1^2 - r2^2) / 2d (5) add d to 4, isolate x1 Using the parametric equation of a line, and letting t=p1/d: x' = x1 + (x2-x1)*p1 / d, y' = y1 + (y2-y1)*p1 / d. The intersections are at: (x'+x",y'+y"), (x'-x",y'-y"), where x" = h*(y2-y1) / d, y" = h*(x1-x2) / d, is LEFR. The other possible configuration is: *_ !--__ r2 h! r1--__ ---+-------+ |p |<--d-->| However, the above solution also applies here. Isn't that nice. -Chris Chris Schoeneman | "I was neat, clean, shaved, and sober, nujy@vax5.ccs.cornell.edu | and I didn't care who knew it." | - Raymond Chandler