Cálculo de la intersección de dos círculos?

29

Estoy tratando de descubrir cómo derivar matemáticamente los puntos comunes de dos círculos que se cruzan en la superficie de la Tierra dado un centro Lat / Lon y un radio para cada punto.

Por ejemplo, dado:

  • Lat / Lon (37.673442, -90.234036) Radio 107.5 NM
  • Lat / Lon (36.109997, -90.953669) Radio 145 NM

Debería encontrar dos puntos de intersección con uno de ellos (36.948, -088.158).

Sería trivialmente fácil resolver esto en un plano, pero no tengo ninguna experiencia resolviendo ecuaciones en una esfera imperfecta como la superficie de la tierra.

Será
fuente
1
Si todos sus radios van a ser tan pequeños (menos de varios kilómetros), entonces la tierra es esencialmente plana a esta escala y también podría elegir una proyección precisa y simple y realizar los cálculos euclidianos habituales. Asegúrese de calcular la intersección con más de tres decimales: ¡la imprecisión en el tercer decimal es tan grande como cualquiera de sus radios!
whuber
1
Debería haber agregado unidades, esos radios están en NM, por lo que todavía es una pequeña distancia en relación con la superficie de la Tierra, pero más grande que unos pocos km. ¿Cómo afecta esa escala a la distorsión? Estoy tratando de encontrar una solución precisa a menos de <1 nm, por lo que no tiene que ser súper precisa. ¡Gracias!
Will
Todo esto es bueno saberlo, ya que muestra que puedes usar un modelo esférico de la tierra: los modelos elipsoidales más complicados son innecesarios.
whuber
@whuber ¿Esto implica que el problema podría reformularse como: encontrar la intersección de 3 esferas donde una de las esferas es la tierra y las otras dos están centradas en los puntos con sus respectivos radios?
Kirk Kuykendall
@Kirk Sí, esa es la forma de hacerlo, suponiendo un modelo esférico de la superficie de la tierra. Después de algunos cálculos preliminares que reducen esto a un caso especial del problema de trilateración en 3D. (Los cálculos son necesarios para convertir la distancia a lo largo de arcos esféricos en distancias a lo largo de los acordes esféricos, que se convierten en los radios de las dos esferas más pequeñas.)
whuber

Respuestas:

21

No es mucho más difícil en la esfera que en el avión, una vez que reconoce que

  1. Los puntos en cuestión son las intersecciones mutuas de tres esferas: una esfera centrada debajo de la ubicación x1 (en la superficie de la tierra) de un radio dado, una esfera centrada debajo de la ubicación x2 (en la superficie de la tierra) de un radio dado, y la tierra misma , que es una esfera centrada en O = (0,0,0) de un radio dado.

  2. La intersección de cada una de las dos primeras esferas con la superficie de la tierra es un círculo, que define dos planos. Por lo tanto, las intersecciones mutuas de las tres esferas se encuentran en la intersección de esos dos planos: una línea .

En consecuencia, el problema se reduce a la intersección de una línea con una esfera, lo cual es fácil.


Aquí están los detalles. Las entradas son los puntos P1 = (lat1, lon1) y P2 = (lat2, lon2) en la superficie de la tierra, considerados como una esfera, y dos radios correspondientes r1 y r2.

  1. Convierta (lat, lon) en coordenadas geocéntricas (x, y, z). Como de costumbre, porque podemos elegir unidades de medida en las cuales la tierra tiene un radio unitario,

    x = cos(lon) cos(lat)
    y = sin(lon) cos(lat)
    z = sin(lat).
    

    En el ejemplo, P1 = (-90.234036 grados, 37.673442 grados) tiene coordenadas geocéntricas x1 = (-0.00323306, -0.7915, 0.61116) y P2 = (-90.953669 grados, 36.109997 grados) tiene coordenadas geocéntricas x2 = (-0.0134464, -0.807775 , 0.589337).

  2. Convierta los radios r1 y r2 (que se miden a lo largo de la esfera) en ángulos a lo largo de la esfera. Por definición, una milla náutica (NM) es 1/60 grados de arco (que es pi / 180 * 1/60 = 0.0002908888 radianes). Por lo tanto, como ángulos,

    r1 = 107.5 / 60 Degree = 0.0312705 radian
    r2 = 145 / 60 Degree = 0.0421788 radian
    
  3. El círculo geodésico de radio r1 alrededor de x1 es la intersección de la superficie de la tierra con una esfera euclidiana de radio sin (r1) centrada en cos (r1) * x1.

  4. El plano determinado por la intersección de la esfera de radio sin (r1) alrededor de cos (r1) * x1 y la superficie de la tierra es perpendicular a x1 y pasa por el punto cos (r1) x1, de donde su ecuación es x.x1 = cos (r1) (el "." representa el producto de punto habitual ); igualmente para el otro plano. Habrá un punto único x0 en la intersección de esos dos planos que es una combinación lineal de x1 y x2. Escribiendo x0 = a x1 + b * x2 las dos ecuaciones planas son

    cos(r1) = x.x1 = (a*x1 + b*x2).x1 = a + b*(x2.x1)
    cos(r2) = x.x2 = (a*x1 + b*x2).x2 = a*(x1.x2) + b
    

    Usando el hecho de que x2.x1 = x1.x2, que escribiré como q, la solución (si existe) viene dada por

    a = (cos(r1) - cos(r2)*q) / (1 - q^2),
    b = (cos(r2) - cos(r1)*q) / (1 - q^2).
    

    En el ejemplo en ejecución, calculo a = 0.973503 yb = 0.0260194.

    Evidentemente, necesitamos q ^ 2! = 1. Esto significa que x1 y x2 no pueden ser ni el mismo punto ni los puntos antipodales.

  5. Ahora todos los demás puntos en la línea de intersección de los dos planos difieren de x0 por algún múltiplo de un vector n que es mutuamente perpendicular a ambos planos. El producto cruzado

    n = x1~Cross~x2
    

    realiza el trabajo siempre que n no sea cero: una vez más, esto significa que x1 y x2 no son ni coincidentes ni diametralmente opuestas. (Debemos tener cuidado de calcular el producto cruzado con alta precisión, ya que involucra restas con mucha cancelación cuando x1 y x2 están cerca una de la otra). En el ejemplo, n = (0.0272194, -0.00631254, -0.00803124) .

  6. Por lo tanto, buscamos hasta dos puntos de la forma x0 + t * n que se encuentran en la superficie de la tierra: es decir, su longitud es igual a 1. De manera equivalente, su longitud al cuadrado es 1:

    1 = squared length = (x0 + t*n).(x0 + t*n) = x0.x0 + 2t*x0.n + t^2*n.n = x0.x0 + t^2*n.n
    

    El término con x0.n desaparece porque x0 (que es una combinación lineal de x1 y x2) es perpendicular a n. Las dos soluciones son fácilmente

    t = sqrt((1 - x0.x0)/n.n)
    

    y es negativo Una vez más se requiere alta precisión, porque cuando x1 y x2 están cerca, x0.x0 está muy cerca de 1, lo que lleva a una pérdida de precisión de coma flotante. En el ejemplo, t = 1.07509 o t = -1.07509. Los dos puntos de intersección, por lo tanto, son iguales

    x0 + t*n = (0.0257661, -0.798332, 0.601666)
    x0 - t*n = (-0.0327606, -0.784759, 0.618935)
    
  7. Finalmente, podemos convertir estas soluciones de nuevo a (lat, lon) convirtiendo geocéntrico (x, y, z) en coordenadas geográficas:

    lon = ArcTan(x,y)
    lat = ArcTan(Sqrt[x^2+y^2], z)
    

    Para la longitud, use los valores de retorno de arcotangente generalizados en el rango de -180 a 180 grados (en aplicaciones informáticas, esta función toma tanto x como y argumentos como argumentos en lugar de solo la relación y / x; a veces se le llama "ATan2").

    Obtengo las dos soluciones (-88.151426, 36.989311) y (-92.390485, 38.238380), que se muestran en la figura como puntos amarillos.

Figura 3D

Los ejes muestran las coordenadas geocéntricas (x, y, z). El parche gris es la porción de la superficie de la tierra de -95 a -87 grados de longitud, 33 a 40 grados de latitud (marcado con una retícula de un grado). La superficie de la tierra se ha hecho parcialmente transparente para mostrar las tres esferas. La exactitud de las soluciones calculadas es evidente por cómo los puntos amarillos se sientan en las intersecciones de las esferas.

whuber
fuente
Bill, esto es asombroso. Una aclaración que podría agregar, basada en alguien que estaba tratando de implementarlo. En el paso 2 no das explícitamente la conversión de grados a radianes.
Jersey Andy
@Jersey Gracias por su edición sugerida. Lo cambié un poco para evitar la redundancia y mantener las fórmulas lo más claras posible. Después de leer el hilo al que se refiere, también inserté un enlace para explicar el producto de puntos.
whuber
8

El caso elipsoidal :

Este problema es una generalización de encontrar límites marítimos definidos como "líneas medianas" y hay una extensa literatura sobre este tema. Mi solución a este problema es aprovechar la proyección acimutal equidistante:

  1. Adivina en el punto de intersección
  2. Proyecte los dos puntos base utilizando este punto de intersección adivinado como el centro de una proyección acimutal equidistante,
  3. Resuelva el problema de intersección en el espacio proyectado 2d.
  4. Si el nuevo punto de intersección está demasiado lejos del anterior, vuelva al paso 2.

Este algoritmo converge cuadráticamente y produce una solución precisa en un elipsoide. (Se requiere precisión en el caso de los límites marítimos, ya que determina los derechos de pesca, petróleo y minerales).

Las fórmulas se dan en la Sección 14 de Geodesics en un elipsoide de revolución . La proyección azimutal equidistante elipsoidal es proporcionada por GeographicLib . Una versión de MATLAB está disponible en las proyecciones geodésicas para un elipsoide .

cffk
fuente
+1 Ese es un artículo increíble: tu modesta descripción aquí no le hace justicia.
whuber
Consulte también mi artículo más breve sobre geodésicos "Algoritmos para geodésicos" dx.doi.org/10.1007/s00190-012-0578-z (¡descarga gratuita!) Más erratas y adiciones para estos documentos Geographiclib.sf.net/geod-addenda.html
cffk
1

Aquí hay un código R para hacer esto:

p1 <- cbind(-90.234036, 37.673442) 
p2 <- cbind(-90.953669, 36.109997 )

library(geosphere)
steps <- seq(0, 360, 0.1)
c1 <- destPoint(p1, steps, 107.5 * 1852)
c2 <- destPoint(p2, steps, 145 * 1852)

library(raster)
s1 <- spLines(c1)
s2 <- spLines(c2)

i <- intersect(s1, s2)
coordinates(i)

#        x        y
# -92.38241 38.24267
# -88.15830 36.98740

s <- bind(s1, s2)
crs(s) <- "+proj=longlat +datum=WGS84"
plot(s)
points(i, col='red', pch=20, cex=2)
Robert Hijmans
fuente
1

Siguiendo la respuesta de @ whuber , aquí hay un código Java que es útil por dos razones:

  • destaca un error con respecto a ArcTan (para Java y quizás otros idiomas)
  • maneja los posibles casos límite, incluido uno no mencionado en la respuesta de @ whuber.

No está optimizado o completo (he omitido clases obvias como Point), pero debería ser el truco.

public static List<Point> intersection(EarthSurfaceCircle c1, EarthSurfaceCircle c2) {

    List<Point> intersections = new ArrayList<Point>();

    // project to (x,y,z) with unit radius
    UnitVector x1 = UnitVector.toPlanar(c1.lat, c1.lon);
    UnitVector x2 = UnitVector.toPlanar(c2.lat, c2.lon);

    // convert radii to radians:
    double r1 = c1.radius / RadiusEarth;
    double r2 = c2.radius / RadiusEarth;

    // compute the unique point x0
    double q = UnitVector.dot(x1, x2);
    double q2 = q * q;
    if (q2 == 1) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }
    double a = (Math.cos(r1) - q * Math.cos(r2)) / (1 - q2);
    double b = (Math.cos(r2) - q * Math.cos(r1)) / (1 - q2);
    UnitVector x0 = UnitVector.add(UnitVector.scale(x1, a), UnitVector.scale(x2, b));

    // we only have a solution if x0 is within the sphere - if not,
    // the circles are not touching.
    double x02 = UnitVector.dot(x0, x0);
    if (x02 > 1) {
        // no solution: circles not touching
        return intersections;
    }

    // get the normal vector:
    UnitVector n = UnitVector.cross(x1, x2);
    double n2 = UnitVector.dot(n, n);
    if (n2 == 0) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }

    // find intersections:
    double t = Math.sqrt((1 - UnitVector.dot(x0, x0)) / n2);
    intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, t))));
    if (t > 0) {
        // there's only multiple solutions if t > 0
        intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, -t))));
    }
    return intersections;
}

También, lo más importante, tenga en cuenta el uso de atan2: es lo contrario de lo que esperaría de la respuesta de @ whuber (no sé por qué, pero funciona):

    public static Point toPolar(UnitVector a) {
        return new Point(
                Math.toDegrees(Math.atan2(a.z, Math.sqrt(a.x * a.x + a.y * a.y))),
                Math.toDegrees(Math.atan2(a.y, a.x)));          
    }
ianhoolihan
fuente
0

Código 'R' de trabajo para @wuhber respuesta.

P1 <- c(37.673442, -90.234036)
P2 <- c(36.109997, -90.953669) 

#1 NM nautical-mile is 1852 meters
R1 <- 107.5
R2 <- 145

x1 <- c(
  cos(deg2rad(P1[2])) * cos(deg2rad(P1[1])),  
  sin(deg2rad(P1[2])) * cos(deg2rad(P1[1])),
  sin(deg2rad(P1[1]))
);

x2 <- c(
  cos(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[1]))
);

r1 = R1 * (pi/180) * (1/60)
r2 = R2 * (pi/180) * (1/60)

q = dot(x1,x2)
a = (cos(r1) - cos(r2) * q) / (1 - q^2)
b = (cos(r2) - cos(r1) * q)/ (1 - q^2)

n <- cross(x1,x2)

x0 = a*x1 + b*x2


t = sqrt((1 - dot(x0, x0))/dot(n,n))

point1 = x0 + (t * n)
point2 = x0 - (t * n)

lat1 = rad2deg(atan2(point1[2] ,point1[1]))
lon1= rad2deg(asin(point1[3]))
paste(lat1, lon1, sep=",")

lat2 = rad2deg(atan2(point2[2] ,point2[1]))
lon2 = rad2deg(asin(point2[3]))
paste(lat2, lon2, sep=",")
Sri
fuente
-1

Si uno de círculo es el Nortstar, entonces hay una manera más fácil con la esfera de la unidad.

Puede medir su latitud con Nortstar. Entonces tienes una posición relativa en esta esfera. v1 (0, sin (la), cos (la)) Conoces la posición (ángulo) de la otra estrella (star2), de almanaque. v2 (sin (lo2) * cos (la2), sin (la2), cos (lo2) * cos (la2)) Sus vectores. De la ecuación de esfera.

lo2 es la longitud relativa. Es desconocido .

El ángulo entre usted y star2, también puede medirlo, (m) Y ya sabe, el producto interno del vector de dos unidades es cos (ángulo) de entre. cos (m) = punto (v1, v2) puedes calcular ahora la longitud relativa (lo2). lo2 = acos ((cos (m) -sin (la) * sin (la2)) / (cos (la) * cos (la2)))

Después de todo, agrega la longitud real de star2 a lo2. (o sub, depende de su lado oeste de usted, o este.) lo2 ahora es su longitud.

Perdón por mi inglés, nunca aprendo este idioma.


2 cosas: Northstar significa estrella polar.

Otro. Debido a que el ángulo medido con respecto al horizonte relativamente, siempre se necesita una corrección de 90 ángulos. También es válido para el ángulo m.

ps: ángulo real significa: posición de la estrella - corrección de tiempo.

docwho
fuente
No es evidente cómo esto responde la pregunta.
whuber