Changements de coordonnées

Description

Simplement une application graphique des changements de coordonnées dans les repères orthonormés : Un cube qui tourne.
Ayant eu la chance de travailler dans l'aéronautique et pour le spatial, j'ai eu envie de "jouer" !!! A partir d'un trièdre de base animé en rotations sur les 3 axes, les points de jonctions des arrètes du cubes sont recalculés cycliquement. Une fonction est chargée du tracé du cube. La géométrie de la fenêtre peut être modifiée, c'est pris en compte.

Source / Exemple :


'
' Notes sur les changements de coordonnées :
'
' Dans un trièdre de base orthonormé avec :
'    l'axe des X dans l'axe du mobile et orienté vers l'avant
'    l'axe des Y orienté vers la gauche
'    l'axe des Z orienté vers le haut
'
' Les rotations autour de l'axe des X sont matérialisées par l'angle Phi
' Les rotations autour de l'axe des Y sont matérialisées par l'angle Teta
' Les rotations autour de l'axe des Z sont matérialisées par l'angle Psi
'
' Les rotations sont réalisées dans l'ordre Psi, Teta, Phi
'
' En aéronautique cela correspond respectivement au Cap, Tangage et Roulis
'
' Pour chaque rotation on calcule les projections dans le nouveau trièdre
'
' Cela abouti à avoir 3 systèmes trigonométriques respectivement f(Psi), f(Teta) et f(Psi)
'
' Afin de rendre le soft "lisible", la matrice complète de changement de coordonnées
' n'est pas utilisée
' Seules les systèmes d'équations spécifiques à chaque rotations sont utilisées
'
'
' Avion
' =====
'
' Xprime = x * cos(psi) + y * sin(psi)
' Yprime = x * -sin(psi) + y * cos(psi)
' Zprime = z
'
' Xseconde = Xprime * cos(teta) + Zprime * -sin(teta)
' Yseconde = Yprime
' Zseconde = Xprime * sin(teta) + Zprime * cos(teta)
'
' X3Avion = Xseconde
' Y3Avion = Yseconde * cos(phi) + Zseconde * sin(phi)
' Z3Avion = Yseconde * -sin(phi) + Zseconde * cos(phi)
'
'
' Vb6
' ===
'
' Xprime = x * cos(psi) + y * -sin(psi)
' Yprime = x * sin(psi) + y * cos(psi)
' Zprime = z
'
' Xseconde = xprime * cos(teta) + zprime * sin(teta)
' Yseconde = yprime
' Zseconde = xprime * -sin(teta) + zprime * cos(teta)
'
' X3Vb6 = xseconde
' Y3Vb6 = yseconde * cos(phi) + zseconde * sin(phi)
' Z3Vb6 = yseconde * -sin(phi) + zseconde * cos(phi)
'
'
' Hé oui, il y a une différence de comportement entre VB6
' et l'avion, cela vient des conventions de matriçage de l'écran par Microsoft
'
' Le cube comporte 12 cotés qui sont regroupés en 3 familles de 4 éléments
' suivant les axes X, Y et Z
' Les éléments de chaque famille sont indicés de 0 à 4 (!)
' Hé oui, il faut un groupe spécifique au trièdre de référence, c'est l'indice 0
'
' Enfin, chaque coté est défini par deux points (x1,y1)-(x2,y2)
'
' Le reste n'est que du "collage" de segments
'
Public Xctrx As Double, Xctry As Double
Public Yctrx As Double, Yctry As Double
Public Zctrx As Double, Zctry As Double

Public Xdx As Double, Xdy As Double
Public Ydx As Double, Ydy As Double
Public Zdx As Double, Zdy As Double
'
Public Psi As Double
Public Teta As Double
Public Phi As Double
'
Public PsiActual As Double
Public TetaActual As Double
Public PhiActual As Double
'
Public XActual As Double
Public YActual As Double
Public ZActual As Double

Public Sub Form_Load()
   '
   Dim LonCot As Double
   '
   On Error Resume Next
   '
   DoEvents
   '
   ' Détermination de la longueur du coté du cube
   LonCot = Int(Form1.Width / 5)
   '
   ' Affectations des dimensions aux axes en X et en Y (représentation plane)
   Xdx = LonCot
   Ydx = -LonCot
   Zdx = 0
   '
   Xdy = -LonCot
   Ydy = -LonCot
   Zdy = LonCot
   '
   ' Détermination du trièdre de référence
   AxeX(0).X1 = Int(Form1.Width / 2)
   AxeX(0).Y1 = Int(Form1.Height / 2)
   AxeX(0).X2 = Int(Form1.Width / 2)
   AxeX(0).Y2 = Int(Form1.Height / 2) + Int(LonCot / 2)
   '
   AxeY(0).X1 = AxeX(0).X1
   AxeY(0).Y1 = AxeX(0).Y1
   AxeY(0).X2 = AxeY(0).X1 + Int(Ydx / 2)
   AxeY(0).Y2 = AxeY(0).Y1 + Int(Ydy / 2)
   '
   AxeZ(0).X1 = AxeX(0).X1
   AxeZ(0).Y1 = AxeX(0).Y1
   AxeZ(0).X2 = AxeZ(0).X1 + Int(Zdx / 2)
   AxeZ(0).Y2 = AxeZ(0).Y1 + Int(Zdy / 2)
   '
   ' Initialisation des angles
   Psi = 0
   Teta = 0
   Phi = 0
   '
   PsiActual = 0
   TetaActual = 0
   PhiActual = 0
   '
   ' Tracé du cube
   Call Cube
   '
   ' Armement des timers pour réaliser les variations de Psi, Teta et Phi
   Tpsi.Interval = 15
   Tpsi.Enabled = True
   '
   Tteta.Interval = 18
   Tteta.Enabled = True
   '
   Tphi.Interval = 19
   Tphi.Enabled = True
   '
End Sub

Private Sub Form_Resize()
   '
   LonCot = Int(Form1.Width / 10)
   '
   Xdx = LonCot
   Ydx = -LonCot
   Zdx = 0
   '
   Xdy = -LonCot
   Ydy = -LonCot
   Zdy = LonCot
   '
   AxeX(0).X1 = Int(Form1.Width / 2)
   AxeX(0).Y1 = Int(Form1.Height / 2)
   AxeX(0).X2 = Int(Form1.Width / 2)
   AxeX(0).Y2 = Int(Form1.Height / 2) + Int(LonCot / 2)
   '
   AxeY(0).X1 = AxeX(0).X1
   AxeY(0).Y1 = AxeX(0).Y1
   AxeY(0).X2 = AxeY(0).X1 + Int(Ydx / 2)
   AxeY(0).Y2 = AxeY(0).Y1 + Int(Ydy / 2)
   '
   AxeZ(0).X1 = AxeX(0).X1
   AxeZ(0).Y1 = AxeX(0).Y1
   AxeZ(0).X2 = AxeZ(0).X1 + Int(Zdx / 2)
   AxeZ(0).Y2 = AxeZ(0).Y1 + Int(Zdy / 2)
   '
End Sub

Public Sub Tpsi_Timer()
   With Form1
      .Psi = .Psi + 1
      If .Psi = 180 Then .Psi = -180
      '
      .AxeX(0).X2 = .AxeX(0).X1 + X3Vb6(.Xdx, .Ydx, .Zdx, .Psi, .TetaActual, .PhiActual)
      .AxeX(0).Y2 = .AxeX(0).Y1 + X3Vb6(.Xdy, .Ydy, .Zdy, .Psi, .TetaActual, .PhiActual)
      .AxeY(0).X2 = .AxeY(0).X1 + Y3Vb6(.Xdx, .Ydx, .Zdx, .Psi, .TetaActual, .PhiActual)
      .AxeY(0).Y2 = .AxeY(0).Y1 + Y3Vb6(.Xdy, .Ydy, .Zdy, .Psi, .TetaActual, .PhiActual)
      '
      .XActual = .AxeX(0).X2 - .AxeX(0).X1
      .YActual = .AxeY(0).X2 - .AxeY(0).X1
      .ZActual = .AxeZ(0).X2 - .AxeZ(0).X1
      '
      .PsiActual = .Psi
      '
   End With
   '
   Call Cube
   '
End Sub

Public Sub Tteta_Timer()
   With Form1
      .Teta = .Teta - 1
      If .Teta = -180 Then .Teta = 180
      '
      .AxeX(0).X2 = .AxeX(0).X1 + X3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .Teta, .PhiActual)
      .AxeX(0).Y2 = .AxeX(0).Y1 + X3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .Teta, .PhiActual)
      .AxeZ(0).X2 = .AxeZ(0).X1 + Z3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .Teta, .PhiActual)
      .AxeZ(0).Y2 = .AxeZ(0).Y1 + Z3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .Teta, .PhiActual)
      '
      .XActual = .AxeX(0).X2 - .AxeX(0).X1
      .YActual = .AxeY(0).X2 - .AxeY(0).X1
      .ZActual = .AxeZ(0).X2 - .AxeZ(0).X1
      '
      .TetaActual = .Teta
      '
   End With
   '
   Call Cube
   '
End Sub

Public Sub Tphi_Timer()
   With Form1
      .Phi = .Phi + 1
      If .Phi = 180 Then .Phi = -180
      '
      .AxeY(0).X2 = .AxeY(0).X1 + Y3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .TetaActual, .Phi)
      .AxeY(0).Y2 = .AxeY(0).Y1 + Y3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .TetaActual, .Phi)
      .AxeZ(0).X2 = .AxeZ(0).X1 + Z3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .TetaActual, .Phi)
      .AxeZ(0).Y2 = .AxeZ(0).Y1 + Z3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .TetaActual, .Phi)
      '
      .XActual = .AxeX(0).X2 - .AxeX(0).X1
      .YActual = .AxeY(0).X2 - .AxeY(0).X1
      .ZActual = .AxeZ(0).X2 - .AxeZ(0).X1
      '
      .PhiActual = .Phi
      '
   End With
   '
   Call Cube
   '
End Sub

'
' Avion
' =====
'
' Xprime = x * cos(psi) + y * sin(psi)
' Yprime = x * -sin(psi) + y * cos(psi)
' Zprime = z
'
' Xseconde = Xprime * cos(teta) + Zprime * -sin(teta)
' Yseconde = Yprime
' Zseconde = Xprime * sin(teta) + Zprime * cos(teta)
'
' X3Avion = Xseconde
' Y3Avion = Yseconde * cos(phi) + Zseconde * sin(phi)
' Z3Avion = Yseconde * -sin(phi) + Zseconde * cos(phi)
'
Public Function X3Avion(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * Sin(Psi)
   Yprime = x * -Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * -Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * Sin(Teta) + Zprime * Cos(Teta)
   '
   X3Avion = Xseconde
   ' Y3Avion = Yseconde * cos(phi) + Zseconde * sin(phi)
   ' Z3Avion = Yseconde * -sin(phi) + Zseconde * cos(phi)
   '
   Form1.PsiActual = Form1.Psi
   '
End Function

Public Function Y3Avion(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * Sin(Psi)
   Yprime = x * -Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * -Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * Sin(Teta) + Zprime * Cos(Teta)
   '
   ' X3Avion = Xseconde
   Y3Avion = Yseconde * Cos(Phi) + Zseconde * Sin(Phi)
   ' Z3Avion = Yseconde * -sin(phi) + Zseconde * cos(phi)
   '
   Form1.TetaActual = Form1.Teta
   '
End Function

Public Function Z3Avion(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * Sin(Psi)
   Yprime = x * -Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * -Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * Sin(Teta) + Zprime * Cos(Teta)
   '
   ' X3Avion = Xseconde
   ' Y3Avion = Yseconde * cos(phi) + Zseconde * sin(phi)
   Z3Avion = Yseconde * -Sin(Phi) + Zseconde * Cos(Phi)
   '
   Form1.PhiActual = Form1.Phi
   '
End Function

'
' Vb6
' ===
'
' Xprime = x * cos(psi) + y * -sin(psi)
' Yprime = x * sin(psi) + y * cos(psi)
' Zprime = z
'
' Xseconde = xprime * cos(teta) + zprime * sin(teta)
' Yseconde = yprime
' Zseconde = xprime * -sin(teta) + zprime * cos(teta)
'
' X3Vb6 = xseconde
' Y3Vb6 = yseconde * cos(phi) + zseconde * sin(phi)
' Z3Vb6 = yseconde * -sin(phi) + zseconde * cos(phi)
'

Public Function X3Vb6(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * -Sin(Psi)
   Yprime = x * Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * -Sin(Teta) + Zprime * Cos(Teta)
   '
   X3Vb6 = Xseconde
   'Y3Vb6 = yseconde * cos(phi) + zseconde * sin(phi)
   'Z3Vb6 = Yseconde * -Sin(Phi) + Zseconde * Cos(Phi)
   '
End Function

Public Function Y3Vb6(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * -Sin(Psi)
   Yprime = x * Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * -Sin(Teta) + Zprime * Cos(Teta)
   '
   'X3Vb6 = Xseconde
   Y3Vb6 = Yseconde * Cos(Phi) + Zseconde * Sin(Phi)
   'Z3Vb6 = Yseconde * -Sin(Phi) + Zseconde * Cos(Phi)
   '
End Function

Public Function Z3Vb6(x As Double, y As Double, z As Double, _
                      Psi As Double, Teta As Double, Phi As Double) As Double
   '
   Dim Xprime As Double, Yprime As Double, Zprime As Double
   Dim Xseconde As Double, Yseconde As Double, Zseconde As Double
   Dim Pi As Double
   '
   Pi = 4 * Atn(1)
   Psi = Psi * Pi / 180
   Teta = Teta * Pi / 180
   Phi = Phi * Pi / 180
   '
   Xprime = x * Cos(Psi) + y * -Sin(Psi)
   Yprime = x * Sin(Psi) + y * Cos(Psi)
   Zprime = z
   '
   Xseconde = Xprime * Cos(Teta) + Zprime * Sin(Teta)
   Yseconde = Yprime
   Zseconde = Xprime * -Sin(Teta) + Zprime * Cos(Teta)
   '
   'X3Vb6 = Xseconde
   'Y3Vb6 = yseconde * cos(phi) + zseconde * sin(phi)
   Z3Vb6 = Yseconde * -Sin(Phi) + Zseconde * Cos(Phi)
   '
End Function

Public Function Cube()
   '
   With Form1
      '
      .VectX.X1 = .AxeY(0).X2
      .VectX.Y1 = .AxeY(0).Y2
      .VectX.X2 = .VectX.X1 + X3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .VectX.Y2 = .VectX.Y1 + X3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .VectZ.X1 = .VectX.X2
      .VectZ.Y1 = .VectX.Y2
      .VectZ.X2 = .VectZ.X1 - Z3Vb6(.Xdx, .Ydx, .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .VectZ.Y2 = .VectZ.Y1 - Z3Vb6(.Xdy, .Ydy, .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      '
      .AxeX(2).X1 = .VectZ.X2
      .AxeX(2).Y1 = .VectZ.Y2
      .AxeX(2).X2 = .AxeX(2).X1 - X3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeX(2).Y2 = .AxeX(2).Y1 - X3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeY(3).X1 = .VectZ.X2
      .AxeY(3).Y1 = .VectZ.Y2
      .AxeY(3).X2 = .AxeY(3).X1 - Y3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeY(3).Y2 = .AxeY(3).Y1 - Y3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeZ(3).X1 = .VectZ.X2
      .AxeZ(3).Y1 = .VectZ.Y2
      .AxeZ(3).X2 = .AxeZ(3).X1 + Z3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeZ(3).Y2 = .AxeZ(3).Y1 + Z3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeX(1).X1 = .AxeY(3).X2
      .AxeX(1).Y1 = .AxeY(3).Y2
      .AxeX(1).X2 = .AxeX(1).X1 - X3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeX(1).Y2 = .AxeX(1).Y1 - X3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeY(1).X1 = .AxeX(1).X2
      .AxeY(1).Y1 = .AxeX(1).Y2
      .AxeY(1).X2 = .AxeX(2).X2
      .AxeY(1).Y2 = .AxeX(2).Y2
      '
      .AxeZ(1).X1 = .AxeX(1).X2
      .AxeZ(1).Y1 = .AxeX(1).Y2
      .AxeZ(1).X2 = .AxeZ(1).X1 + Z3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeZ(1).Y2 = .AxeZ(1).Y1 + Z3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeZ(2).X1 = .AxeX(1).X1
      .AxeZ(2).Y1 = .AxeX(1).Y1
      .AxeZ(2).X2 = .AxeZ(2).X1 + Z3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeZ(2).Y2 = .AxeZ(2).Y1 + Z3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeZ(4).X1 = .AxeY(1).X2
      .AxeZ(4).Y1 = .AxeY(1).Y2
      .AxeZ(4).X2 = .AxeZ(4).X1 + Z3Vb6(2 * .Xdx, 2 * .Ydx, 2 * .Zdx, .PsiActual, .TetaActual, .PhiActual)
      .AxeZ(4).Y2 = .AxeZ(4).Y1 + Z3Vb6(2 * .Xdy, 2 * .Ydy, 2 * .Zdy, .PsiActual, .TetaActual, .PhiActual)
      '
      .AxeY(2).X1 = .AxeZ(1).X2
      .AxeY(2).Y1 = .AxeZ(1).Y2
      .AxeY(2).X2 = .AxeZ(4).X2
      .AxeY(2).Y2 = .AxeZ(4).Y2
      '
      .AxeX(3).X1 = .AxeZ(4).X2
      .AxeX(3).Y1 = .AxeZ(4).Y2
      .AxeX(3).X2 = .AxeZ(3).X2
      .AxeX(3).Y2 = .AxeZ(3).Y2
      '
      .AxeX(4).X1 = .AxeZ(1).X2
      .AxeX(4).Y1 = .AxeZ(1).Y2
      .AxeX(4).X2 = .AxeZ(2).X2
      .AxeX(4).Y2 = .AxeZ(2).Y2
      '
      .AxeY(4).X1 = .AxeZ(2).X2
      .AxeY(4).Y1 = .AxeZ(2).Y2
      .AxeY(4).X2 = .AxeZ(3).X2
      .AxeY(4).Y2 = .AxeZ(3).Y2
      '
   End With
   '
End Function

Conclusion :


Pour l'instant je n'ai pas identifié de bug.
17/10/2003 : Tenant compte des remarques reçues - merci aux auteurs - j'ai tenté d'expliquer comment ça fonctionne et pourquoi.
Pour l'évolution avec la fonction me.line(x,y)-(x2,y2) il me faut le temps de maitriser !

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.