Cet article a fait l'objet d'une traduction automatique.
Saisie tactile et accès
Exploration des coordonnées sphériques sur Windows Phone
Télécharger l'exemple de code
Depuis que je fis connaissance avec le détecteur de mouvement Windows Phone 7.1, j'ai connu exactement ce que je voulais faire avec lui : ressusciter c# astronomie positionnel code que j'ai écrit il y a environ cinq ans et d'un grillage à avec la logique de détection de mouvement dans un programme de Windows Phone.Un tel programme me permettraient de pointer le téléphone à un endroit dans le ciel nocturne de montrer les planètes et les constellations qui s'y trouve.
Ce programme — avec le ridicule nom AstroPhone — est entrée dans le prochain épisode de cette colonne.Pendant ce temps, certaines bases conceptuelles, mathématiques et programmation sont nécessaire.
Comme j'ai parlé dans les colonnes précédentes, le capteur de mouvement consolide l'apport de la boussole, accéléromètre, gyroscope et de GPS et calcule (entre autres) une matrice de rotation 3D qui décrit l'orientation du téléphone dans l'espace.Il convient d'appliquer cette matrice à un vecteur 3D par rapport au repère du téléphone.Ce vecteur transformé indique un emplacement sur la sphère céleste conceptuel.Un emplacement sur cette sphère est une coordonnée horizontale, qui consiste en une altitude — un angle au-dessus ou au-dessous de horizon le spectateur — et un azimut, qui est essentiellement une direction de la boussole.
Coordonnées horizontales sont semblables aux coordonnées géographiques familiers qui identifient une position sur la surface de la terre.L'altitude au-dessus ou en dessous d'horizon de l'observateur est analogue à une latitude au-dessus ou en dessous l'Équateur terrestre.L'azimut indiquant une boussole direction autour d'horizon de l'observateur est analogue à la longitude à l'Équateur terrestre.Comme vous le verrez, tous les types de coordonnées sphériques sont fondamentalement les mêmes, différant plus cruciale de l'avion qui sépare l'hémisphère supérieur inférieur.
Aplatissement de la sphère
Dans la colonne du mois dernier (msdn.microsoft.com/magazine/jj553520), j'ai montré comment utiliser les coordonnées horizontales d'analyser les grandes photographies et autres images en changeant l'orientation du téléphone dans l'espace.Cependant, ce programme « triché » un peu en ignorant tout simplement la vraie nature des coordonnées sphériques.Il refuse de reconnaître le fait que les cercles de latitude deviennent de plus en plus petits vers le haut et le bas de la sphère céleste, et par conséquent, les degrés d'azimut deviennent plus en plus comprimées.
Un programme qui offre une visualisation simulation du ciel nocturne tout simplement ne pas prendre ces raccourcis.Elle doit trouver une façon algorithmique d'une région de la sphère céleste de la carte à l'écran plat du téléphone.Bien sûr, l'aplatissement de la sphère a été un problème rencontré par les cartographes pendant des siècles.On ne peut pas faire sans distorsion, mais l'objectif est de réduire au minimum les distorsions.
La figure 1 montre une sphère décorée avec des lignes de l'altitude et l'azimut chaque 15 °.D'un point de vue au Centre de l'intérieur de la sphère, le point rouge représente un point qui vous écoute ou pointant sur votre téléphone.L'altitude de ce point particulier est de 25 °.L'azimut dépend d'où vous commencez à compter et dans quelle direction.
Figure 1 Point (en rouge) sur une sphère céleste
Appelons ce point le « Centre d'avis » parce que c'est le point qui sera mappé au Centre de l'écran du téléphone.Quelles lignes sur la sphère correspondent aux bords de l'écran ?
Il est tentant de supposer que les bords de l'écran du téléphone correspondra à des lignes de l'altitude et l'azimut.Mais qui semble seulement raisonnable aux endroits près de l'horizon.Le concept commence à décomposer comme le Centre de la vue obtient plus loin de l'horizon et s'effondre complètement lorsque que vous visionnez directement vers le haut ou vers le bas aux pôles.
Au lieu de cela, Let's construction orthogonales » grands cercles » au Centre de la vue, comme le montre Figure 2.
Figure 2 grands cercles orthogonaux, traversant le Centre de la vue
Grands cercles sont un concept important en géométrie sphérique.Un grand cercle est un cercle en deux dimensions dans l'espace 3D, partage le même centre et rayon de la sphère elle-même.Grands cercles sur la sphère sont analogues aux lignes droites sur un plan parce qu'elles représentent la distance la plus courte entre deux points.Azimut (et les longitudes) est des grands cercles.Lignes d'altitude (et latitude) ne le sont pas ; ils sont plutôt « petits cercles, « à l'exception du cercle qui divise la sphère en deux — l'horizon (ou l'Équateur).
Le grand cercle rouge en Figure 2 passe par les deux pôles et qui est tout simplement une ligne d'azimut.Le grand cercle bleu traverse l'horizon à azimuts 90 ° de l'azimut du Centre de la vue.
Un rectangle autour de ce centre de la vue sera mappé sur l'écran du téléphone.D'un point de vue conceptuel, ce rectangle peut être une grille de grands cercles.Allons construire deux plus grands cercles en bleu qui traversent l'horizon au même endroit que le premier.Et il faut construire deux plus rouges grands cercles qui partagent également deux points avec le premier.Le résultat est reproduit à la figure 3.Les points communs des grands cercles rouges ont le même azimut ainsi le Centre de la vue (ou l'azimut 180 °), mais l'altitude est compensée par 90 °.
La figure 3 plus grands cercles de créer une zone rectangulaire
Les autres grands cercles définissent les contours d'un rectangle qui correspond à l'écran en mode portrait du téléphone, avec une largeur d'environ 19 ° d'arc et d'une hauteur de 32 ° d'arc.Si vous supposer que l'écran du téléphone est environ 2 pouces de large et de 3,33 pouces de haut, ces degrés d'arc sont appropriés lorsque l'écran du téléphone est tenu environ 6 pouces de votre visage.L'écran du téléphone est 480 pixels de large et de 800 pixels de haut, donc ces chiffres impliquent également 25 pixels par degré d'arc.
Lors de la mise en œuvre de ce système de projection dans un algorithme, vous devez travailler vers l'arrière : Considérer les deux points partagées par les trois cercles de grand bleus, un axe et les deux partagé par les trois cercles rouges de grands comme un autre axe.Avec le vecteur vers le Centre de la vue, elles forment un système de coordonnées orthonormées.
Algèbre vectorielle permet de dériver des compensations d'angle de toute autre coordonnée du Centre de la vue, comme illustré dans la classe HorizontalCoordinateProjection dans Figure 4.La classe possède une méthode pour définir le Centre de la vue et une autre méthode pour obtenir des compensations de l'angle de la coordonnée horizontale de n'importe quel autre objet par rapport à ce centre de la vue.
Figure 4 la classe 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;
}
}
Les angles obtenus par la méthode GetAngleOffsets pour déterminer où cet objet doit être positionné sur l'écran du téléphone, doivent être multipliée par une constante que vous sélectionnez pour le nombre de pixels par degré d'arc. Je l'ai déjà indiqué que cette constante doit être égal à 25 lorsque le téléphone est tenu de 6 pouces de votre visage, mais vous pouvez aller avec quelque chose de plus faible pour fournir une vue plus large.
Affichage de la sphère de l'intérieur
Le programme ViewHorizontalCoordinates définit la constante PIXELS_PER_DEGREE à 15 pour afficher les coordonnées horizontales à l'intérieur qui, comme le montre la recherche Figure 5. Ce point de vue particulier se produit lorsque le téléphone pointe un peu au sud est, un peu au-dessus de l'horizon.
Figure 5 le programme ViewHorizontalCoordinates
Pour chaque événement de CurrentValueChanged déclenché par le capteur de mouvement, le gestionnaire d'événement commence par obtenir la matrice de rotation qui indique comment la terre est orientée par rapport au téléphone. Elle qui convertit une valeur de HorizontalCoordinate et définit le Centre de la vue dans un objet HorizontalCoordinateProjection créé précédemment :
Microsoft.Xna.Framework.Matrix matrix =
args.SensorReading.Attitude.RotationMatrix;
HorizontalCoordinate viewCenter =
HorizontalCoordinate.FromMotionMatrix(matrix);
coordinateProjection.SetViewCenter(viewCenter);
rotate.Angle = -viewCenter.Tilt;
L'objet en rotation est un RotateTransform appliqué à la toile entière. Ensuite, le gestionnaire d'événements implémente plusieurs boucles impliquant des valeurs de l'altitude et l'azimut en incréments de 15 °. La première fois que l'événement CurrentValueChanged se déclenche, le gestionnaire d'événements crée tous les éléments TextBlock et de ligne nécessaires et les ajoute à la toile. Les fois deuxième et ultérieures, le gestionnaire d'événements simplement accède à la ligne et TextBlock éléments existants déjà dans la toile et définit de nouveaux points.
Chaque valeur de HorizontalCoordinate doit être convertie en une coordonnée d'écran. C'est l'emploi de la méthode CalculateScreenPoint dans Figure 6, qui appelle la méthode GetAngleOffsets dans HorizontalCoordinateProjection et multiplie les angles par la constante PIXELS_PER_DEGREE.
La figure 6, calcul d'un Point de l'écran d'une coordonnée horizontale
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);
}
La méthode GetAngleOffsets retourne toujours des angles dans la gamme de-180 ° à 180 °. Parfois les lignes chevauchent ces limites et cela crée un problème multidisciplinaire. Par exemple, une ligne peut (en théorie) étendre de-175 ° à 175 °. Cette ligne devrait être seulement 10 ° de longueur, mais la longueur calculée serait 380 ° ! La logique de CalculateScreenPoint impliquant NaN (« pas un nombre) résout ce problème par le repérage de tous les points d'angle compensations de moins de-90 ° ou supérieure à 90 °, ce qui est hors de la portée de l'écran.
Je voulais que les étiquettes de texte indiquant les angles de l'altitude pour être visible quel que soit l'azimut, et celles montrant les points cardinaux pour être visible, peu importe comment élevé ou faible vous pointez le téléphone. Les étiquettes d'altitude sont affichés avec un point d'écran calculé à partir de l'azimut de centre du point de vue, et les étiquettes de la boussoles sont affichés avec un point d'écran calculé à partir de l'altitude du Centre de vue, avec un petit ajustement afin qu'ils ne cluster tous ensemble lorsque vous pointez le téléphone directement vers le haut ou vers le bas. Cette petite astuce permet de conserver les étiquettes à l'intérieur de l'écran, une rotation peut-être un peu loin du Centre.
Un commutateur à XNA
Comme je travaillais sur les programmes pour cette colonne en collaboration avec AstroPhone pour le mois prochain, j'ai commencé à remarquer certains problèmes de performances. Le programme de ViewHorizontalCoordinates ne peut gérer qu'environ 10 images par seconde sur mon téléphone de développement, et le problème semble être plus dans le système de disposition Silverlight plutôt que dans mon code.
Avec une certaine réticence, j'ai décidé que les programmes restants prenne pour cible la Windows Phone XNA framework plutôt que Silverlight. C'est le cas pour le projet ViewThreeCoordinates, qui est similaire à ViewHorizontalCoordinates, mais écrit pour XNA plutôt que Silverlight.
Aperçu de la bibliothèque
Le projet ViewThreeCoordinates révèle également certaines des stratégies que je vais utiliser pour le programme d'astronomie tous azimuts. Il fait usage d'une partie d'une bibliothèque plus grande appelée Petzold.Astronomy. Dans la construction de cette bibliothèque, ma référence principale a été la deuxième édition de la classique « Astronomical Algorithms » par Jean Meeus (Willmann-Bell, 1998).
Astronomie de position nécessite beaucoup de trigonométrie. Dans la bibliothèque de Petzold.Astronomy, j'essaie d'éviter la confusion et les conversions entre les degrés et radians en mettant en œuvre une struct nommé Angle. Vous pouvez créer une valeur d'Angle d'un degré ou un radian en utilisant les méthodes statiques de FromDegree ou FromRadian et obtenir les degrés ou radians sort, mais il n'est pas souvent nécessaire parce que l'Angle implémente également toutes les fonctions trigonométriques comme propriétés.
Par exemple, si vous avez une valeur d'Angle nommée myAngle, vous pouvez obtenir le cosinus de l'angle comme suit :
double x = myAngle.Cosine;
Si vous pensez que des sinus, cosinus et tangentes comme « propriétés » des angles, cela prend tout son sens. Mais, remarquez comment la propriété de cosinus est mis en œuvre :
public double Cosine
{
get { return Math.Cos(radians); }
set { radians = Math.Acos(value); }
}
L'accesseur set est la fonction cosinus inverse, ce qui signifie que vous pouvez définir une valeur d'Angle existante sur le cosinus d'un nombre en utilisant une instruction comme celle-ci :
myAngle.Cosine = x;
Le seul endroit où ce processus n'a pas bien fonctionné a été mise en œuvre de la méthode Atan2 essentielle. Je l'ai fait avec une méthode statique qui crée une valeur d'Angle :
public static Angle ArcTangent(double y, double x)
{
return Angle.FromRadians(Math.Atan2(y, x));
}
Coordonnées équatoriales
Le programme ViewThreeCoordinates affiche les coordonnées horizontales en vert, plus deux autres systèmes de coordonnées très utiles en astronomie de position : coordonnées équatoriales en bleu et écliptique coordonnées en rouge. La figure 7montre un affichage typique avec le téléphone pointant vers le Nord et à une altitude de 25 °. (Oui, je sais, mais l'écran est encombrée, vous pouvez tapoter l'écran pour afficher seulement un ou deux ensembles de coordonnées.)
Figure 7 l'affichage ViewThreeCoordinates
Comme la Terre tourne sur son axe et autour du soleil, Équateur terrestre reste pratiquement dans le même plan. Le plan de l'Équateur terrestre est le plan fondamental associé aux coordonnées équatoriales. Les coordonnées équatoriales sont constitués d'une déclinaison — positives au-dessus de l'Équateur et négatives ci-dessous — et une ascension droite aller autour de l'Équateur. L'ascension droite est généralement spécifiée en heures plutôt que de degrés, où chaque heure est l'équivalent de 15 °.
Bien sûr, les coordonnées géographiques (latitude et longitude) reposent aussi sur l'Équateur terrestre, mais les coordonnées géographiques faire pivoter avec la terre, tandis que les coordonnées équatoriales sont fixes par rapport au reste de l'univers et semblent donc tourner comme la Terre tourne sur son axe. Les positions des étoiles sont spécifiées en coordonnées équatoriales, et ils ne changent pas beaucoup avec le passage du temps.
ViewThreeCoordinates affiche une grille de coordonnées équatoriales en les convertissant en coordonnées horizontales. Cette conversion dépend de la localisation géographique de l'observateur (longitude et latitude) et à l'heure actuelle et est implémentée dans la structure HorizontalCoordinate.
Cependant, une conversion très rugueuse de l'ascension droite azimut est possible : À une heure locale de minuit à l'équinoxe de printemps (20 mars ou environs), 0 heures, ascension droite est au nord (0 ° d'azimut). La brillante étoile Arcturus a une ascension droite d'environ 14 heures, sur cette date à ce moment-là, vous aurez besoin de balancer vers l'ouest par 210 ° (ou vers l'est de 150 °) pour le voir. Ou, vous pouvez simplement attendre deux heures jusqu'au 02 et Arcturus seront dus au sud.
Vous pouvez calculer l'angle horaire local d'une étoile en soustrayant son ascension droite du nombre d'heures depuis l'heure locale de minuit. Convertir en multipliant par 15 degrés et ajouter le nombre de jours depuis mars 21 et que l'azimut de l'étoile mesurée vers l'est, du Nord.
Si vous exécutez ViewThreeCoordinates et maintenez le téléphone jusqu'à la nuit, le pôle équatorial du Nord (visible en haut de la Figure 7) correspond à l'emplacement de Polaris, l'étoile du Nord, qui a une déclinaison de très près de 90 ° et coïncide donc avec le vecteur de l'axe terrestre. Notez comment la ligne d'azimut du Nord croise ce pôle.
Coordonnées écliptiques
Les orbites de toutes les planètes du système solaire sont à peu près dans le même plan. Ce plan est appelé plan de l'écliptique, et c'est la base de coordonnées écliptique (également connu sous le nom de celestial coordonnées), qui sont affichées par ViewThreeCoordinates en rouge. Une coordonnées écliptique se compose d'une longitude écliptique et latitude écliptique.
Coordonnées écliptiques sont principalement utilisées lors du calcul de la position des planètes, le soleil et la Lune. Parce que le soleil et les planètes se trouvent dans à peu près le même plan, la latitude écliptique de ces objets est habituellement proche de zéro. Plan de l'écliptique est affiché avec une ligne rouge épaisse dans ViewThreeCoordinates. Si vous maintenez le téléphone à la journée ou les planètes, le soleil et le ciel nocturne devraient coïncider avec cette ligne.
Coordonnées équatoriales et coordonnées écliptiques diffèrent uniquement par suite de l'inclinaison de la terre d'environ 23 ° par rapport à l'écliptique. Une coordonnée équatoriale d'ascension droite et 0 °, la déclinaison de 0 heures est identique à une coordonnée équatoriale de 0 ° de latitude et de longitude 0 °, et les deux systèmes coïncident également à 180 °.
L'équinoxe de printemps, le soleil a une longitude écliptique de 0 °. Cette longitude augmente d'environ 1 ° par jour au cours de l'année. Par conséquent, la longitude écliptique du soleil en degrés est approximativement égale au nombre de jours depuis le 21 mars.
Longitude écliptique est souvent étiquetés avec les signes du zodiaque, à commencer par Aries pour 0 °-30 °, Taurus à 30 °-60 ° pour Gemini pour 60 °-90 ° et ainsi de suite par le biais de poissons pour 330 °-360 °. Je l'ai aussi fait dans ViewThreeCoordinates. Ces signes du zodiaque sont les constellations qui se trouvent environ à ces longitudes écliptiques avec latitudes de l'écliptique dans le voisinage de zéro. Ainsi, le soleil est « bélier » (qui signifie que le bélier est au-delà du soleil) au cours du mois à partir du 21 mars.
Assez de théorie. L'apparition prochaine de cette colonne, les lignes de la grille des systèmes de coordonnées sphériques seront remplacés par le soleil, lune, planètes, étoiles et les constellations.
Charles Petzold est un contributeur de longue date de MSDN Magazine et est actuellement à jour son livre classique « Programmation Windows » (Microsoft Press, 1998) pour Windows 8. Son site Web est charlespetzold.com.
Merci à l'expert technique suivant d'avoir relu cet article : Donn Morse