Dessiner un croissant de lune

MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 - 21 sept. 2018 à 09:44
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 - 23 sept. 2018 à 13:41
Bonjour,

Je me suis attaqué à une carte du ciel, après avoir développé les routines de calcul pour déterminer l’azimut et la hauteur de plus de 1000 étoiles, du soleil, de la lune et des sept autres planètes.

Tout va bien, la carte est nickel, sauf que... je me suis mis en tête de dessiner la lune dans son état réel, et non toute ronde.

J'ai donc à dessiner un croissant de lune, sans détruire le fond de carte sur lequel sont déjà placés les étoiles et le quadrillage des coordonnées, et là je sèche.

La partie sombre de la lune n'a pas besoin d'être transparente, au contraire puisqu'elle masque les étoiles qui sont derrière.

Je pense utiliser un bitmap spécifique à la lune, puis à recopier ce bitmap sur la carte.

Le problème se situe donc au tracé de ce bitmap : il faut pouvoir représenter les différents phases de la lune.

Pour le premier et le dernier quartiers, la lune est un demi-cercle. Facile. Pour la nouvelle lune et la pleine lune, encore plus facile, c'est un cercle.

Mais pour les phases intermédiaires, c'est beaucoup plus compliqué. J'ai essayé le recouvrement d'ellipses, mais cela ne va pas. il faut que l'ellipse de recouvrement ait un diamètre variable, depuis l'infini (quartier) jusqu'au diamètre du cercle visible (arrivée à nouvelle ou pleine lune). De plus, l’ellipse de recouvrement doit être oblique pour que la partie visible soit orientée vers le soleil. Je cale.

Quelqu'un aurait-il un algorithme à proposer ? ou un lien traitant du sujet ? J'ai beaucoup cherché mais pas trouvé.

PS : ne me dites pas d'utiliser des images de la lune à différentes phases, j'y ai déjà pensé et ce n'est pas ce que je cherche à faire.
A voir également:

7 réponses

Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
21 sept. 2018 à 12:15
Bonjour,
Un principe que je sais possible, mais que je n’ai jamais utilisé.
Tu crées un contrôle utilisateur rond noir.
Sur ce controle, tu dessines une forme blanche.
Demande à Vb95 c’est le genre de truc qu’il sait faire.
0
MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 2
21 sept. 2018 à 12:28
Merci, mais je n'ai pas de problème pour dessiner des formes.
Le problème, c'est de les dessiner par code, dynamiquement en fonction de l'angle entre le soleil et la lune (ce qui donne la phase de la lune), et de la différence de hauteur (ce qui donne l'orientation du croissant).

J'ai ces deux valeurs. Le problème, c'est de dessiner la forme (blanche ou noire, selon la couleur du cercle dont on part), qui est très complexe pour les croissants en fonction de la phase de la lune.

Je crois que finalement je vais me résoudre à l'intégration de bitmaps. J'ai des images pour chaque phase. Reste le pivotement du bitmap, que je ne sais pas encore faire. Je pense que ce n'est pas sorcier, je vais chercher sur le net.
0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 656
21 sept. 2018 à 13:30
Si tu as le fond rond noir, tu n’as que le blanc à gérer.
Attends que Vb fasse un tour, je pense qu’il sait comment faire, en winform.
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
21 sept. 2018 à 19:18
bonjour à vous deux !
J'ai bien reçu ton message Whismeril ! Merci
Pour MGD Software : tout d'abord il faut que je comprenne bien les phases de la lune pour ne pas me tromper !
Et pour faire bien une petite image :



1) En partant en haut à gauche on est à la nouvelle lune : rond noir ( le blanc est à 0% du cercle noir )
2) Ensuite le croissant blanc apparait à droite et va de 0% à 100% ( 100% est la pleine lune) . il faut noter que le sens du croissant change après 50% ( le premier quartier )
3) En bas à gauche nous sommes à la pleine lune
4) Ensuite le "croissant" noir apparait à droite et va de 0% à 100% ( 100% est la nouvelle lune) . il faut noter que le sens du croissant change après 50% ( le dernier quartier )

donc l'algorithme se divise en 2 parties en inversant les couleurs
1) de la nouvelle lune à la pleine lune
2) de la pleine lune à la nouvelle lune
Dans ces 2 parties lorsque l'on atteint 50% ( un quartier) on inverse la sens de l'ellipse

Me reste plus qu'à réfléchir à la façon de coder cela si mon raisonnement est correct
J'aurais besoin que tu me dises quels sont les angles entre le soleil et la lune pour les phases principales ( nouvelle lune, premier quartier, pleine lune et dernier quartier) pour bâtir une ébauche de code

Le principe de ce code est l'utilisation d'un contrôle utilisateur à qui on enverra l'angle soleil- Lune et la différence de hauteur et celui-ci renverra directement un Bitmap directement exploitable
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 2
Modifié le 22 sept. 2018 à 11:20
Bonjour VB95 et merci pour la réponse.

Le principe, c'est bon. Voici des photos pour mieux visualiser les phases (ou plutôt "l'age") de la lune


Pour le moment j'ai extrait chaque partie de l'image et utilisé ces bitmaps dans mon programme, mais comme j'ai dit ce n'est pas ce que je souhaite faire.

"L'age" de la lune est normalement déterminé par sa position relative par rapport au soleil et l'angle sous lequel on la voit. Pour simplifier les calculs j'utilise simplement la différence entre l'azimut de la lune et l'azimut du soleil. C'est suffisamment réaliste et conforme à la réalité. On a donc un angle de 0 à 360°: 0 = nouvelle lune, 180° = pleine lune, 90° = premier quartier (L'angle est vu de la lune), 270° = dernier quartier, et pour les valeurs intermédiaires un croissant proportionnel (c'est là que ça coince).

Pour l'orientation du croissant, c'est un peu plus compliqué. La partie éclairée est toujours face au soleil. Comme je trace la carte du ciel en mode rectangulaire sur 180° (par exemple Est-Ouest = 100%, Horizon-zénith = 100%, pas de correction d'aspect en fonction de la latitude), j'ai un X et un Y pour la lune et le soleil.
La différence des X divisée par la différence des Y me donne la tangente de l'angle lune-soleil. Il faut donc orienter la partie convexe du croissant dans cette direction. Pour être plus clair, si le soleil est à droite et plus bas que la lune, le croissant devra avoir cet aspect :


Il y a donc simplement 2 paramètres pour le dessin : La différence d'azimut lune-soleil 0-360° (ou 0-2PI) pour l'âge, et l'angle relatif d'affichage (ou DeltaX et DeltaY) pour l'orientation.

Le résultat peut être un objet Bitmap pour pouvoir l'écrire sur la carte avec les autres objets, ou simplement des lignes de code utilisant la bibliothèque Graphics du framework .Net.
Dans le cas d'un bitmap, pas de problème pour l'orientation, actuellement j'oriente les images identiques à celle ci-dessus face au soleil par code (C#).

Bon courage et merci de te pencher sur mon problème.

MGD

PS : J'ai réalisé il y a quelque temps un ébauche du même programme sur le web en JavaScript, mais sans les planètes (ça viendra peut-être si je viens à bout de celui en C#). Si tu veux une idée de ce que cela donne, consulte le lien suivant et clique sur le bouton "Carte des étoiles". Attention, c'est très long (plusieurs minutes) et il faut dire plusieurs fois au navigateur de continuer.
http://public.mgdsoft.fr/astrocalc/astrocalc.php
Le programme en C# met moins de 10ms pour faire la même chose...
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
22 sept. 2018 à 15:35
Bonjour MGD Software
J'ai déposé un code à ton intention : https://codes-sources.commentcamarche.net/source/102798-phases-lunaises-de-0-a-360
La lune est visualisée sur 2 PictureBox de taille différente et ces Picturebox ont leurs propriétés sur StrecthImage ( cela signifie qu'elles adaptent la taille du Bitmap à leur propre taille .
tu verras que ma "pleine lune" se positionne sur 180 ° . Un label affiche l'angle selon tes critères ( 0 = nouvelle lune, 90 = premier quartier, etc.....
Le projet crée l'animation des phases par pas d'angle de 1°
J'attends ta réponse pour voir si cela peut t'aider à trouver une solution .
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169 > vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024
Modifié le 22 sept. 2018 à 18:00
J'ai modifié le code pour n'avoir qu'une seule Picturebox dont la taille est paramétrable .
ATTENTION : les 2 dimensions largeur et hauteur de la PictureBox doivent être de la même dimension sinon tous les calculs sont faussés
Je n'ai pas traité l'inclinaison du croissant de lune : j'attends ton retour pour voir la suite
La valeur 1.7222222 dans le code est le rapport entre la taille de la PictureBox et la taille de la représentation de la lune : c'est grâce à lui que la PictureBox a sa taille paramétrable .
A ++
0
MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 2
22 sept. 2018 à 18:41
Superbe !

Pour ma part, je n'aurai pas besoin du PictureBox, puisque j'utilise directement le bitmap avec un DrawImage sur le reste de ma carte.
Par contre, le bitmap BitmapLune va remplacer idéalement les photos que j'utilise actuellement.

Après ça, il faut faire pivoter le bitmap pour qu'il soit orienté vers le soleil, mais ça, ça fonctionne déjà avec les photos.

Je pense que je vais pouvoir finir mon programme...
À ce que j'ai pu voir, les parties blanche et noire sont tracées quasiment point à point. C'est un peu lent, mais comme il n'y a qu'un seul dessin à faire lors de l'affichage de la carte, ça devrait aller. Cependant, cela me paraît un peu incompatible avec la version en JavaScript, qui est déjà trop lente. Tant pis.

Par contre, j'ai une interrogation concernant la taille du bitmap en pixels. Il est indiqué que la valeur donnée est faite pour que le bitmap rentre dans le PictureBox. Je n'ai pas ce problème, puisque je ne vais pas utiliser ce dernier. Mais je souhaiterais savoir le rapport entre Param1, Param2 et la taille finale du bitmap. J'avoue que je n'ai pas tout compris dans le calcul des points pB et pW. Cela ressemble au calcul des coordonnées des points d'une ellipse avec foyers, grand axe et petit axe, mais mon dernier cours de géométrie date de plus de 55 ans... Pour tout comprendre, il va falloir que je retrouve mes bouquins de math. Si tu te sens une âme de prof et que tu as un peu de temps, un petit tuto mathématique et procédural expliquant le calcul serait le bienvenu. J'ai horreur d'utiliser du code que je ne comprends pas.

Merci pour ce beau boulot.
0
MGD Software Messages postés 186 Date d'inscription vendredi 1 septembre 2006 Statut Membre Dernière intervention 23 avril 2022 2
Modifié le 22 sept. 2018 à 19:18
Juste un détail : La nouvelle lune correspond à un angle de 0° et non 180°, puisque le soleil est juste derrière elle, et donc que le côté visible est noir.
La pleine lune correspond à un angle de 180°, puisque la lune est à l'opposé du soleil, et donc que sa face visible est entièrement éclairée - sauf bien sûr en cas d'éclipse de lune ;-).

Bien sûr, je pourrais écrire dans la ligne 57 :
Phase = ((Angle + 180) % 360) / 360
, mais il y a sûrement mieux à faire.
Un conseil ?

Edit : Je n'ai peut-être pas compris le code : on part avec un angle de 180° "pour la nouvelle lune selon le commentaire de la ligne précédente. Quid ?
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
22 sept. 2018 à 19:13
Bonsoir !
Pour le projet je me suis inspiré d'un projet trouvé sur le Net dont j'ai repris le principe et que j'ai adapté pour avoir les angles de 0° à 360 °
Celui-ci selon la date du jour et donc l'âge de la lune nous donnait le dessin de la lune sur un cycle de 28 jours ( le temps entre 2 nouvelles lunes ) donc 28 images successives alors que là j'ai 360 images de 0° à 360° .
Le plus dur fut de trouver le moyen que l'image soit toujours correcte quelle que soit la taille de la PictureBox et c'est là qu'intervient le 1,722222 qui est le rapport entre la taille de la PictureBox et l'image de la lune dans la Picturebox .
Pour moi aussi les Maths sont très loin ( j'ai 68 ans bientôt ) mais j'ai voulu m'intéresser au sujet par défi et aussi parce que Whismeril m'a contacté pour voir ton problème ! De plus je traine aussi souvent sur CodeProject et j'avais un vague souvenir d'une source qui traitait de ce sujet . Donc j'ai cherché et j'ai retrouvé la source .
La valeur dans la boucle for de la procédure DessineLune peut être abaissée ( elle était de 45 d'origine ) ce qui améliorerait le rapidité mais cela est assez insignifiant si l'affichage ne se fait qu'une seule fois .
Pour l'histoire de 0 ° et 180 ° pour la nouvelle lune je me demande si en inversant les couleurs noir et blanc cela ne résoudrait pas le problème : ainsi on aurait la nouvelle lune à 0 °
Je teste ce dernier point et te dirait ce qu'il en est !
0
vb95 Messages postés 3472 Date d'inscription samedi 11 janvier 2014 Statut Contributeur Dernière intervention 13 avril 2024 169
23 sept. 2018 à 13:41
bonjour MGD software
J'ai encore modifié le projet avec un Trackbar pour modifier la taille du Bitmap final
Je me suis rendu compte que la valeur dans la boucle for avait une influence sur la taille de la lune elle-même et donc cette valeur est maintenant aussi associé au 1,722222222 qui est le rapport entre la taille du bitmap et la taille de la lune elle-même .
Je continue mes investigations pour comprendre l'algorithme : je suis comme toi ( j'ai bien comprendre et non utilser simplement du code )
Bonne journée à toi
0
Rejoignez-nous