Este artigo foi traduzido por máquina.

Toque e ouça

Exibindo o Night Sky no seu Windows Phone

Charles Petzold

Baixar o código de exemplo

Nas páginas de abertura da história clássica, "A revolução copernicana" (Harvard University Press, 1957), Thomas S. Kuhn evoca um mundo há muitos séculos atrás, em que as pessoas tinham uma íntima familiaridade com o céu noturno. Ainda que não sujeitos a iluminação persistente da iluminação artificial, esses observadores experimentaram em primeira mão como a cúpula de estrelas parece girar durante a noite em um longo arco ao redor da estrela do Norte e como a configuração de estrelas no nascer e pôr do sol progride através de um ciclo anual de 12 etapas do zodíaco.

Observaram, também, como várias estrelas não seguiu este mesmo padrão. Estas curiosidades pareciam vagueiam o panorama de estrelas fixas, às vezes até mesmo invertendo o movimento em relação a abóbada celeste. Essas exceções à regra geral ainda são conhecidas pela palavra grega antiga para andarilho: Πλανήτης, ou planeta.

A tentativa de traçar e prever o movimento desses planetas foi o início da agitação mais famoso na história da ciência, levando-à derrubada da cosmologia primitiva e o deslocamento da terra do centro do universo. Ao mesmo tempo que a raça humana ganhou uma melhor compreensão do seu lugar no cosmos, ele também começou a perder essa relação especial com o céu noturno.

Usando AstroPhone

Hoje em dia a maioria de nós têm não o tempo, paciência ou tranquilidade de espírito para olhar o céu à noite tempo suficiente para começar uma sensação para seus padrões cíclicos ou detectar o errante dos planetas. Em vez disso contamos com gráficos de estrelas ou baseado em computador astronômico ferramentas para ajudar.

Esta coluna descreve minha modesta contribuição para o gênero, um pequeno programa para Windows Phone com o nome bobo AstroPhone. O código-fonte para download do aplicativo consiste em um programa XNA chamado AstroPhone e uma biblioteca chamada Petzold.Astronomy que contém muitos dados e Phyton.

Este programa não tem nenhuma interface do usuário de qualquer tipo exceto o esforço necessário para apontar a parte traseira do telefone para um local no céu noturno. A tela do telefone, em seguida, exibe as estrelas, constelações e planetas localizado lá. Figura 1 mostra uma tela típica, feita em 15:45 Hora local em 15 de julho de 2012, na região de Nova York, com o telefone em uma direção oeste.


Figura 1 tela típica do AstroPhone

A linha verde é o horizonte rotulado com pontos da bússola. (Observe o W West.) A linha vermelha é a eclíptica, que é o plano através do qual todos os planetas aproximadamente órbita, com marcas de escala cada 15 °. Você pode ver Júpiter e Vênus devido a definir nos próximos 90 minutos ou assim. Também visível — na tela, se não na meados-­tarde céu — é a constelação de touro.

Para posicionar as estrelas e planetas corretamente na tela, o programa precisa para combinar informações de várias fontes:

  • Dados e algoritmos para derivar a posição das estrelas e planetas (descritas nas seções a seguir).
  • A data atual e a hora para usar esses algoritmos.
  • GPS do telefone para que o programa sabe onde o telefone está localizado na superfície da terra.
  • Sensor de movimento do telefone então o programa sabe como o telefone é orientado no espaço 3D, e, portanto, que parte do celestial sphere está apontado na direção.

Devido à sua forte dependência de sensores do telefone, este programa não será executado no emulador Windows Phone.

Em várias parcelas anteriores desta coluna eu discutindo alguns dos conceitos de usando o sensor de movimento e converter essa informação em vários sistemas de coordenadas. Os artigos anteriores estão disponíveis no site da MSDN Magazine (bit.ly/NoMc8R). Grande parte da minha abordagem à astronomia posicional é baseado no livro de Jean Meeus, "Algoritmos astronômicos" (Rebecka-Bell, 1998), embora eu usei algumas vezes um pouco simplificados de cálculos, e não garante que eu tenha eliminado todos os erros que eu faça.

Estrelas e constelações

Se você procurar uma estrela particular na Wikipedia, você vai encontrar a sua localização é dada em termos de dois números — uma ascensão reta e a declinação. Por exemplo, Betelgeuse tem uma ascensão reta de 5 horas, 55 minutos e 10.3053 segundos e uma declinação de 7 °, 24 minutos e 25.426 segundos. Esta posição é relativo ao sistema de Coordenadas Equatoriais, em que do Equador divide o universo em declinações angulares positivas para o norte e negativas declinações angulares para o Sul. (Polaris, também conhecido como estrela do Norte, tem uma declinação de quase 90 °).

Tradicionalmente, a ascensão reta é medido em horas, com cada hora equivalente a 15 °. A Ascenção de zero corresponde à mesma direção norte em meia-noite, hora local na data do equinócio vernal. Porque o plano do Equador da terra permanece aproximadamente constante durante todo o ano (e ao longo dos séculos), e porque as estrelas estão tão longe, longe, eles são considerados têm as mesmas coordenadas equatoriais independentemente da posição da terra. Estas Coordenadas Equatoriais para as estrelas são especificadas para uma determinada época (por exemplo, o ano 2000), e pequenos ajustes anuais podem ser aplicados a conta para o ligeiro movimento das estrelas.

Existem muitos catálogos de estrelas, mais deles com muitas estrelas mais do que eu queria mostrar no meu programa. Eu decidi usar a versão atualizada de um catálogo que originou mais de 100 anos atrás: o Bright Star Catalog, 5ª edição revisada, que obtidos a partir de um site FTP, mantido pelo centro de dados astronômico Estrasburgo (bit.ly/T51GE5).

Mesmo este catálogo forneceu informações muito mais do que eu precisava e também um pouco menos. A maior parte eu queria que meu programa para exibir apenas as estrelas principais associadas com as 88 constelações padrão usadas na astronomia moderna. Isso foi bastante fácil, pois as estrelas têm denominações (primeiro desenvolvidas por Johann Bayer há mais de 400 anos) que indicam qual constelação a estrela pertence a uma abreviação de três letras e uma única letra grega.

Mas eu também queria realçar cada constelação com as conexões da linha familiar entre as estrelas assim que Leo seria realmente parecido com um boneco Leão. As linhas ligando as estrelas nas constelações não são padrão, e eu não sabia de um catálogo de estrela que inclui-los.

Então eu adicionei-me. Eu escrevi um pequeno programa de Windows Presentation Foundation (WPF) que acessado o Bright Star Catalog e exibido as estrelas de cada uma das 88 constelações. O programa respondeu a cliques de mouse em pares de estrelas e gravou os resultados. Geralmente eu baseado em linhas de conexão em diagramas das constelações na Wikipedia, que são creditados a União Astronômica Internacional e Sky & Revista do telescópio.

O programa WPF consolidados os dados em um arquivo chamado Constellations.xml, que pode ser encontrado no diretório de dados do projeto de biblioteca de Petzold.Astronomy. Cada marca de constelação contém uma coleção de marcas de estrelas. Cada estrela é identificada com um número de catálogo estrela brilhante. As marcas de estrelas em cada constelação, em seguida, são seguidas por uma coleção de conector marcas que definem linhas entre pares de estrelas numeradas.

Os planetas

Como mesmo primitivos astrônomos percebidos, a localização dos planetas é muito mais complexa do que o das estrelas. Os planetas têm órbitas elípticas em torno do sol, mas irregularidades resultam da mútua interação gravitacional. Um algoritmo para determinar a localização de um planeta em um determinado momento é muitas vezes conhecido como uma "teoria" e geralmente com base em uma série de Fourier.

A teoria planetária que usei é chamada VSOP87, variações Séculaires des Orbites Planétaires, versão de 1987, que é mantido pelo Bureau des Longitudes, em Paris. Os arquivos contendo os dados de uma porção de VSOP87 também estão incluídos no diretório de dados do projeto Petzold.Astronomy. A classe VsopCruncher realiza os cálculos para cada planeta de um ponto específico no tempo.

As posições dos planetas são geralmente calculadas em coordenadas elípticas, mas com o sol no centro — ou seja, heliocêntrico, ao invés de geocêntrico. Para cada planeta, essas coordenadas consistem de:

  • uma longitude eclíptica que vai de 0 ° a 360 ° como o planeta faz uma órbita completa em torno do sol durante o ano especial
  • uma latitude eclíptica que é perto de zero, porque todos os planetas orbitam o sol em aproximadamente o mesmo plano
  • um raio, que é a distância do planeta do sol.

Essas coordenadas são grandes para plotar o movimento dos planetas em torno do sol. No entanto, se você deseja calcular a posição do planeta como visto da terra, é conveniente converter estas coordenadas esféricas em coordenadas retangulares tridimensionais, onde a posição de um planeta é indicada por X, Y e Z valores com o sol ocupando a origem de centro em (0, 0, 0). Subtraindo-se a coordenada retangular de qualquer planeta da coordenada retangular da terra, você começa um vetor 3D da terra para que o planeta, que pode ser então convertido a ascenção e valores de declinação de uma coordenada da eclíptica geocêntrica — o mesmo sistema de coordenadas usado para as estrelas.

Movimento da lua é muito mais complexo do que as estrelas e planetas e tem que ser tratado como um caso separado. Optei por não incluir a lua nesta versão do programa AstroPhone. Além disso, se incluir a lua, iria se sentir obrigado a mostrar a fase atual, e que iria complicar o trabalho ainda mais.

Cadeias de cálculos

Para executar os cálculos necessários de forma metódica, defini uma hierarquia de classes:

CelestialBody
        Constellation
        Star
            SolarSystemBody
                Sun
                Planet
                    Earth

As classes de estrela e constelação também desempenham um papel duplo como alvos de desserialização do arquivo Constellations.xaml.

Conforme Figura 2, a classe CelestialBody é responsável por uma HorizontalCoordinate de um EquatorialCoordinate de computação baseado sobre a localização geográfica do telefone e a data atual e tempo. Classes descendente calculam que EquatorialCoordinate propriedade substitui o método OnTimeChanged.

Figura 2 classe de CelestialBody pai

public abstract class CelestialBody
{
  // Only used internally
  private GeographicCoordinate Location { set; get; }
  // Set here, used by descendant classes
  protected Time Time { private set; get; }
  // Set by descendant classes, used here
  protected EquatorialCoordinate EquatorialCoordinate { set; private get; }
  // Set here, used external to library
  public HorizontalCoordinate HorizontalCoordinate { private set; get; }
  // Used externally to retain screen location
  public float ScreenX;
  public float ScreenY;
  // Called external to update HorizontalCoordinate
  public void Update(Time time, GeographicCoordinate location)
  {
    bool needsUpdate = false;
    if (!this.Time.Equals(time))
    {
      this.Time = time;
      needsUpdate = true;
      OnTimeChanged();
    }
    if (!this.Location.Equals(location))
    {
      this.Location = location;
      needsUpdate = true;
    }
    if (needsUpdate)
    {
      this.HorizontalCoordinate =
        HorizontalCoordinate.From(this.EquatorialCoordinate,
                                  this.Location, this.Time);
    }
  }
  // Overridden by descendant classes to update EquatorialCoordinate
  protected virtual void OnTimeChanged()
  {
  }
}

A classe SolarSystemBody mostrada Figura 3 calcula o EquatorialCoordinate propriedade de um vetor de HeliocentricLocation fornecido por suas classes descendentes e a classe do planeta, mostrada na Figura 4, calcula-se que HeliocentricLocation baseado em uma chamada para o VsopCruncher.

Figura 3 da classe de SolarSystemBody

public class SolarSystemBody : CelestialBody
{
  protected SolarSystemBody()
  {
  }
  protected SolarSystemBody(string name, Color color)
  {
    this.Name = name;
    this.Color = color;
  }
  public string Name { protected set; get; }
  public Color Color { protected set; get; }
  // Set by descendant classes, used here
  protected Vector3 HeliocentricLocation { set; private get; }
  protected override void OnTimeChanged()
  {
    // Calculate geocentric coordinates
    Vector3 bodyLocation = this.HeliocentricLocation -
                           Earth.Instance.HeliocentricLocation;
    EclipticCoordinate geocentricCoordinate =
      new EclipticCoordinate(bodyLocation);
    this.EquatorialCoordinate =
      EquatorialCoordinate.From(geocentricCoordinate, this.Time);
    base.OnTimeChanged();
  }
}

Figura 4 a classe do planeta

public class Planet : SolarSystemBody
{
  VsopCruncher vsop;
  public Planet(string strPlanetAbbreviation, 
    string name, Color color) :
    this(strPlanetAbbreviation)
  {
    this.Name = name;
    this.Color = color;
  }
  protected Planet(string strPlanetAbbreviation)
  {
    vsop = new VsopCruncher(strPlanetAbbreviation);
  }
  protected override void OnTimeChanged()
  {
    Angle latitude = Angle.FromRadians(vsop.GetLatitude(this.Time.Tau));
    Angle longitude = Angle.FromRadians(vsop.GetLongitude(this.Time.Tau));
    double radius = vsop.GetRadius(this.Time.Tau);
    this.HeliocentricLocation =
      new EclipticCoordinate(longitude, 
          latitude, radius).RectangularCoordinates;
    base.OnTimeChanged();
  }

A classe de estrelas é ainda mais simples porque ele pode calcular um Equatorial­coordenar com apenas um pequeno ajuste para a posição do ano 2000.

O fim da frente XNA

Comecei a escrever o programa de AstroPhone usando o Silverlight, que trabalhou muito com o primeiro várias constelações. Mas as constelações mais acrescentei, ficou mais lento.

Tenha em mente que, quando usando o Silverlight para um programa desse tipo, o texto, linhas e pontos são elementos TextBlock, linha e caminho em um painel de algum tipo. Para obter o movimento do fluido como você varre o telefone em um arco, este deve ser apenas um painel, e ele tem que ter tudo na mesma. Desempenho fica prejudicado ainda mais se você começar a remoção de itens ou tornando-se invisível quando não está no modo de exibição.

Passei muito tempo tentando melhorar o desempenho do programa Silverlight. Descobri que usar uma tela funcionou melhor do que uma grade de célula única. Achei que ao exibir um monte de elementos de linha, você poderia melhorar o desempenho, definindo uma coordenada da linha para o ponto (0, 0), ajustando a outra coordenada pela mesma quantidade e usando um TranslateTransform para movê-lo para a posição.

Mas com todas as 88 constelações no lugar, a taxa de frame de vídeo caiu para um único frame por segundo, e não havia simplesmente alternativa exceto ao abandonar o Silverlight. É por isso que AstroPhone é um programa XNA.

Curiosamente, a parte mais lenta da AstroPhone não em todos os gráficos. É a desserialização do arquivo Constellations.xml, que ocorre na substituição da classe de jogo OnActivated. O programa compila várias coleções para atualização e renderização de objetos celestes. A coleção principal usada para atualização de coordenadas é chamada celestialBodies. Como o nome sugere, esta é uma coleção de instâncias de classes que derivam de CelestialBody, e contém 832 objetos — 735 objetos do tipo estrela, 88 de tipo constelação, um sol e todos os oito objetos do planeta. (Plutão não está incluído no VSOP87).

Em um programa XNA para Windows Phone, substitui a atualização e desenhar na classe jogo é chamados à taxa de 30 vezes por segundo. Atualização é responsável por obter entrada de sensores (GPS e movimento, neste caso) e preparação de dados para o método desenhar.

Para obter a resposta mais suave para os movimentos do telefone, a atualização substituir faz um loop através da coleção inteira celestialBodies, obtém a propriedade HorizontalCoordinate de cada objeto e usa a matriz atual do movimento que converter um ponto bidimensional na tela, que, em seguida, armazena as propriedades ScreenX e imagens do objeto CelestialBody. O método Draw, em seguida, acessa as propriedades ScreenX e imagens para desenhar o objeto na tela.

Mas esse cálculo é apenas para explicar o movimento da tela. Também é necessário para cada objeto de CelestialBody para atualizar periodicamente sua propriedade HorizontalCoordinate como o tempo passa e a terra e outros planetas movem um pouco. Ainda assim, esta atualização não é crucial para o bom funcionamento do programa. A propriedade HorizontalCoordinate é baseada na data atual e tempo e a localização geográfica do usuário, mas nenhum desses itens muda rapidamente o suficiente para afetar a posição das estrelas e planetas a curto prazo.

Por esse motivo, a substituição de atualização do jogo classe lida com os métodos de atualização de objetos CelestialBody de forma agradável. Somente um item na coleção celestialBodies é atualizado para cada chamada de substituição de atualização da classe jogo, exigindo um ciclo de aproximadamente 28 segundos para loop através da coleção inteira de 832 objetos.

Para fins de processamento, outras coleções são mantidas diferentes tipos de objetos celestes são processados em maneiras diferentes. A coleção de visibleStars contém os 735 objetos de estrelas que são processados na tela, a coleção de constelações tem 88 constelações e systemBodies coleção tem o sol e os sete planetas, excluindo a terra.

Como cada classe que deriva de CelestialBody, a constelação classe define uma propriedade de EquatorialCoordinate, mas isso é apenas para fins de posicionamento o nome da constelação. Que posição é calculada por cada instância de constelação, tendo uma média das estrelas conectadas que compõem a constelação.

As linhas de conexão se foram um pouco complicadas. Cada objeto constelação tem uma coleção de objetos do conector, cada qual faz referência a um par de estrelas da constelação. Mas esses objetos do conector provêm do arquivo original do Constellations.xml e que fazem referência o par de estrelas conectadas com números de ID. Para acelerar o desenho de linha, o programa passa a parte do processo de inicialização, completando cada par de números de identificação com um objeto StarConnector, que é um par de objetos reais de estrela. Assim, o programa pode desenhar linhas conectoras referenciando as propriedades ScreenX e imagens de objetos de estrelas reais.

Figura 5 mostra a parte do método Draw que processa os nomes da constelação, as linhas de conexão e as próprias estrelas.

Figura 5 o método de sorteio para processar constelações e estrelas

protected override void Draw(GameTime gameTime)
{
  // Dark blue sky
  GraphicsDevice.Clear(new Color(0, 0, 0x20));
  spriteBatch.Begin(SpriteSortMode.Immediate, 
    null, null, null, null, null,
    displayMatrix);
  ...
// Loop through constellations
  foreach (Constellation constellation in 
    constellations.ConstellationList)
  {
    if (!float.IsNaN(constellation.ScreenX))
    {
      // Display constellation name
      Vector2 textSize = 
        labelFont.MeasureString(constellation.LongName);
      spriteBatch.DrawString(labelFont, constellation.LongName,
        new Vector2(constellation.ScreenX - textSize.X / 2,
        constellation.ScreenY - textSize.Y / 2), Color.Gray);
    }
    // Display constellation connectors
    if (constellation.StarConnectors != null)
    {
      foreach (StarConnector starConnector in 
        constellation.StarConnectors)
      {
        Vector2 point1 = new Vector2((float)starConnector.From.ScreenX,
          (float)starConnector.From.ScreenY);
        Vector2 point2 = new Vector2((float)starConnector.To.ScreenX,
          (float)starConnector.To.ScreenY);
        if (!float.IsNaN(point1.X) && !float.IsNaN(point2.X))
          lineRenderer.Draw(spriteBatch, point1, point2, 
           1, Color.White);
      }
    }
  }
  // Now display the stars themselves
  foreach (Star star in visibleStars)
    if (!float.IsNaN(star.ScreenX))
      starDotRenderer.Draw(spriteBatch,
        new Vector2(star.ScreenX, star.ScreenY), Color.White);
  ...
spriteBatch.End();
  base.Draw(gameTime);
}

Apesar de programas como o AstroPhone fornecem um guia útil para as estrelas e planetas, nada se aproxima a experiência de realmente olhar para eles na vida real. Talvez como pessoas ganham mais conhecimento com a ajuda de programas como este, eles mais uma vez irão desenvolver uma íntima familiaridade com o céu noturno.

Charles Petzold é um colaborador de longa data de MSDN Magazine e atualmente está atualizando seu livro clássico, "Programação Windows" (Microsoft Press, 1998), para o Windows 8. Seu site é charlespetzold.com.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Donn Morse