Ruotare un eptagono in una DrawingArea

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca

Di seguito mostreremo un possibile codice per ruotare un Eptagono regolare disegnato in una DrawingArea. [Nota 1]

Rotazione in 2D

Private DrawingArea1 As DrawingArea
Private Tmr As Timer
Private Const ScalaRaggio As Float = 0.2   ' Scala del raggio (dimensione dell'eptagono)
Private Rotazione As Float                 ' Angolo di rotazione in radianti


Public Sub Form_Open()

 With Me
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.Lighter(Color.Yellow)
 End With

 Tmr = New Timer As "Tmr"
 Tmr.Delay = 30             ' circa 33 FPS
 Tmr.Start()

End


Public Sub Tmr_Timer()

 Rotazione += Rad(1.5)         ' Rotazione di 1.5° per frame
 If Rotazione >= 2 * Pi Then
   Rotazione -= 2 * Pi
 End If
 DrawingArea1.Refresh()

End


Public Sub DrawingArea1_Draw()

 Dim cx As Float = DrawingArea1.W / 2
 Dim cy As Float = DrawingArea1.H / 2
 Dim r As Float = Min(DrawingArea1.W, DrawingArea1.H) * ScalaRaggio
 Dim numSides As Integer = 7
 Dim angleStep As Float = 2 * Pi / numSides
 Dim points As New PointF[numSides]
 Dim i As Integer

 For i = 0 To numSides - 1
   Dim angle As Float = angleStep * i - Pi / 2 + Rotazione
   points[i] = New PointF(cx + r * Cos(angle), cy + r * Sin(angle))
 Next

 With Paint
   .Brush = Paint.Color(Color.Black)
   .LineWidth = 2

   .MoveTo(points[0].X, points[0].Y)
   For i = 1 To numSides - 1
     .LineTo(points[i].X, points[i].Y)
   Next
   .LineTo(points[0].X, points[0].Y)

   .Stroke
 End With

End

Rotazione in 3D

Rotazione dell'eptagono intorno al suo asse Y

Private angleY As Float


Public Sub Form_Open()

 With Me
   .Title = "Eptagono che ruota in senso orario intorno al suo asse Y"
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 Timer1.Delay = 16  ' ~60 FPS
 Timer1.Start

End


Public Sub Timer1_Timer()

' Ruota solo attorno all’asse Y:
 angleY += 2

 DrawingArea1.Refresh

End


Public Sub DrawingArea1_Draw()

' Centro della DrawingArea:
 Dim cx As Float = DrawingArea1.Width / 2
 Dim cy As Float = DrawingArea1.Height / 2

' Parametri dell'eptagono:
 Dim radius As Float = 1.0              ' Raggio del poligono regolare
 Dim d As Float = 4.0                   ' Distanza simulata della "camera"
 Dim sides As Integer = 7               ' Numero di lati (7 = eptagono)

 Dim ay As Float = Rad(angleY)          ' Converte l'angolo in radianti

 Dim coords As Float[] = []             ' Array dei punti proiettati 2D

 ' === Calcolo dei vertici ===
 For i As Integer = 0 To sides - 1
   Dim theta As Float = 2 * Pi * i / sides     ' Angolo per il vertice i-esimo

' Coordinate 3D sul piano XY (z=0):
   Dim x As Float = radius * Cos(theta)
   Dim y As Float = radius * Sin(theta)
   Dim z As Float = 0.0

   Dim p As Float[] = [x, y, z]

' Ruota il punto attorno all'asse Y:
   p = RotateY(p, ay)

' Proietta il punto 3D in 2D con effetto prospettico:
   Dim pt As PointF = Project3D(p, d, cx, cy)

' Aggiunge le coordinate 2D all'array da disegnare:
   coords.Add(pt.X)
   coords.Add(pt.Y)
 Next

' === Riempie l'eptagono ruotato ===
 Paint.Brush = Paint.Color(Color.RGB(255, 204, 0))
 Paint.Polygon(coords)
 Paint.Fill()

' === Bordo nero dell'eptagono ===
 Paint.LineWidth = 1
 Paint.Brush = Paint.Color(Color.Black)
 Paint.Polygon(coords)
 Paint.Stroke()

End


' === Rotazione 3D attorno all’asse Y ===
Private Function RotateY(v As Float[], angle As Float) As Float[]

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]

' Ruota x e z attorno all'asse Y:
 Dim xr As Float = x * Cos(angle) + z * Sin(angle)
 Dim zr As Float = -x * Sin(angle) + z * Cos(angle)

 Return [xr, y, zr]

End


' === Proiezione prospettica da 3D a 2D ===
Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]

' Calcola fattore prospettico in base alla profondità z:
 Dim factor As Float = d / (z + d + 0.001)   ' +0.001 evita divisione per 0

' Applica la scala prospettica:
 Dim x2D As Float = x * factor
 Dim y2D As Float = y * factor

' Trasla nel sistema di coordinate della DrawingArea:
 Return New PointF(cx + x2D * 100, cy - y2D * 100)

End


Rotazione dell'eptagono intorno ai sui assi X, Y e Z

' === Variabili private per la rotazione su X, Y, Z ===
Private angleX As Float
Private angleY As Float
Private angleZ As Float


Public Sub Form_Open()

 With Me
   .Title = "Eptagono che ruota in senso orario intorno ai sui assi X, Y, Z"
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 Timer1.Delay = 16  ' ~60 FPS
 Timer1.Start

End


Public Sub Timer1_Timer()

 angleX += 1.2
 angleY += 2
 angleZ += 0.8

 DrawingArea1.Refresh

End


Public Sub DrawingArea1_Draw()

' Centro della DrawingArea:
 Dim cx As Float = DrawingArea1.Width / 2
 Dim cy As Float = DrawingArea1.Height / 2

' Parametri eptagono:
 Dim radius As Float = 1.0
 Dim d As Float = 4.0
 Dim sides As Integer = 7

' Angoli in radianti:
 Dim ax As Float = Rad(angleX)
 Dim ay As Float = Rad(angleY)
 Dim az As Float = Rad(angleZ)

' Array dei punti proiettati 2D:
 Dim coords As Float[] = []

' === Calcolo e rotazione dei vertici ===
 For i As Integer = 0 To sides - 1
   Dim theta As Float = 2 * Pi * i / sides

' Punto iniziale nel piano XY:
   Dim x As Float = radius * Cos(theta)
   Dim y As Float = radius * Sin(theta)
   Dim z As Float = 0.0

   Dim p As Float[] = [x, y, z]

' Rotazioni in sequenza: X → Y → Z:
   p = RotateX(p, ax)
   p = RotateY(p, ay)
   p = RotateZ(p, az)

' Proiezione 3D → 2D:
   Dim pt As PointF = Project3D(p, d, cx, cy)

   coords.Add(pt.X)
   coords.Add(pt.Y)
 Next

' Riempie l’eptagono ruotato:
 Paint.Brush = Paint.Color(Color.RGB(255, 204, 0))
 Paint.Polygon(coords)
 Paint.Fill()

' Bordo nero:
 Paint.LineWidth = 1
 Paint.Brush = Paint.Color(Color.Black)
 Paint.Polygon(coords)
 Paint.Stroke()

End

' === ROTAZIONE attorno all'asse X ===
Private Function RotateX(v As Float[], angle As Float) As Float[]

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]
 Dim yr As Float = y * Cos(angle) - z * Sin(angle)
 Dim zr As Float = y * Sin(angle) + z * Cos(angle)

 Return [x, yr, zr]

End

' === ROTAZIONE attorno all'asse Y ===
Private Function RotateY(v As Float[], angle As Float) As Float[]

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]
 Dim xr As Float = x * Cos(angle) + z * Sin(angle)
 Dim zr As Float = -x * Sin(angle) + z * Cos(angle)

 Return [xr, y, zr]

End


' === ROTAZIONE attorno all'asse Z ===
Private Function RotateZ(v As Float[], angle As Float) As Float[]

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]
 Dim xr As Float = x * Cos(angle) - y * Sin(angle)
 Dim yr As Float = x * Sin(angle) + y * Cos(angle)

 Return [xr, yr, z]

End

' === PROIEZIONE prospettica 3D → 2D ===
Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF

 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]
 Dim factor As Float = d / (z + d + 0.001)   ' Simula profondità:
 Dim x2D As Float = x * factor
 Dim y2D As Float = y * factor

 Return New PointF(cx + x2D * 100, cy - y2D * 100)

End



Note

[1] Vedere anche la seguente pagina: Ruotare un pentagono in una DrawingArea