Ruotare un eptagono in una DrawingArea
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