Share via


Este artículo proviene de un motor de traducción automática.

Tocar y listo

Coordenadas esféricas en Windows Phone

Charles Petzold

Descargar el ejemplo de código

Charles PetzoldDesde que conocí con el sensor de movimiento en Windows Phone 7.1, he sabido exactamente lo que quería hacer con él: resucitar algunos C# código de Astronomía posicional que escribí hace unos cinco años y alambre con lógica de sensor de movimiento en un programa de Windows Phone.Dicho programa me permitiera apuntar el teléfono en un lugar en el cielo de la noche para mostrar los planetas y las constelaciones situadas allí.

Ese programa, con el ridículo nombre AstroPhone — viene en la próxima entrega de esta columna.Mientras tanto, algunas bases conceptuales, matemáticas y programación es necesario.

Como he debatido en columnas anteriores, el sensor de movimiento consolida la entrada de la brújula, acelerómetro, giroscopio y GPS y calcula (entre otras cosas) una matriz de rotación 3D que describe la orientación del teléfono en el espacio.Es conveniente aplicar esta matriz a un vector 3D con relación al sistema de coordenadas del teléfono.Este vector transformado apunta a una ubicación en la esfera celeste conceptual.Un lugar en este ámbito es una coordenada horizontal, que consiste en una altitud — un ángulo por encima o por debajo del horizonte del espectador — y un azimut, que es básicamente una brújula dirección.

Coordenadas horizontales son análogas a las coordenadas geográficas familiares que identifican una posición en la superficie de la tierra.La altitud por encima o por debajo del horizonte del espectador es análoga a una latitud por encima o por debajo del Ecuador terrestre.El azimut que indica una dirección brújula alrededor de horizonte del espectador es análogo a la longitud en el Ecuador terrestre.Como verás, todos los tipos de coordenadas esféricas son fundamentalmente los mismos, diferentes más crucial por el plano que separa el hemisferio superior de la inferior.

Aplanamiento de la esfera

En la columna del mes pasado (msdn.microsoft.com/magazine/jj553520), he demostrado cómo usar coordenadas horizontales para explorar grandes fotografías y otras imágenes cambiando la orientación del teléfono en el espacio.Sin embargo, ese programa "engañado" un poco por hacer caso omiso de la verdadera naturaleza de las coordenadas esféricas.Se negó a reconocer el hecho de que círculos de latitud reducirse cada vez más hacia la parte superior e inferior de la esfera celeste, y en consecuencia, grados de azimut convertirse en cada vez más comprimidos.

Un programa que le permite ver el cielo nocturno en una simulada simplemente no puede tomar los atajos.Debe encontrar una forma algorítmica para asignar un área de la esfera celeste a la pantalla plana del teléfono.Por supuesto, el aplanamiento de la esfera ha sido un problema encontrado por cartógrafos durante siglos.No puede hacerse sin distorsión, pero el objetivo es minimizar las distorsiones.

Figura 1 muestra una esfera decorada con líneas de altitud y acimut cada 15 °.Desde un punto de vista en el centro de la parte interior de la esfera, el punto rojo representa un punto que usted está viendo o apuntando con su teléfono.La altitud de este punto en particular es de 25 °.El acimut depende donde empezar a contar y en qué dirección.

A Point (in Red) on a Celestial Sphere
Figura 1 punto (en rojo) en una esfera celeste

Vamos a llamar a este punto el "centro de la vista" porque es el punto que se asignarán al centro de la pantalla del teléfono.¿Qué líneas sobre la esfera corresponden a los bordes de la pantalla?

Es tentador suponer que los bordes de la pantalla del teléfono se corresponden a líneas de altitud y acimut.Pero que sólo parece razonable en lugares cerca del horizonte.El concepto empieza a romper el centro de la vista obtiene más allá del horizonte, y derrumba por completo cuando está viendo hacia arriba o hacia abajo en los polos.

En cambio, vamos a construir ortogonales "grandes círculos" en el centro de la vista, como se muestra en la figura 2.

Orthogonal Great Circles Crossing the View Center
Figura 2 grandes círculos ortogonales cruzando el centro de la vista

Grandes círculos son un concepto importante en la geometría esférica.Un gran círculo es un círculo de dos dimensiones en el espacio 3D, compartir el mismo radio y centro como la propia esfera.Grandes círculos de la esfera son análogas a las líneas rectas en un plano porque representan la distancia más corta entre dos puntos.Líneas de acimut (y longitud) son grandes círculos.Líneas de latitud (y altitud) son no; por el contrario son "pequeños círculos," excepto el círculo que divide la esfera en dos — el horizonte (o Ecuador).

El gran círculo rojo en figura 2 pasa por los polos y es simplemente una línea de azimut.El gran círculo azul cruza el horizonte en azimuts 90 ° desde el azimut del centro de la vista.

Un rectángulo alrededor de ese centro de vista se asignará a la pantalla del teléfono.Conceptualmente, este rectángulo puede ser una cuadrícula de grandes círculos.Vamos a construir dos más grandes círculos en azul que cruzan el horizonte en el mismo punto que el primero.Y vamos a construir dos más grandes círculos rojos que también comparten dos puntos con el primero de ellos.El resultado se muestra en figura 3.Los puntos compartidos de los grandes círculos rojos tienen el mismo acimut como el centro de la vista (o el acimut y 180 °), pero la altitud es compensada por 90 °.

Additional Great Circles to Create a Rectangular Area
Figura 3 adicionales grandes círculos para crear un área Rectangular

Los grandes círculos adicionales definen los bordes de un rectángulo que corresponde a la pantalla de modo de retrato del teléfono, con una anchura de unos 19 ° de arco y una altura de 32 ° de arco.Si usted asume que la pantalla del teléfono es aproximadamente 2 pulgadas de ancho y 3,33 cm de alto, estos grados de arco son apropiados cuando la pantalla del teléfono se mantiene aproximadamente 6 pulgadas de su cara.Pantalla del teléfono es de 480 píxeles de ancho y 800 píxeles de alto, por lo que estos números también implican 25 píxeles por cada grado de arco.

Al aplicar este esquema de proyección en un algoritmo, que necesita para trabajar hacia atrás: Piense en los dos puntos compartidos por los tres círculos de gran azules como un eje y los dos puntos compartidos por los tres círculos rojos de grandes como otro eje.Junto con el vector para el centro de la vista, forman un sistema de coordenadas ortonormales.

Álgebra vectorial permite derivar desvíos de ángulo de cualquier otras coordenadas desde el centro de la vista, como se muestra en la clase de HorizontalCoordinateProjection en figura 4.La clase tiene un método para establecer el centro de la vista y otro método para obtener compensaciones de ángulo de la coordenada horizontal de cualquier otro objeto en relación con ese centro de la vista.

Figura 4 la clase de HorizontalCoordinateProjection

public class HorizontalCoordinateProjection
{
  Vector3 viewCenterVector, horzAxis, vertAxis;
  public void SetViewCenter(HorizontalCoordinate viewCenterCoord)
  {
    viewCenterVector = viewCenterCoord.ToVector();
    HorizontalCoordinate vertAxisCoord =
      new HorizontalCoordinate(viewCenterCoord.Azimuth + 90, 0);
    vertAxis = vertAxisCoord.ToVector();
    horzAxis = Vector3.Cross(viewCenterVector, vertAxis);
  }
  public void GetAngleOffsets(HorizontalCoordinate objectCoord,
       out double horzAngle, out double vertAngle)
  {
    Vector3 objectVector = objectCoord.ToVector();
    Vector3 horzObjectCross = Vector3.Cross(objectVector, -horzAxis);
    Vector3 vertObjectCross = Vector3.Cross(objectVector, vertAxis);
    horzObjectCross.Normalize();
    vertObjectCross.Normalize();
    double x = Vector3.Dot(horzObjectCross, vertAxis);
    double y = Vector3.Dot(horzObjectCross, viewCenterVector);
    horzAngle = -180 * Math.Atan2(y, x) / Math.PI;
    x = Vector3.Dot(vertObjectCross, horzAxis);
    y = Vector3.Dot(vertObjectCross, viewCenterVector);
    vertAngle = -180 * Math.Atan2(y, x) / Math.PI;
  }
}

Para determinar donde debe colocarse el objeto en la pantalla del teléfono, los ángulos obtenidos por el método de GetAngleOffsets deben ser multiplicada por una constante que se selecciona el número de píxeles por cada grado de arco. Anteriormente sugerí que esta constante debe ser igual a 25 cuando se sostiene el teléfono 6 pulgadas de su cara, pero puede que desee ir con algo inferior para proporcionar una visión más amplia.

Visualización de la esfera desde el interior

El programa de ViewHorizontalCoordinates establece su constante PIXELS_PER_DEGREE a 15 para mostrar las coordenadas horizontales desde el interior buscando afuera, como se muestra en la figura 5. Esa opinión particular se produce cuando el teléfono puntos un poco al sur de este, un poco por encima del horizonte.

The ViewHorizontalCoordinates Program
Figura 5 el programa de ViewHorizontalCoordinates

Para cada evento de CurrentValueChanged despedido por el sensor de movimiento, el controlador del evento comienza por la obtención de la matriz de rotación que indica cómo la tierra se orienta en relación con el teléfono. Lo convierte a un valor de HorizontalCoordinate y establece el centro de la vista en un objeto de HorizontalCoordinateProjection creado anteriormente:

Microsoft.Xna.Framework.Matrix matrix =
  args.SensorReading.Attitude.RotationMatrix;
HorizontalCoordinate viewCenter =
  HorizontalCoordinate.FromMotionMatrix(matrix);
coordinateProjection.SetViewCenter(viewCenter);
rotate.Angle = -viewCenter.Tilt;

El objeto gire es un RotateTransform aplicada a todo el lienzo. El controlador entonces implementa varios bucles con valores de altitud y acimut en incrementos de 15 °. La primera vez que se dispara el evento CurrentValueChanged, el controlador de eventos crea todos los elementos necesarios de línea y TextBlock y los agrega al lienzo. Las segunda y sucesivas veces, el controlador simplemente accede a los elementos de línea y TextBlock existentes ya en el lienzo y establece nuevos puntos.

Cada valor de HorizontalCoordinate debe convertirse en una coordenada de la pantalla. Ese es el trabajo del método CalculateScreenPoint en figura 6, que llama al método GetAngleOffsets en HorizontalCoordinateProjection y multiplica los ángulos por la constante PIXELS_PER_DEGREE.

Figura 6, calcular un punto de la pantalla de una coordenada Horizontal

Point CalculateScreenPoint(HorizontalCoordinate horizontalCoordinate)
{
  double horzAngle, vertAngle;
  coordinateProjection.GetAngleOffsets(horizontalCoordinate,
                                       out horzAngle, out vertAngle);
  // Use NaN to indicate points clearly out of range of the screen
  float x = float.NaN;
  float y = float.NaN;
  if (horzAngle > -90 && horzAngle < 90 && 
     vertAngle > -90 && vertAngle < 90)
  {
    x = (float)(width / 2 + PIXELS_PER_DEGREE * horzAngle);
    y = (float)(height / 2 + PIXELS_PER_DEGREE * vertAngle);
  }
  return new Point(x, y);
}

El método GetAngleOffsets devuelve siempre ángulos en la gama de-180 ° a 180 °. A veces las líneas entre estos límites y esto crea un problema envolvente. Por ejemplo, una línea puede (en teoría) extenderse desde-175 ° a 175 °. Esa línea debería sólo 10 ° de longitud, pero la longitud calculada sería 380 °! La lógica en CalculateScreenPoint de NaN ("no es un número") corrige este problema por marcar todos los puntos con desvíos de ángulo inferior a-90 ° o mayor de 90 °, que está fuera del rango de la pantalla.

Quería que las etiquetas de texto mostrando los ángulos de altitud para ser visible independientemente del acimut, y aquellos mostrando los puntos de la brújula sea visible no importa qué tan alto o bajo se apunta el teléfono. Las etiquetas de altitud aparecen con un punto de pantalla calculado desde el azimut de centro de la vista, y las etiquetas de la brújula se muestran con un punto de pantalla calculado a partir de la altitud de centro de la vista, con un pequeño ajuste para no clúster todos juntos cuando se apunta el teléfono hacia arriba o hacia abajo. Este pequeño truco que ayuda a mantener las etiquetas dentro de la pantalla, tal vez girada un poco alejado del centro.

Un interruptor para XNA

Como estaba trabajando en los programas para esta columna en conjunción con AstroPhone para el próximo mes, comencé a notar algunos problemas de rendimiento. El programa de ViewHorizontalCoordinates sólo puede administrar unos 10 fotogramas por segundo en mi teléfono de desarrollo, y el problema parece ser más en el sistema de diseño de Silverlight en lugar de mi código.

Con cierta renuencia decidí que los programas restantes destino el Windows Phone XNA framework en lugar de Silverlight. Este es el caso del proyecto ViewThreeCoordinates, que es similar a ViewHorizontalCoordinates pero escrita para XNA en lugar de Silverlight.

Vista previa de la biblioteca

El proyecto ViewThreeCoordinates también revela algunas de las estrategias que utilizará para el programa de Astronomía completa. Se hace uso de parte de una biblioteca más grande llamada Petzold.Astronomy. En la construcción de esta biblioteca, mi referencia principal ha sido la segunda edición del libro clásico "Algoritmos astronómicos" por Jean Meeus (Willmann-Bell, 1998).

Astronomía posicional requiere mucho de trigonometría. En la biblioteca de Petzold.Astronomy, trato de evitar confusiones y conversiones entre grados y radianes mediante la implementación de una estructura denominada ángulo. Puede crear un valor de ángulo de un grado o un radián utilizando los métodos estáticos de FromDegree o FromRadian y obtener los grados o radianes a, pero no a menudo es necesario porque el ángulo también implementa todas las funciones trigonométricas necesarias como propiedades.

Por ejemplo, si usted tiene un valor de ángulo llamado myAngle, puede obtener el coseno de ese ángulo como tal:

double x = myAngle.Cosine;

Si piensas de senos, cosenos y tangentes como "Propiedades" de ángulos, esto tiene perfecto sentido. Pero observe cómo se implementa la propiedad de coseno:

public double Cosine
{
  get { return Math.Cos(radians); }
  set { radians = Math.Acos(value); }
}

El descriptor de acceso set es la función coseno inverso, lo que significa que puede establecer un valor de ángulo existente en el coseno inverso de un número con una instrucción como ésta:

myAngle.Cosine = x;

El único lugar donde no funcionó bastante este proceso fue en la implementación del método Atan2 esencial. Lo hice con un método estático que crea un valor de ángulo:

public static Angle ArcTangent(double y, double x)
{
  return Angle.FromRadians(Math.Atan2(y, x));
}

Coordenadas ecuatoriales

El programa ViewThreeCoordinates muestra las coordenadas horizontales en dos otros sistemas de coordenadas muy útiles en astronomía posicional más verde: coordenadas ecuatoriales en coordenadas azul y eclíptica en rojo. Figura 7muestra un típico con el teléfono hacia el norte y a una altitud de 25 °. (Sí, ya sé que se llena la pantalla, pero puede tocar la pantalla para mostrar sólo uno o dos conjuntos de coordenadas.)

The ViewThreeCoordinates Display
Figura 7 en la pantalla de ViewThreeCoordinates

Como la tierra gira sobre su eje y gira alrededor del sol, el Ecuador terrestre permanece prácticamente en el mismo plano. El plano del Ecuador terrestre es el plano fundamental asociado con coordenadas ecuatoriales. Coordenadas ecuatoriales consisten en una declinación — positivo sobre el Ecuador y negativo a continuación — y una ascensión que va alrededor del Ecuador. La ascensión se especifica normalmente en horas en lugar de grados, donde cada hora equivale a 15 °.

Naturalmente, coordenadas geográficas (longitud y latitud) también se basan en el Ecuador de la tierra, pero coordenadas geográficas gire con la tierra, mientras que las coordenadas ecuatoriales son fijos en relación con el resto del universo y por lo tanto parecen girar como la tierra gira sobre su eje. Las posiciones de las estrellas se especifican en las coordenadas ecuatoriales, y no cambian mucho con el paso del tiempo.

ViewThreeCoordinates muestra una cuadrícula de coordenadas ecuatoriales convirtiéndolos a coordenadas horizontales. Esta conversión depende de la ubicación geográfica del observador (longitud y latitud) y la hora actual y se implementa en la estructura de HorizontalCoordinate.

Sin embargo, una conversión muy áspera de ascensión a azimut es posible: En un momento de local de medianoche en el equinoccio de primavera (20 de marzo o lácteo), 0 horas ascensión derecha es hacia el norte (0 º de azimut). La brillante estrella Arcturus tiene una ascensión de unas 14 horas, en esa fecha en ese momento, deberás girar hacia el oeste por 210 ° (o hacia el este por 150 °) para verlo. O simplemente puede esperar dos horas hasta 2 y Arcturus será debidamente sur.

Se puede calcular el ángulo de hora local de una estrella, restando su ascensión desde el número de horas desde la hora local de medianoche. Convertir a grados multiplicando por 15 y añadir el número de días desde marzo 21 y que el azimut de la estrella mide hacia el este desde el norte.

Si ejecuta ViewThreeCoordinates y sostenga el teléfono hasta el cielo nocturno, el polo norte Ecuatorial (visible en la parte superior de la figura 7) se corresponden con la ubicación de Polaris, la estrella del Norte, que tiene una declinación de casi 90 ° y, por tanto, coincide con el vector de eje de la tierra. Observe cómo la línea de azimut de norte cruza ese polo.

Coordenadas de la eclíptica

Las órbitas de todos los planetas del sistema solar están aproximadamente en el mismo plano. Este plano se llama la eclíptica, y es la base de coordenadas de la eclíptica (también conocido como celestes coordenadas), que se muestran por ViewThreeCoordinates en rojo. Una coordenada de la eclíptica consiste en una eclíptica longitud y la latitud de la eclíptica.

Las coordenadas de la eclíptica se usan principalmente cuando se calculan las posiciones del sol, planetas y la Luna. Porque el sol y los planetas se encuentran en aproximadamente el mismo plano, la latitud de la eclíptica de estos objetos generalmente es cercano a cero. La eclíptica sí se muestra con una línea roja gruesa en ViewThreeCoordinates. Si tiene el teléfono al día o planetas, el sol y el cielo nocturno deben coincidir con esa línea.

Coordenadas ecuatoriales y las coordenadas de la eclíptica difieren únicamente como consecuencia de la inclinación de la tierra de alrededor de 23 ° con respecto a la eclíptica. Una coordenadas ecuatoriales de declinación de ascensión recta y 0 ° 0 horas es igual a una coordenadas ecuatoriales de 0 ° de longitud y latitud 0 °, y los dos sistemas coinciden también en 180 °.

En el equinoccio de primavera, el sol tiene una longitud eclíptica de 0 °. Esa longitud aumenta aproximadamente 1 ° por día a lo largo del año. Por lo tanto, la longitud eclíptica del sol en grados es aproximadamente igual al número de días desde el 21 de marzo.

Longitudes de la eclíptica se etiquetan con los signos del zodiaco, comenzando por Aries para 0 °-30 °, Taurus para 30 °-60 °, Gemini para 60 °-90 ° y así sucesivamente a través de Piscis para 330 °-360 °. También he hecho esto en ViewThreeCoordinates. Estos signos del zodíaco son las constelaciones que se encuentran aproximadamente en estas longitudes de la eclíptica con latitudes de la eclíptica en el barrio de cero. Así, el sol está "Aries" (que significa que Aries está más allá de sol) durante el mes comenzando el 21 de marzo.

Suficiente teoría. En la siguiente aparición de esta columna, las líneas de la cuadrícula de los sistemas de coordenadas esféricas se reemplazará con el sol, Luna, planetas, estrellas y constelaciones.

Charles Petzold es un viejo colaborador MSDN Magazine y actualmente está actualizando su clásico libro "Programming Windows" (Microsoft Press, 1998) para Windows 8. Su sitio Web es charlespetzold.com.

Gracias al siguiente experto técnico por su ayuda en la revisión de este artículo: Donn Morse