Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Silverlight : Dessiner des horloges, un peu de trigonométrie !

Tout le monde sait faire un cercle, enfin une Ellipse particulière sous Silverlight ayant une hauteur et une largeur identiques. En revanche placer les marques des minutes ou placer correctement le texte des heures dans le cadran n'est pas toujours évident.

Si on tente de le faire "à la main", et même sous Blend, c'est une véritable galère (imaginez 60 petites ellipses pour les secondes à répartir soigneusement, sans parler d'un éventuel changement de dimension qui mettrait tout par terre !).

La seule solution raisonnable passe ici forcément par code. Mais malgré la croyance populaire tous les informaticiens ne sont pas forcément des "bêtes" en math ! On peut être un expert en SQL sans se rappeler ses cours de trigonométrie et on peut développer toute une architecture multithreadée sans même savoir ce qu'est un Groupe de Lie. Mais parfois ce genre de connaissance peut manquer notamment dès qu'on aborde le traitement d'image ou de dessin.

[silverlight:source=/SLSamples/ClockHours/ClockHours.xap;width=360;height=222]

Le but du jeu est donc ici de répartir harmonieusement des objets sur un cercle. Dans un cas il s'agit de texte (les heures) dans l'autre des cercles (les dots). Mais avant de regarder le code, rappelons quelques points mathématiques :

L'unité Math fonctionne en radians c'est à dire qu'un cercle vaut 2 Pi (donc deux fois 3.1415926...). C'est bête parce qu'en général un humain normalement consituté raisonne plutôt en degrés, ce qui est plus facile à se représenter mentalement.

 

 

Comme on peut le remarquer en radian le 0 se trouve au milieu à droite du cercle et non pas en haut à midi comme on pourrait s'y attendre. Du coup, comme les fonctions mathématiques de .NET marchent en radians si on raisonne en degrés il faudra penser à cette petite spécifité lors de la conversion. Par exemple, la place de "1 heure" sur une horloge se situe à 300 degrés et non pas à 30° (1 pas de 360 divisé par 12).

Le code ci-dessous permet d'écrire les heures dans l'exemple live Silverlight plus haut dans ce billet :

private void writeHours(int radius, int offsetx, int offsety, Canvas parent, double fontsize, Color color)
        {
            var h = 1;
            for (var angle=300;angle<=630;angle+=30)
            {
                var t = new TextBlock {
                        Foreground=new SolidColorBrush(color), 
                        Text=h.ToString(),
                        FontSize = fontsize};
                h++;
                t.SetValue(Canvas.LeftProperty,(radius * Math.Cos(DegreetoRadian(angle))) + offsetx);
                t.SetValue(Canvas.TopProperty,(radius * Math.Sin(DegreetoRadian(angle))) + offsety);
                parent.Children.Add(t);
            }
        }

Les paramètres sont les suivants :

  • radius : rayon du cercle virtuel sur lequel les heures sont posées
  • offsetx et offsety : positionnement du centre du cercle dans le canvas parent, sachant que le 0,0 se trouve en haut à gauche.
  • parent : le Canvas parent
  • fontSize : taille de la fonte
  • color : la couleur de la fonte

Pour dessiner les dots on utilise le même principe (sans s'encombrer des détails du point de départ décalé puisque toutes les dots sont identiques).

Le code n'est pas optimal et on peut certainement faire mieux, mais cela vous donne un point de départ ... Pour compléter le tout, vous pouvez télécharger le projet : ClockHours.zip (61,42 kb)

Stay Tuned !

blog comments powered by Disqus