Il presente articolo è stato tradotto automaticamente.

Touch-and-Go

Visualizzazione del cielo notturno nel proprio Windows Phone

Charles Petzold

Scarica il codice di esempio

Charles PetzoldNelle prime pagine della sua storia classica, "Rivoluzione copernicana" (Harvard University Press, 1957), Thomas S. Kuhn evoca un mondo molti secoli fa, in cui la gente aveva un'intima familiarità con il cielo notturno. Non ancora soggetti a illuminazione permanente di illuminazione artificiale, questi osservatori sperimentato in prima persona come la cupola di stelle sembra ruotare durante la notte in un lungo arco attorno alla stella del Nord e come la configurazione di stelle all'alba e al tramonto progredisce attraverso un ciclo annuale di 12 passi dello zodiaco.

Essi hanno anche osservato come molte stelle non hanno seguito questo stesso modello. Queste stranezze sembravano di vagare per il panorama delle stelle fisse, a volte anche invertire il moto relativo della cupola celeste. Queste eccezioni alla regola generale sono ancora conosciute dall'antica parola greca per wanderer: Πλανήτης, o il pianeta.

Il tentativo di rintracciare e di prevedere il movimento di questi pianeti fu l'inizio dello sconvolgimento più famoso nella storia della scienza, che portò al rovesciamento della cosmologia primitiva e lo spostamento della terra dal centro dell'universo. Allo stesso tempo che la razza umana ha guadagnato una comprensione molto meglio del suo posto nel cosmo, ha cominciato a perdere quel rapporto speciale con il cielo notturno.

Utilizzando AstroPhone

In questi giorni molti di noi hanno non il tempo, pazienza o la quiete della mente a guardare il cielo abbastanza a lungo per ottenere un tatto per i suoi modelli ciclici o rilevare l'errare dei pianeti. Invece, contiamo su mappe stellari o strumenti astronomici basati su computer per aiutare.

Questo articolo descrive il mio modesto contributo al genere, un piccolo programma per Windows Phone con il nome stupido AstroPhone. Il codice sorgente scaricabile per l'applicazione è costituito da un programma XNA chiamato AstroPhone e una libreria denominata Petzold.Astronomy che contiene gran parte dei dati e sgranocchiare numero.

Questo programma non ha alcuna interfaccia utente qualsiasi cosa tranne lo sforzo necessario per puntare la parte posteriore del telefono verso una posizione nel cielo notturno. Schermo del telefono cellulare visualizza quindi stelle, costellazioni e pianeti che si trova lì. Figura 1 Mostra una tipica schermata, a 15:45 ora locale il 15 luglio 2012, nella regione di New York City, con il telefono è tenuto in direzione ovest.

A Typical AstroPhone Screen
Figura 1 tipico AstroPhone schermo

La linea verde è l'orizzonte etichettato con i punti cardinali. (Notare il W per west). La linea rossa è l'eclittica, che è il piano attraverso il quale tutti i pianeti circa orbitano, con graduazione ogni 15 °. Si vede Giove e Venere dovuto impostare entro i prossimi 90 minuti o così. Visibile anche — sullo schermo, se non nella metà-­pomeriggio cielo — è la costellazione del Toro.

Per posizionare correttamente le stelle e i pianeti sullo schermo, il programma deve combinare informazioni provenienti da fonti diverse:

  • Dati e algoritmi per ricavare la posizione delle stelle e dei pianeti (descritti nelle sezioni seguenti).
  • La data e ora correnti per utilizzare tali algoritmi.
  • GPS del telefono così il programma sa dove si trova il telefono sulla superficie della terra.
  • Sensore di movimento del telefono così il programma sa come il telefono è orientato nello spazio 3D, e quindi quale parte dei celesti sfera si è puntato verso.

A causa del suo pesante dipendenza da sensori del telefono cellulare, questo programma non verrà eseguito sull'emulatore Windows Phone.

In diverse rate precedenti di questo articolo io ho discusso alcuni dei concetti di usando il sensore di movimento e la conversione di tali informazioni ai vari sistemi di coordinate. Gli articoli precedenti sono disponibili sul sito Web di MSDN Magazine (bit.ly/NoMc8R). Gran parte del mio approccio all'astronomia posizionale è basato sul libro di Jean Meeus, "Algoritmi astronomici" (Willmann-Bell, 1998), anche se a volte ho usato un po' semplificati di calcoli e non fare alcuna garanzia che io ho eliminato tutti gli errori.

Stelle e costellazioni

Se si cerca una stella particolare su Wikipedia, troverai la sua posizione è dato in termini di due numeri — un'ascensione retta e una declinazione. Per esempio, Betelgeuse ha un'ascensione retta di 5 ore, 55 minuti e 10.3053 secondi e una declinazione di 7 °, 24 minuti, 25.426 secondi. Questa posizione è relativo al sistema di coordinate equatoriali, in cui equatore terrestre si divide l'universo in positivi declinazioni angolare a nord e negativi declinazioni angolare a sud. (Polaris, noto anche come la stella del Nord, ha una declinazione di quasi 90 °).

Tradizionalmente, l'ascensione retta è misurata in ore, ogni ora equivalente a 15 °. Un'ascensione retta zero corrisponde alla stessa direzione nord a mezzanotte ora locale alla data dell'equinozio di primavera. Perché il piano dell'equatore terrestre rimane all'incirca costante durante tutto l'anno (e nel corso dei secoli), e perché le stelle sono finora via, sono considerati hanno le stesse coordinate equatoriali indipendentemente dalla posizione della terra. Queste coordinate equatoriali di stelle vengono specificate per una determinata epoca (ad esempio, l'anno 2000) e piccole regolazioni annuale possono essere applicati al conto per il leggero movimento delle stelle.

Esistono molti cataloghi di stelle, più di loro, con molte più stelle che volevo visualizzare nel mio programma. Ho deciso di utilizzare la versione aggiornata di un catalogo che ha avuto origine più di 100 anni fa: Il Bright Star Catalog, quinta edizione riveduta, ottenuti da un sito FTP mantenuto da Strasburgo Astronomical Data Center (bit.ly/T51GE5).

Anche questo catalogo fornito informazioni molto di più che mi serviva e anche un po' meno. Per la maggior parte volevo che il mio programma per visualizzare solo le stelle principali associate con le 88 costellazioni standard usate in astronomia moderna. Che è stato abbastanza facile perché le stelle hanno denominazioni (in primo luogo sviluppate da Johann Bayer più di 400 anni fa) che indicano quale costellazione la stella appartiene a con un'abbreviazione di tre lettere e un'unica lettera greca.

Ma anche voluto migliorare ogni costellazione con le connessioni di linea familiare tra le stelle così che Leo in realtà apparirebbe come un bastone-figura di Leone. Le linee che collegano le stelle delle costellazioni non sono standard, e non sapevo di un catalogo di stella che li comprendeva.

Così ho aggiunto io. Ho scritto un piccolo programma di Windows Presentation Foundation (WPF) che accede il Bright Star Catalog e visualizzate le stelle di ciascuna delle 88 costellazioni. Il programma ha risposto al clic del mouse su una coppia di stelle e registrata i risultati. Generalmente basate le linee di collegamento sui diagrammi delle costellazioni su Wikipedia, che sono accreditati alla International Astronomical Union e Sky & Rivista del telescopio.

Il programma WPF consolidato i dati in un file denominato Constellations.xml, che si trova nella directory dei dati del progetto della libreria Petzold.Astronomy. Ogni tag costellazione contiene un insieme di tag di stelle. Ogni stella è identificato con un numero dal Bright Star Catalog. I tag di Star in ogni costellazione sono poi seguiti da un insieme di tag connettore che definiscono le linee tra le coppie di stelle numerate.

I pianeti

Come anche primitivi stargazers realizzato, la posizione dei pianeti è molto più complessa di quello delle stelle. I pianeti hanno orbite ellittiche attorno al sole, ma irregolarità dovuta alla reciproca interazione gravitazionale. Un algoritmo per determinare la posizione di un pianeta in un momento particolare è spesso conosciuto come una "teoria" e in genere basato su una serie di Fourier.

La teoria planetaria che ho usato è chiamata VSOP87, variazioni Séculaires des Orbites Planétaires, versione del 1987, che viene mantenuto dal Bureau des Longitudes a Parigi. I file contenenti i dati di una porzione di VSOP87 sono anche inclusi nella directory dei dati del progetto Petzold.Astronomy. La classe VsopCruncher esegue i calcoli per ciascun pianeta per un determinato punto nel tempo.

Le posizioni dei pianeti sono solitamente calcolate in coordinate eclittiche, ma con il sole nel centro — che è eliocentrico e quello geocentrico. Per ciascun pianeta, costituito da queste coordinate:

  • una longitudine eclittica che va da 0 ° a 360 ° come il pianeta rende un'orbita completa intorno al sole durante il suo anno di particolare
  • una latitudine eclittica che è vicino a zero, perché tutti i pianeti orbitano il sole più o meno sullo stesso piano
  • un raggio, che è la distanza del pianeta dal sole.

Queste coordinate sono grandi per tracciare il movimento dei pianeti intorno al sole. Tuttavia, se si desidera calcolare la posizione del pianeta come visto dalla terra, è conveniente convertire le coordinate sferiche in tridimensionale coordinate rettangolari, dove la posizione di un pianeta è indicato da X, Y e Z valori con il sole che occupa l'origine centro in (0, 0, 0). Sottraendo le coordinate cartesiane di qualsiasi pianeta dalla coordinata della terra rettangolare, si ottiene un vettore 3D dalla terra di quel pianeta, che poi può essere convertito in ascensione retta e i valori di declinazione di una coordinata eclittica geocentrica — lo stesso sistema di coordinate usato per le stelle.

Il movimento della luna è molto più complesso di quello delle stelle e dei pianeti e deve essere gestito come un caso separato. Ho scelto di non includere la luna in questa versione del programma AstroPhone. Inoltre, se includono la luna, mi sento obbligato a mostrare la fase attuale e che complicherebbero ancora di più il lavoro.

Catene di calcoli

Per eseguire i calcoli necessari in modo metodico, definita una gerarchia di classi:

 

CelestialBody
        Constellation
        Star
            SolarSystemBody
                Sun
                Planet
                    Earth

Le classi Star e costellazione anche giocano ruoli doppi come obiettivi la deserializzazione del file Constellations.xaml.

Come mostrato Figura 2, la classe CelestialBody è responsabile di un HorizontalCoordinate da un EquatorialCoordinate di calcolo basato sulla posizione geografica del telefono la data corrente e l'ora. Le classi discendenti calcolano che EquatorialCoordinate proprietà esegue l'override del metodo OnTimeChanged.

Figura 2 la classe di CelestialBody padre

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()
  {
  }
}

La classe SolarSystemBody in Figura 3 calcola la proprietà di EquatorialCoordinate da un vettore di HeliocentricLocation fornito da relative classi discendenti e la classe del pianeta, mostrata Figura 4, calcola che HeliocentricLocation si basa su una chiamata al VsopCruncher.

Figura 3 la classe 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 la classe Planet

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();
  }

Classe Star è ancora più semplice, perché si può calcolare un equatoriale­coordinare con solo un piccolo aggiustamento di posizione anno 2000.

L'estremità anteriore XNA

Ho iniziato a scrivere il programma di AstroPhone utilizzando Silverlight, che ha lavorato molto con il primo diverse costellazioni. Ma le costellazioni più ho aggiunto, più lenta è diventato.

Tenere presente che quando si utilizza Silverlight per tale programma, il testo, linee e punti sono elementi TextBlock, linea e percorso in un pannello di qualche tipo. Per ottenere movimenti fluidi come si spazza il telefono in un arco, questo deve essere un solo pannello e ha avuto modo di avere tutto in esso. Le prestazioni si riducono ancora di più se si inizia la rimozione di elementi o rendere invisibile quando non sono in vista.

Ho speso un sacco di tempo cercando di migliorare le prestazioni di questo programma di Silverlight. Ho scoperto che utilizzando una tela lavorato meglio di una griglia a cella singola. Ho trovato che quando si visualizza un sacco di elementi della linea, potrebbe migliorare le prestazioni impostando una coordinata della linea il punto (0, 0), regolando le altre coordinate per lo stesso importo e utilizzo di un oggetto TranslateTransform per spostarlo nella posizione.

Ma con tutte le 88 costellazioni in luogo, il frame rate video, sceso a un singolo frame al secondo, e non c'era semplicemente alcuna alternativa tranne ad abbandonare Silverlight. Ecco perché AstroPhone è un programma XNA.

Interessante, la parte più lenta del AstroPhone non è grafica a tutti. È la deserializzazione del file Constellations.xml, che si verifica nell'override di OnActivated della classe gioco. Il programma si basa quindi diverse collezioni per l'aggiornamento e il rendering di oggetti celesti. L'insieme primario utilizzato per l'aggiornamento di coordinate è chiamato celestialBodies. Come suggerisce il nome, questo è un insieme di istanze di classi che derivano da CelestialBody, e contiene 832 oggetti — 735 oggetti di tipo Star, 88 di tipo costellazione, un sole e tutti gli oggetti pianeta otto. (Pluto non è incluso in VSOP87).

In un programma XNA per Windows Phone, sono chiamate Update e Draw override nella classe gioco al ritmo di 30 volte al secondo. Aggiornamento è responsabile per ottenere input da sensori (GPS e movimento, in questo caso) e preparazione dei dati per il metodo Draw.

Per ottenere la risposta più ai movimenti del telefono, l'aggiornamento eseguire l'override di loop attraverso la raccolta intera celestialBodies, ottiene la proprietà di HorizontalCoordinate da ogni oggetto e utilizza la matrice corrente di movimento per che convertire un punto bidimensionale sullo schermo, che viene quindi memorizzato nelle Proprietà ScreenX e ScreenY dell'oggetto CelestialBody. Il metodo Draw quindi accede a tali proprietà ScreenX e ScreenY per disegnare l'oggetto sullo schermo.

Ma tale calcolo è esclusivamente per il movimento dello schermo. È anche necessario per ogni oggetto CelestialBody per aggiornare periodicamente le sue proprietà HorizontalCoordinate come passa il tempo e la terra e altri pianeti muovono un po '. Questo aggiornamento non è ancora, fondamentale per il corretto funzionamento del programma. La proprietà HorizontalCoordinate è basata sulla data corrente e il tempo e la posizione geografica dell'utente, ma nessuno di questi elementi cambia abbastanza rapidamente a pregiudicare la posizione di stelle e pianeti nel breve termine.

Per questo motivo, l'override di aggiornamento della classe gioco tratta con i metodi di aggiornamento degli oggetti CelestialBody in maniera piacevole. Per ogni chiamata di override di aggiornamento della classe gioco, che richiedono un ciclo di circa 28 secondi per scorrere l'intero insieme di 832 oggetti viene aggiornato solo un elemento dell'insieme celestialBodies.

Ai fini della resa, altre collezioni sono mantenuti perché diversi tipi di oggetti celesti sono resi in modi diversi. L'insieme visibleStars contiene gli oggetti stelle 735 sono resi sullo schermo, la collezione costellazioni ha 88 costellazioni e insieme systemBodies ha il sole e i sette pianeti, escludendo la terra.

Come ogni altra classe che deriva da CelestialBody, la classe Constellation imposta una proprietà EquatorialCoordinate, ma questo è esclusivamente per scopi di posizionamento il nome della costellazione. Tale posizione è calcolata da ogni istanza costellazione prendendo una media delle stelle collegate che compongono la costellazione.

Le linee di connessione si erano piuttosto difficile. Ogni oggetto della costellazione ha una collezione di oggetti di connettori, ognuno dei quali fa riferimento a una coppia di stelle nella costellazione. Ma questi oggetti connettore provengono dal file originale Constellations.xml e fanno riferimento alla coppia di stelle connesse con i numeri di ID. Per accelerare il disegno, il programma passa parte del processo di inizializzazione che completa ogni coppia di numeri ID con un oggetto StarConnector, che è una coppia di oggetti reali Star. Così, il programma può disegnare le linee connettore facendo riferimento a Proprietà ScreenX e ScreenY degli oggetti stelle effettivi.

Figura 5 Mostra la porzione del metodo Draw che rende i nomi di costellazioni, le linee di collegamento e le stelle stesse.

Figura 5 il metodo Draw per eseguire il rendering di costellazioni e stelle

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);
}

Anche se programmi come AstroPhone forniscono una guida utile a stelle e pianeti, nulla si avvicina l'esperienza di guardare effettivamente a loro nella vita reale. Forse come persone acquisire maggiori conoscenze con l'aiuto di programmi come questo, ancora una volta si svilupperà un'intima familiarità con il cielo notturno.

Charles Petzold è un collaboratore di lunga data di MSDN Magazine e attualmente sta aggiornando il suo classico libro "Programming Windows" (Microsoft Press, 1998), di Windows 8. Il suo sito Web è charlespetzold.com.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Donn Morse