VB: trigonométrie

Résolu/Fermé
arscy - Modifié le 19 oct. 2020 à 22:55
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 - 27 oct. 2020 à 22:33
Bonsoir,

Je suis en train de tourner en bourrique avec VB.
Je suis face à un exercice de dessin, et je suis infichu de réussir à créer ne serait-ce que le début de ma figure géométrique.

Le concept pourtant est relativement simple:
dessiner un segment à des coordonnées (x, y, xPrim, yPrim)
lui infliger un raccourcissement par un facteur k
puis dessiner le nouveau segment au point de coordonnées initiales (xPrim, yPrim) avec une rotation de teta degrés (et répéter ce processus jusqu'à ce que la Terre s'effondre mais pas tout à fait).

Le "détail" qui, pêche concerne d'après moi la manipulation des fonctions cos et sin.
Sur calculatrice j'obtiens un résultat cohérent pour mes futures coordonnées.
Sur cet algorithme en revanche... c'est l'équivalent d'un slip un soir de gastro. Le respect des angles n'a aucune corrélation avec l'angle lui-même.
Malgré la conversion des degrés en radians, l'appel à C'thulhu et aux poupées vaudou, l'incohérence reste la référence.
J'en déduis que c'est la version VB de cos et sin que j'utilise comme un manche.

Je vous propose si vous l'acceptez, de jeter un œil sur ma progression du moment _ nb: j'ai désactivé certains fragments à cause de la faute de base et il me reste 2 paramètres à traiter (limite de la future boucle notamment).

        Dim longueur, angle, x, y, xPrim, yPrim, j As Integer
        Dim coeff, k As Double
        longueur = LengthBox.Text()                     '// valeurs utilisateur
        angle = AngleUpDown.Value()
        angle = angle * Math.PI / 180                   '//angle en RAD
        k = CoeffUpDown.Value()
        x = PictureBox1.Width / 2 - longueur / 2        '//dessin autour du centre
        y = PictureBox1.Height / 2 + longueur / 2
        xPrim = x + longueur                            '//coordonnees temporaires B du sgt [AB]
        yPrim = y
        j = 1
        coeff = 1                                       '//coeff temporaire avant boucle
        'For i = longueur To 0 Step -1
        g.DrawLine(Pens.Black, x, y, xPrim, yPrim)
        coeff = k
        longueur = longueur * coeff
        x = xPrim                                        '// coordonnees A deviennent B
        y = yPrim
        xPrim = (Math.Cos(angle) * longueur)     '// B devient C - formule trigo x = hypothenuse . cos angle
        yPrim = yPrim - (Math.Sin(angle) * longueur)     '// y = hypothenuse . sin angle
        'Next
        g.DrawLine(Pens.Black, x, y, xPrim, yPrim)
        Label1.Text = ((Math.Cos(angle) * longueur))


J'ai enlevé un compteur entre temps (j) dont le but à la base était d'incrémenter l'angle (angle = angle x j)
Mes 2 dernières lignes sont des vérifications dans l'optique "débogage".
Auriez-vous une solution pour résoudre mes équations de xPrim et yPrim qui sont définitivement fausses? et probablement le nœud du problème?
Merci d'avance pour votre temps
A voir également:
  • VB: trigonométrie
  • Vb cable - Télécharger - Audio & Musique
  • Vb - Télécharger - Langages
  • Vb editor - Télécharger - Langages
  • Vb runtime - Télécharger - Divers Utilitaires
  • Vb 2008 - Télécharger - Langages

9 réponses

Whismeril Messages postés 19021 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 14 avril 2024 927
20 oct. 2020 à 20:35
Bonsoir

ce n'est de toute façon pas un problème de développement, mais de maths.



Connaissant l'angle Alpha et la longueur L, c'est Dx et Dy que tu peux calculer.
Les coordonnées de B, ça vient après.
1
Whismeril Messages postés 19021 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 14 avril 2024 927
22 oct. 2020 à 10:30
Il faut faire par étape.
D'abord on calcule la longueur du futur segment, ce que tu as fait.
Ensuite on détermine son angle par rapport à l'horizontale (on peut aussi par rapport à la verticale, mais ça inverse les calculs), ce que tu as fait.

J'ai donc un segment de longueur L et d'angle Alpha, avec un point connu => c'est un vecteur.
Avec la trigonométrie on peut calculer les coordonnées du vecteur Dx et Dy.

cos(Alpha) = Dx / L => Dx = L * cos(Alpha)
sin(Alpha) = Dy / L => Dy = L * sin(Alpha)

Ce que tu as fait aussi.

Pour déterminer les coordonnées du point B, il faut translater les coordonnées du point A de la valeur du vecteur.

Dans ton premier code
        xPrim = (Math.Cos(angle) * longueur)     '// B devient C - formule trigo x = hypothenuse . cos angle
        yPrim = yPrim - (Math.Sin(angle) * longueur)     '// y = hypothenuse . sin angle

il n'y avait pas de translation de X.

Dans le second, je pense que c'est un problème de signe.
On a fait le calcul avec des longueurs positives donc Dx et Dy sont positifs.

Le repère que j'ai montré à son axe des X positif à droite et son axe des Y positifs vers le haut, car j'ai utilisé Géogebra (un logiciel de Maths utilisé au collège).
Dans ce cas, il faudrait effectivement ajouter Dx à xA et soustraire Dy à yA.

Mais je ne suis pas sûr dans une pictureBox le repère soit dans ce sens. Je ne code plus en winform depuis un moment et je n'ai que rarement utiliser des picturebox. Je crois me souvenir que comme pour un image, les Y sont positifs vers le bas.
Il faudrait donc ajouter Dy à yA.
1
jordane45 Messages postés 38135 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 13 avril 2024 4 647
22 oct. 2020 à 10:57
hello,
de mémoire, le point aux coordonnées 0,0 se situe dans l'angle haut gauche.
et donc, en effet, le Y est positif vers le bas.
0
Whismeril Messages postés 19021 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 14 avril 2024 927
Modifié le 23 oct. 2020 à 11:29
Bonjour

j'ai fait un essai chez moi.

J'ai d'abord écrit une méthode dont le rôle est de retourner le 2eme point en fonction du premier, de la norme du vecteur et de l'angle directeur

    ''' <summary>
    ''' Calcule le point de fin d'un segment en fonction du point de départ, de la norme et de l'angle
    ''' </summary>
    ''' <param name="Depart">Point de départ</param>
    ''' <param name="Rho">Norme</param>
    ''' <param name="Teta">Angle en radians</param>
    ''' <returns></returns>
    Private Function FinSegment(Depart As Point, Rho As Double, Teta As Double) As Point
        Dim vecteur As Size

        vecteur.Width = Convert.ToInt32(Math.Round(Rho * Math.Cos(Teta)))
        vecteur.Height = Convert.ToInt32(Math.Round(Rho * Math.Sin(Teta)))

        FinSegment = Depart + vecteur

    End Function


J'ai écrit une seconde méthode qui dessine un trait sur une Picturebox à partir des 2 extrémités
    ''' <summary>
    ''' Dessine un trait sur le pictureBox 
    ''' </summary>
    ''' <param name="Depart">Début du trait</param>
    ''' <param name="Fin">Fin du trait</param>
    ''' <param name="Pc">PictureBox à dessiner</param>
    Private Sub DessineTrait(Depart As Point, Fin As Point, Pc As PictureBox)
        Dim BMP As Bitmap = New Bitmap(Pc.Image)
        Dim G As Graphics = Graphics.FromImage(BMP)

        G.DrawLine(Pens.Black, Depart, Fin)

        Pc.Image = BMP

    End Sub


J'ai ensuite mis en musique avec 2 boucles, la première remplit une liste de points et la seconde dessine les traits à partir de la liste.

        PictureBox1.Image = New Bitmap(400, 400)
        Using graph As Graphics = Graphics.FromImage(PictureBox1.Image)
            Dim ImageSize As Rectangle = New Rectangle(0, 0, PictureBox1.Image.Width, PictureBox1.Image.Height)
            graph.FillRectangle(Brushes.White, ImageSize)
        End Using

        Dim lesPoints As New List(Of Point)
        Dim rho As Double = 80
        Dim teta As Double = 0
        Dim deltaTeta As Double = -10.0 * Math.PI / 180 'angle négatif pour que ça tourne dans le sens trigo

        lesPoints.Add(New Point(10, 380))

        For i As Integer = 0 To 4
            lesPoints.Add(FinSegment(lesPoints.Last(), rho, teta))
            rho *= 4 / 5
            teta += deltaTeta
        Next

        For i As Integer = 0 To 3
            DessineTrait(lesPoints(i), lesPoints(i + 1), PictureBox1)
        Next




1
Whismeril Messages postés 19021 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 14 avril 2024 927
23 oct. 2020 à 11:30
j'ai oublié la capture
0
Whismeril Messages postés 19021 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 14 avril 2024 927
27 oct. 2020 à 20:43
Bonsoir

mais ma frustration demeure intacte, parce que je suis convaincu que ma méthode a du sens, sauf que je suis infichu d'utiliser la formule correctement sur VB.
Donc ta méthode résout mon exercice,
mais ne répond pas à ma question initiale concernant les formules de xPrim et yPrim ^^


ben si, j'ai appliqué exactement la même chose....

        vecteur.Width = Convert.ToInt32(Math.Round(Rho * Math.Cos(Teta))) 'le décalage en X est bien le produit de la longueur par le cosinus
        vecteur.Height = Convert.ToInt32(Math.Round(Rho * Math.Sin(Teta)))'le décalage en Y est bien le produit de la longueur par le sinus

        FinSegment = Depart + vecteur 'là ça fait bien x' = x + dX et y' = y + dY, mais en une ligne puisque les objets existent, autant s'en servir


Donc juste en passant l'angle en Double je viens de faire le test pour les valeurs qui fâchent (ex: 30°), et j'ai des segments pertinents :-)
ha oui, forcément, 1 radian c'est 57.3° environ

En fait, ton problème est que tu n'as pas su/pensé débogguer correctement.
En exécutant en pas à pas et espionnant le contenu des variables, tu aurais du voir le symptôme assez rapidement.
Je te conseille ce petit tuto https://openclassrooms.com/fr/courses/1526901-apprenez-a-developper-en-c/2867766-utilisez-le-debogueur les exemples de code sont en C# mais c'est bien fait avec Visual Studio

1

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

Posez votre question
yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024 1 468
20 oct. 2020 à 14:44
bonjour,
il est préférable de déclarer le type de chaque variable.
peux-tu plutôt partager un programme plus simple qui se concentre sur ce qui ne fonctionne pas?
0
yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024 1 468
20 oct. 2020 à 14:54
quelques principes de base:
https://www.commentcamarche.net/contents/1381-debogage
0
yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024 1 468
20 oct. 2020 à 14:55
n'hésite pas, non plus, à préciser quelles sont les valeurs de tes variables, quel résultat tu obtiens, et quel résultat tu souhaites.
0
arscy > yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024
20 oct. 2020 à 16:49
ok. Je vais supprimer mon post et revenir en plus concis dans ce cas (le petit geste pour la planète)
0
Chris 94 Messages postés 50978 Date d'inscription mardi 8 janvier 2008 Statut Modérateur Dernière intervention 17 février 2023 7 321 > arscy
20 oct. 2020 à 16:54
Salut,

Heu ? Pourquoi ? Continue ici, il n'y a aucune raison de supprimer les réponses de yg_be, n'est-ce pas ?
0
Bonsoir,
Je suis d'accord avec la première partie de la phrase faute d'avoir compris à quoi fait allusion D.
Dans ma formule j'envoie pour un segment [AB] les coordonnées du point A en B,
puis les coordonnées de B en un C qui correspond à AB + un angle alpha.
C'est donc de la trigonométrie de base.
→ cos alpha = (longueur xC)/(longueur AB)
→ sin alpha = (longueur yC)/(longueur AB)
donc
longueur xC = cos alpha x longueur AB
longueur yC = sin alpha x longueur AB
Et si je n'ai pas écrit n'importe quoi, pour avoir xC et yC
il faut que j'additionne ces longueurs aux coordonnées préexistantes
soit xC= xB + cos alpha x longueur AB
yC = yB - sin alpha x longueur AB (repère inversé dans VB d'où la soustraction)

soit, dans ma formule:
xPrim = x + (Math.Cos(angle) * longueur)
 yPrim = y - (Math.Sin(angle) * longueur) 


mais ça
C'est faux.
Pourquoi?
0
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 9
22 oct. 2020 à 22:39
Comme le dit jordane45, le (0,0) se trouve dans l'angle supérieur gauche du pictureBox.
Pour ma part je souhaite une rotation dans le sens trigonométrique, donc je pense que la soustraction est la bonne idée.
Au point où j'en étais j'ai quand même tenté la version par addition, et à part avoir l'erreur dans le sens horaire, je n'ai pas de résolution de mon problème.
Quand je procède au calcul avec une calculatrice tout se tient, par contre sur VB c'est l'hécatombe. J'ai pris 2 captures d'image juste pour l'illustration, à 10° près.
nb: n'oublions pas que j'ai bloqué mon algorithme initial (pas de boucle): je suis censé avoir
2 vecteurs dessinés, reliés entre eux et différents d'un angle alpha.


angle= 20° → les deux vecteurs sont colinéaires (wtf?)


ange= 30°. Ça ressemble d'avantage à 60° mais bon...

Et entre ces deux angles j'ai droit à des longueurs "figées" (la valeur en bas de l'icône me permettait de voir la taille du vecteur ajouté histoire d'essayer de trouver d'où venait l'erreur.
Cette valeur est fixe jusqu'à des points bascule qui n'ont pas de cohérence à mes yeux :-( ex: angle 0 à 28° : le 2e vecteur est colinéaire, le suivant restera figé au même angle jusque 85°, ...).
Il y a du plomb dans ma formule que je n'arrive pas à saisir... Or mathématiquement parlant, il me semblait que c'était correct...
0
Et bien quoi qu'il en soit ta méthode fonctionne,
mais ma frustration demeure intacte, parce que je suis convaincu que ma méthode a du sens, sauf que je suis infichu d'utiliser la formule correctement sur VB.
Donc ta méthode résout mon exercice,
mais ne répond pas à ma question initiale concernant les formules de xPrim et yPrim ^^

J'ai essayé de recommencer mon système, pour comprendre ce qui partait en cacahuète.
But: dessiner un seul vecteur, avec d'emblée un angle teta
--> point de départ en (0;0);
point xPrim et yPrim correspondant aux abscisse et ordonnée du point d'arrivée du vecteur de longueur lon (qui a été soumis à un angle teta)
        Dim x, y, xPrim, yPrim, angle As Integer
        Dim k, lon As Double
        lon = LengthBox.Text()
        angle = (AngleUpDown.Value) * (Math.PI) / 180       '// conversion en RAD
        k = CoeffUpDown.Value                                  '//on ne s'en sert pas ici
        x = 0
        y = 0
        xPrim = x + (Math.Cos(angle)) * lon
        yPrim = y - (Math.Sin(angle)) * lon
        g.DrawLine(Pens.Black, x, y, xPrim, yPrim)
        Label1.Text = "( " & xPrim & " ; " & yPrim & " )"    '//recuperer les coordonnees de xPrim et                                                                                                                                                        '//yPrim pour avoir une idee 



Pour une longueur de 1, ça m'a l'air très cohérent:
pour teta = 0 j'ai le point d'arrivée en (1;0)
pour teta = 90 j'ai le point d'arrivée en (0;1)
pour teta = 180 j'ai le point d'arrivée en (-1;0)
pour teta = 270 j'ai le point d'arrivée en (0;-1)
→ les fonctions cos et sin semblent fonctionner comme sur une calculatrice standard.
MAIS (car on ne pouvait se passer d'un mais) si j'augmente la valeur de mon vecteur, tout part de travers:
ex: longueur de 5
Pour téta = 0; point d'arrivée en (5;0)
pour téta = 180: point d'arrivée en (-5;1) ← et si ma fonction marchait correctement, je n'ai aucune raison de voir un y en -1 bon sang de bon soir!
0
yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024 1 468
27 oct. 2020 à 16:36
tu veux dire que avec AngleUpDown.Value = 180, tu obtiens, pour (xPrim; Yprim),
(-1;0) quand lon = 1
(-5;1) quand lon = 5

je ne vois pas la déclaration de xPrim et yPrim.
0
yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024 1 468 > yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024
27 oct. 2020 à 16:46
ceci donne quoi?
Dim lon As Double, xprim As Double, yPrim As Double, teta As Double, Angle As Double
teta = 180
lon = 5
Angle = teta * 4 * Atn(1) / 180     '// conversion en RAD
xprim = (Math.Cos(Angle)) * lon
yPrim = -(Math.Sin(Angle)) * lon
MsgBox "( " + CStr(xprim) + " ; " + CStr(yPrim) + " )"
0
arscy > yg_be Messages postés 22679 Date d'inscription lundi 9 juin 2008 Statut Contributeur Dernière intervention 14 avril 2024
27 oct. 2020 à 20:10
Désolé yg_be, j'ai fait un copier/coller un peu court sur ma dernière formule (il manquait x, y, xPrim, yPrim et angle en Integer
mais
Bingo Jeannie Longo:
mon erreur: déclaration de variable angle → j'ai déclaré angle en un entier parce que je le demandais en degrés dans mon interface ... mais je le convertis en radians dans ma formule ... et donc en un Réel.
Ce qui explique que dans ma PictureBox le vecteur était figé de 0 à 28° par exemple (l'entier était toujours arrondi à une valeur quelconque, et à 29 on passait à l'entier supérieur).
Donc juste en passant l'angle en Double je viens de faire le test pour les valeurs qui fâchent (ex: 30°), et j'ai des segments pertinents :-)
Tu as corrigé mon erreur/horreur sur ce point d'ailleurs
Je retourne sur ma formule initiale et je reviens pour confirmer que ça fonctionne.
0
arscy Messages postés 173 Date d'inscription dimanche 26 janvier 2014 Statut Membre Dernière intervention 5 octobre 2023 9
27 oct. 2020 à 22:33


Quand l'erreur basique est résolue, voici à quoi ça ressemble...
Merci pour votre mobilisation et vos suggestions :-)
0