Intersección círculo-recta
Dadas las coordenadas del centro de un círculo y su radio, y la ecuación de una recta, se requiere encontrar los puntos de intersección.
Solución
En lugar de resolver el sistema de dos ecuaciones, abordaremos el problema de forma geométrica. De este modo obtenemos una solución más precisa desde el punto de vista de la estabilidad numérica.
Asumimos sin pérdida de generalidad que el círculo está centrado en el origen. Si no lo está, lo trasladamos allí y corregimos la constante en la ecuación de la recta. Así tenemos un círculo centrado en de radio y una recta con ecuación .
Empecemos por encontrar el punto de la recta más cercano al origen . Primero, tiene que estar a una distancia
Segundo, como el vector es perpendicular a la recta, las coordenadas del punto deben ser proporcionales a las coordenadas de este vector. Como conocemos la distancia del punto al origen, solo hay que escalar el vector a esta longitud, y obtendremos:
Los signos menos no son evidentes, pero se pueden verificar fácilmente sustituyendo e en la ecuación de la recta.
En esta etapa podemos determinar el número de puntos de intersección, e incluso encontrar la solución cuando hay uno o cero puntos. En efecto, si la distancia de al origen es mayor que el radio , la respuesta es cero puntos. Si , la respuesta es un punto . Si , hay dos puntos de intersección, y ahora hay que encontrar sus coordenadas.
Así, sabemos que el punto está dentro del círculo. Los dos puntos de intersección, y , deben pertenecer a la recta y deben estar a la misma distancia de , y esta distancia es fácil de encontrar:
Nótese que el vector es colineal a la recta, y así podemos encontrar los puntos en cuestión sumando y restando el vector , escalado a la longitud , al punto .
Finalmente, las ecuaciones de los dos puntos de intersección son:
Si hubiéramos resuelto el sistema original de ecuaciones usando métodos algebraicos, probablemente obtendríamos una respuesta de otra forma con un error mayor. El método geométrico descrito aquí es más gráfico y más preciso.
Implementación
Como se indicó al comienzo, asumimos que el círculo está centrado en el origen, y por tanto la entrada al programa es el radio del círculo y los parámetros , y de la ecuación de la recta.
double r, a, b, c; // dados como entrada
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';
}