Cómo encontrar el punto de intersección entre un círculo y una línea recta

La pregunta originalmente pedía una solución específica para MATLAB, pero en realidad es más interesante que solo una pregunta de programación limitada, por lo que la he modificado para que sea más general.

Esto se debe a que la forma más fácil de resolver este problema es resolverlo algebraicamente, ¡y luego simplemente conectar la fórmula resultante en MATLAB tal como está!

Abordamos el problema usando vectores .

Primero debe describir la línea como una ecuación vectorial:

[matemáticas] \ vec {x} = \ vec {d} + \ lambda \ hat {n} [/ matemáticas]

Donde [math] \ vec {d} [/ math] es el vector de posición de un punto en la línea, [math] \ hat {n} [/ math] es un vector unitario en la dirección de la línea, y [math ] \ lambda [/ math] es un parámetro que se ‘desliza’ hacia arriba y hacia abajo en la línea.

Nuestro objetivo es encontrar los valores de [math] \ lambda [/ math] que corresponden a la intersección con el círculo, y luego podemos conectar este valor a la ecuación anterior para encontrar la posición.

También necesitamos definir una esfera en notación vectorial:

[matemáticas] \ izquierda (\ vec {x} – \ vec {c} \ derecha) ^ 2 = r ^ 2 [/ matemáticas]

Donde [math] \ vec {c} [/ math] es el vector de posición del centro del círculo, y [math] r [/ math] es el radio.

En la intersección de estos dos sistemas, [matemática] \ vec {x} _ {esfera} = \ vec {x} _ {línea} [/ matemática] – entonces simplemente conectamos la ecuación 1 en la ecuación 2, para obtener:

[matemáticas] \ left (\ vec {d} + \ lambda \ hat {n} – \ vec {c} \ right) ^ 2 = r ^ 2 [/ math]

Expande los corchetes:

[matemáticas] d ^ 2 + \ lambda ^ 2 + c ^ 2 + 2 \ lambda \ vec {d} \ cdot \ hat {n} – 2 \ lambda \ vec {c} \ cdot \ hat {n} – 2 \ vec {d} \ cdot \ vec {c} = r ^ 2 [/ math]

([matemática] | \ hat {n} | = 1 [/ matemática], por lo que no incluimos [matemática] n ^ 2 [/ matemática])

[math] \ lambda [/ math] es el artículo que nos interesa, entonces:

[matemáticas] \ lambda ^ 2 + 2 \ lambda \ left (\ vec {d} – \ vec {c} \ right) \ cdot \ hat {n} + \ left (d ^ 2 + c ^ 2 – r ^ 2 – 2 \ vec {d} \ cdot \ vec {c} \ right) = 0 [/ math]

Esto es ahora un simple cuadrático en [math] \ lambda [/ math] – recordando que la fórmula cuadrática [math] ax ^ 2 + bx + c = 0 [/ math] tiene soluciones de la forma:

[matemáticas] x = \ frac {-b \ pm \ sqrt {b ^ 2 – 4 ac}} {2a} [/ matemáticas] [1]

Por lo tanto:

[matemáticas] \ lambda = \ left (\ vec {c} – \ vec {d} \ right) \ cdot \ hat {n} \ pm \ sqrt {\ left [\ left (\ vec {c} – \ vec { d} \ right) \ cdot \ hat {n} \ right] ^ 2 – \ left (d ^ 2 + c ^ 2 – r ^ 2 – 2 \ vec {d} \ cdot \ vec {c} \ right)} [/matemáticas]

Luego podemos volver a conectar esto en la ecuación uno para obtener nuestras posibles soluciones:

[matemáticas] \ boxed {\ vec {x} _ \ pm = \ vec {d} + \ Bigg (\ left (\ vec {c} – \ vec {d} \ right) \ cdot \ hat {n} \ pm \ sqrt {\ left [\ left (\ vec {c} – \ vec {d} \ right) \ cdot \ hat {n} \ right] ^ 2 – \ left (d ^ 2 + c ^ 2 – r ^ 2 – 2 \ vec {d} \ cdot \ vec {c} \ right)} \ Bigg) \ hat {n}} [/ math]

Esta es la fórmula para calcular la intersección entre una línea y una esfera en dimensiones arbitrarias [math] \ mathbb {R} ^ n [/ math]


Entonces es simple codificar esto en MATLAB (como se hizo originalmente en la pregunta)

% define la línea
d = [2 0 0];
n = [0 1 0];

% define el círculo
c = [0 0 0];
r = 5;

%% Asegúrese de que n sea un vector unitario
n = n./sqrt(dot(n,n));

%% Calcular lambda
prefactor = punto (c – d, n);

squareRoot = sqrt (prefactor ^ 2 – (punto (d, d) + punto (c, c) – r ^ 2 – 2 * punto (d, c)));

lambdaPlus = prefactor + squareRoot;
lambdaMinus = prefactor – squareRoot;

% Verificar si las soluciones son reales
si imag (lambdaPlus) ~ = 0
disp (‘No hay soluciones disponibles’)
más

%% Si las soluciones son reales, salida
xPlus = d + lambdaPlus * n;
xMinus = d + lambdaMinus * n;

disp (‘Solución positiva’); disp (xPlus);
disp (‘Solución negativa’); disp (xMinus);
fin

Hice un uso liberal del soporte incorporado de MATLAB para vectores (de hecho, MATLAB es prácticamente el lenguaje perfecto para esto: ¡está diseñado para hacer que el álgebra de vectores y matrices sea lo más fácil posible! [2])

Usando los valores ficticios de [math] \ vec {c} [/ math], [math] \ vec {d} [/ math], [math] \ hat {n} [/ math] y [math] r [/ matemáticas] que ingresé anteriormente, la salida del script es:

Solución positiva
2.0000 4.5826 0

Solución negativa
2.0000 -4.5826 0

Y, de hecho, si conectamos esto a WolframAlpha nos da el mismo resultado: Computational Knowledge Engine

La verificación “imaginaria” se produce porque si la línea y la esfera nunca se cruzan (al menos en el espacio real), entonces la raíz cuadrada será de un número negativo, por lo que simplemente estamos eliminando esta condición.

Este método se generaliza a dimensiones arbitrarias: funciona si [math] \ vec {c} [/ math] etc. son vectores 2D que describen un círculo, y funciona en 4D para hiperesuperficies.

Notas al pie

[1] Respuesta de Jack Fraser a ¿Cómo resuelve la ecuación [matemáticas] y ^ 2-4y + 4 = 0 [/ matemáticas] usando la fórmula cuadrática?

[2] ¿Por qué MATLAB utiliza el orden principal de la columna en lugar del orden principal de la fila como prevalente en C?