5 votos

Una forma rápida de determinar si se está frente a un determinado par de latas/lon con un rumbo

Busco una forma rápida, preferiblemente sin operaciones trigonométricas (sólo multiplicar, dividir, sumar, cuadrar y restar) para determinar si un punto es visible. Por ejemplo, digamos que estoy frente a 0 grados N, estoy en 51.40,-1.08, la cámara tiene un HFOV de 30 grados y el punto está en 51.20,-1.085 debería devolver VERDADERO, porque el punto estaría frente a mí y está dentro del FOV de 30 grados.

Se requiere que devuelva VERDADERO (falso positivo) en lugar de FALSO dados los casos de borde, de lo contrario los puntos pueden estar ocultos cuando son realmente visibles. Actualmente tengo mi proyecto de realidad aumentada usando atan2 para calcular el ángulo real, pero si puedo afeitar los cálculos de los puntos que definitivamente no son visibles, cada pequeño detalle ayuda. Sólo necesito que sea preciso en distancias de menos de 2 km.

Aquí está mi código para calcular la posición horizontal y vertical. Sólo es preciso en distancias de <5 km, pero la precisión no es crítica de todos modos, ya que esos puntos de ruta no están dibujados. Este proyecto es de código abierto, así que está bien que publique mucho código.

res->est_dist = hypot2(p_viewer->p.lat - p_subj->lat, p_viewer->p.lon - p_subj->lon) * 2000.0f;
// Save precious cycles if outside of visible world.
if(res->est_dist > cliph)
    goto quick_exit;
// Compute the horizontal and vertical angle to the point. 
res->h_angle = angle_dist_deg(RAD2DEG(atan2(p_viewer->p.lon - p_subj->lon, p_viewer->p.lat - p_subj->lat)), p_viewer->yaw);
res->v_angle = RAD2DEG(atan2(p_viewer->p.alt - p_subj->alt, res->est_dist)); // constant scale factor: needs to be adjusted
// Normalize the results to fit in the field of view of the camera.
res->h_angle += p_viewer->hfov / 2;
res->v_angle += p_viewer->vfov / 2;
// Compute projected X and Y position.
res->pos.x = (res->h_angle / p_viewer->hfov) * p_viewer->width;
res->pos.y = (res->v_angle / p_viewer->vfov) * p_viewer->height;

¿Ves esa llamada a atan2 para el h_ángulo? Si pudiera eliminarla diciendo "este punto definitivamente no es visible" estaría bien.

6voto

cjstehno Puntos 131

Dado que sus entradas están en grados, las operaciones trigonométricas son inevitables. Como mínimo hay que tener en cuenta la distorsión de la latitud con respecto a la longitud en todos los puntos que no están en el ecuador.

La aproximación más sencilla (basada en un modelo esférico de la tierra y adecuada sólo para pequeñas distancias) que se me ocurre proyecta los dos puntos (lat1, lon1), (lat2, lon2) a los puntos

(x1, y1) = (lon1 * cos(lat1), lat1) y

(x2, y2) = (lon2 * cos(lat2), lat2)

en el plano euclidiano. (Se trata de un Proyección sinusoidal .) Por lo tanto, el vector de dirección desde el punto de vista (#1) hasta el punto de destino (#2) es

(u, v) = (x2-x1, y2-y1)

con longitud n = Sqrt(u^2 + v^2), por lo que la unidad el vector de dirección es igual a

(u/n, v/n).

Si puedes especificar la dirección a la que te diriges como un vector, en lugar de como un ángulo, puedes evitar algo más de trigonometría. De lo contrario, una dirección t grados al este del norte tiene que ser convertida al vector unitario de dirección

(a, b) = (sin(t), cos(t)).

Por último, la visibilidad se comprueba comparando el producto interior

(u/n, v/n) . (a, b) = (a*u + v*b)/n

al coseno de la mitad del campo de visión horizontal (otro valor trigonométrico, pero se puede precalcular de una vez por todas). El producto interior es menor que este coseno sólo para los puntos invisibles .

Este método requiere calcular un coseno para cada punto base y punto objetivo, así como un seno y un coseno para la dirección de la vista.

Por ejemplo, con un HFOV de 30 grados se puede mirar 15 grados a la derecha y a la izquierda. El coseno de 15 grados es igual a 0,965926. Si usted se encuentra en lon = -1,080 y lat = 51,40 y el punto de destino se encuentra en lon = -1,085 y lat = 51,20, entonces

(x1, y1) = (-1,080 / cos(51,4), 51,4) = (-0,67397, 51,4)

(x2, y2) = (-1,085 / cos(51,2), 51,2) = (-0,67987, 51,2)

(u, v) = (-0,00608, -0,200)

n = 0.200092

(u/n, v/n) = (-0,03036, -0,99954).

El vector de dirección del norte es (sin(0), cos(0)) = (0, 1). Su producto interior con (u/n, v/n) es igual a -0,99954. Como esto es (mucho) menos que 0,965926, el punto es invisible . (Esto, espero, era obvio al principio, porque el punto de destino está al sur -es decir, detrás- del punto de vista). Si se mirara hacia el sur, el vector de dirección sería (sin(180), cos(180)) = (0, -1), el producto interior sería igual a +0,99954, y como esto supera a 0,965926, se concluiría que el punto objetivo está visible.


En algunos casos se puede evitar un montón de trigonometría. Si tienes un único punto base y muchos puntos objetivo cerca, todos los cosenos de las latitudes serán aproximadamente iguales y el coseno de la latitud del punto base. En este caso, sólo hay que calcularlo una vez y utilizar esa aproximación para todos los demás cálculos. De esta manera, no importa cuántos puntos objetivo haya, sólo necesitas cuatro evaluaciones trigonométricas para cada combinación de punto base, HFOV y dirección de la vista. Por supuesto, como se trata de una aproximación (aunque buena), sería una tontería preocuparse por los "casos de borde" (que supongo que son los puntos situados justo en el borde del campo de visión).

4voto

Slayd Puntos 111

Primero: Lo que dijo Whuber sobre que la trigonometría es inevitable.

Ya que estás haciendo realidad aumentada, esta es mi recomendación:

  • Deja de lado las coordenadas lat/lon para todo lo más temprano posible en tu pipeline de datos: convierte a coordenadas cartesianas 3D y usa esas en su lugar, y guárdalas para no tener que rehacerlas todo el tiempo. (¡Ahí está la trigonometría!)
  • A continuación, utilice el método tradicional eliminación de frustraciones para soltar puntos que no son visibles.
    • ¿Utilizando OpenGL? ¿No quieres hacer los cálculos y la contabilidad de un montón de pruebas en el plano? Utilice gluProyecto con la vista del modelo actual y las matrices de proyección y la ventana gráfica. Si la coordenada resultante está dentro del rectángulo de la pantalla (píxeles) y tiene un valor 'z' entre 0 y 1, ¡será visible en la cámara! (De memoria, así que comprueba el manual).

Así es como se ven sus costes computacionales:

  • Cuatro operaciones trigonométricas para convertir de coordenadas esféricas (lat/lon/alt, o phi/theta/rho, dependiendo de si eres geógrafo o matemático) a cartesianas.
    • Sin embargo, ¡sólo hay que hacerlo una vez! (Esto es relevante para esta pregunta también: como ahora sólo trabajas en cartesiano, sólo tienes que añadir el vector y ya está - con exactitud, además, sin factor de confusión).
  • Un montón de multiplicaciones y sumas (tres multiplicaciones vectoriales-matriz), además de tres divisiones y seis comparaciones para la prueba de visibilidad real. ¡Rápido!

Resumiendo, Coordenadas esféricas malas. Cartesianas Buenas.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X