| tags |
|
|
|---|---|---|
| e_maxx_link | circle_line_intersection |
Given the coordinates of the center of a circle and its radius, and the equation of a line, you're required to find the points of intersection.
Instead of solving the system of two equations, we will approach the problem geometrically. This way we get a more accurate solution from the point of view of numerical stability.
We assume without loss of generality that the circle is centered at the origin. If it's not, we translate it there and correct the
Let's start by find the point on the line which is closest to the origin
Second, since the vector
The minus signs are not obvious, but they can be easily verified by substituting
At this stage we can determine the number of intersection points, and even find the solution when there is one or zero points. Indeed, if the distance from
So, we know that the point
Note that the vector
Finally, the equations of the two points of intersection are:
Had we solved the original system of equations using algebraic methods, we would likely get an answer in a different form with a larger error. The geometric method described here is more graphic and more accurate.
As indicated at the outset, we assume that the circle is centered at the origin, and therefore the input to the program is the radius
double r, a, b, c; // given as input
double x0 = -a*c/(a*a+b*b), y0 = -b*c/(a*a+b*b);
if (c*c > r*r*(a*a+b*b)+EPS)
puts ("no points");
else if (abs (c*c - r*r*(a*a+b*b)) < EPS) {
puts ("1 point");
cout << x0 << ' ' << y0 << '\n';
}
else {
double d = r*r - c*c/(a*a+b*b);
double mult = sqrt (d / (a*a+b*b));
double ax, ay, bx, by;
ax = x0 + b * mult;
bx = x0 - b * mult;
ay = y0 - a * mult;
by = y0 + a * mult;
puts ("2 points");
cout << ax << ' ' << ay << '\n' << bx << ' ' << by << '\n';
}