Ruotare un triangolo in una DrawingArea: differenze tra le versioni

Da Gambas-it.org - Wikipedia.
Vai alla navigazione Vai alla ricerca
Nessun oggetto della modifica
Nessun oggetto della modifica
Riga 750: Riga 750:
   
   
  <FONT Color=gray>' ''Trasla e scala nel sistema di coordinate della DrawingArea:''</font>
  <FONT Color=gray>' ''Trasla e scala nel sistema di coordinate della DrawingArea:''</font>
   Return New PointF(cx + x2D * 100, cy - y2D * 100) ' *100 = scala visiva
   Return New PointF(cx + x2D * 100, cy - y2D * 100)   <FONT Color=gray>' ''*100 = scala visiva''</font>
   
   
  End
  End

Versione delle 23:12, 27 lug 2025

Mostriamo due possibili codice per far ruotare su se stesso un Triangolo disegnato su una DrawingArea. [Nota 1]

Rotazione in 2D

Ruotare un Triangolo intorno al suo Baricentro

Di seguito mostreremo un possibile codice per ruotare un Triangolo intorno al suo Baricentro.
Il fulcro del Metodo ".Translate()" agisce da vortice, ossia da centro di rotazione intorno a una ipotetica circonferenza.
La rotazione del triangolo viene effettuata premendo i tasti freccia in su e freccia in giù della tastiera oppure ruotando la rotellina del mouse.

Private DrawingArea1 As DrawingArea
' Imposta le coordinate dei tre vertici del triangolo, con il primo vertice nel punto di rotazione (0, 0):
Private ABC As Single[] = [0, 0, 200, 0, 100, 300]
' Calcoli per ottenere il "Baricentro" del triangolo:
Private xb As Single = (ABC[0] + ABC[2] + ABC[4]) / 3
Private yb As Single = (ABC[1] + ABC[3] + ABC[5]) / 3
' Memorizza i gradi dell'angolo:
Private ang As Float
Private c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
Private f As Float[] = [0, 0.34, 0.67, 1]


Public Sub Form_Open()  

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With  

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

End


Public Sub DrawingArea1_Draw()

 With Paint
   .Brush = .LinearGradient(0, 20, 15, 0, c, f)
' Imposta il fulcro/punto della rotazione - ad esempio - al centro dell'area di disegno:
   .Translate(DrawingArea1.W / 2, DrawingArea1.H / 2)
   .Rotate(Rad(ang))
   .LineWidth = 2.0
' Disegna il Triangolo.
' Siccome l'angolo ruota su se stesso, avendo come centro di rotazione il proprio "Baricentro", ad ogni coordinata del punto, che costituisce un elemento del vettore del Metodo ".Polygon()", si sottrae il valore della corrispondente coordinata del punto del Baricentro. In questo modo si farà coincidere l'angolo di rotazione con il "Baricentro" del Triangolo.
' Non si devono modificare i valori né i segni dei quattro argomenti qui riportati.
   .Polygon([ABC[0] - xb, ABC[1] - yb, ABC[2] - xb, ABC[3] - yb, ABC[4] - xb, ABC[5] - yb])
   .Stroke 
   .End
 End With     

End


Public Sub Form_KeyPress()
  
 Select Case Key.Code
   Case Key.Up
     ang += 1
     If ang = 361 Then ang = 1
   Case Key.Down
     ang -= 1
     If ang = -361 Then ang = -1
 End Select
 
 DrawingArea1.Refresh
  
End


Public Sub Form_MouseWheel()

 ang += Mouse.Delta
 Select Case ang
   Case 361
     ang = 1
   Case -361
     ang = -1
 End Select

 DrawingArea1.Refresh

End


Public Sub Form_Resize()   ' Con questo evento se cambia la dimensione del Form, il disegno non va perso.
  
 DrawingArea1.Refresh
  
End

oppure anche questo codice:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private rotationAngle As Float


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.White)
 End With

 Timer1 = New Timer As "Timer1"
 Timer1.Delay = 30
 Timer1.Start()

End


Public Sub Timer1_Timer()

 rotationAngle += Rad(2)           ' ruota di 2 gradi ogni frame
 If rotationAngle >= 2 * Pi Then
   rotationAngle -= 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 size As Float = Min(DrawingArea1.W, DrawingArea1.H) * 0.4

' Definisci i vertici del triangolo (posizionati attorno a (0,0)):
 Dim points As New PointF[3]
 points[0] = New PointF(0, -size / 2)          ' vertice superiore
 points[1] = New PointF(-size / 2, size / 2)   ' vertice basso sinistro
 points[2] = New PointF(size / 2, size / 2)    ' vertice basso destro

' Calcola baricentro (centroide):
 Dim centroidX As Float = 0
 Dim centroidY As Float = 0
 For i As Integer = 0 To 2
   centroidX += points[i].X
   centroidY += points[i].Y
 Next
 centroidX /= 3
 centroidY /= 3

' Ruota i punti attorno al baricentro e trasla al centro DrawingArea:
 For i As Integer = 0 To 2
   Dim xOld As Float = points[i].X - centroidX
   Dim yOld As Float = points[i].Y - centroidY

   points[i].X = xOld * Cos(rotationAngle) - yOld * Sin(rotationAngle) + centroidX + cx
   points[i].Y = xOld * Sin(rotationAngle) + yOld * Cos(rotationAngle) + centroidY + cy
 Next

 With Paint
   .Brush = Paint.Color(Color.Black)
   .LineWidth = 2
   .MoveTo(points[0].X, points[0].Y)
   For i As Integer = 1 To 2
     .LineTo(points[i].X, points[i].Y)
   Next
   .LineTo(points[0].X, points[0].Y)
   .Stroke

' Punto nero sul baricentro (traslato):
   .Arc(cx + centroidX, cy + centroidY, 5, Rad(0), Rad(360), False)
   .Fill
 End With

End

Il seguente codice disegna e ruota un Triangolo scaleno intorno al suo Baricentro:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private rotationAngle As Float


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.White)
 End With

 Timer1 = New Timer As "Timer1"
 Timer1.Delay = 30
 Timer1.Start()

End


Public Sub Timer1_Timer()

 rotationAngle += Rad(2)
 If rotationAngle >= 2 * Pi Then
   rotationAngle -= 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

' Vertici di un triangolo scaleno (modificabili):
 Dim points As New PointF[3]
 points[0] = New PointF(-160, -80)   ' 'Vertice A
 points[1] = New PointF(210, 50)     ' 'Vertice B
 points[2] = New PointF(50, 190)     ' 'Vertice C

' Calcola il baricentro (media delle coordinate):
 Dim baryX As Float = (points[0].X + points[1].X + points[2].X) / 3
 Dim baryY As Float = (points[0].Y + points[1].Y + points[2].Y) / 3

' Ruota i punti attorno al baricentro:
 For i As Integer = 0 To 2
   Dim xOld As Float = points[i].X - baryX
   Dim yOld As Float = points[i].Y - baryY

   points[i].X = xOld * Cos(rotationAngle) - yOld * Sin(rotationAngle) + baryX
   points[i].Y = xOld * Sin(rotationAngle) + yOld * Cos(rotationAngle) + baryY

' Trasla il triangolo per centrarlo nella DrawingArea:
   points[i].X += cx
   points[i].Y += cy
 Next

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

' Disegna il triangolo:
   .MoveTo(points[0].X, points[0].Y)
   For i As Integer = 1 To 2
     .LineTo(points[i].X, points[i].Y)
   Next
   .LineTo(points[0].X, points[0].Y)
   .Stroke

' Disegna il punto nero sul baricentro traslato correttamente:
   .Arc(cx + baryX, cy + baryY, 5, Rad(0), Rad(360), False)
   .Fill
 End With

End


Ruotare un Triangolo intorno al suo Incentro

Quest'altro codice servirà per far ruotare un Triangolo intorno al suo Incentro.
La rotazione del triangolo viene effettuata premendo i tasti freccia in su e freccia in giù della tastiera oppure ruotando la rotellina del mouse.
Il fulcro del Metodo ".Translate()" agisce da vortice, ossia da centro di rotazione intorno a una ipotetica circonferenza.

Private DrawingArea1 As DrawingArea
' Imposta le coordinate dei tre vertici del triangolo, con il primo vertice nel punto di rotazione (0, 0):
Private ABC As Single[] = [0, 0, 200, 0, 100, 300]
' Calcola la distanza euclidea fra due punti, per ottenere la lunghezza di ciascun lato del triangolo:
Private ab As Single = Sqr(((ABC[2] - ABC[0]) ^ 2) + ((ABC[3] - ABC[1]) ^ 2))
Private bc As Single = Sqr(((ABC[4] - ABC[2]) ^ 2) + ((ABC[5] - ABC[3]) ^ 2))
Private ac As Single = Sqr(((ABC[4] - ABC[0]) ^ 2) + ((ABC[5] - ABC[1]) ^ 2))
' Calcoli per ottenere il "Incentro" del triangolo:
Private ix As Single = ((ab * ABC[4]) + (bc * ABC[0]) + (ac * ABC[2])) / (ab + bc + ac)
Private iy As Single = ((ab * ABC[5]) + (bc * ABC[1]) + (ac * ABC[3])) / (ab + bc + ac)
' Memorizza i gradi dell'angolo:
Private ang As Float
Private c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
Private f As Float[] = [0, 0.34, 0.67, 1]


Public Sub Form_Open()  

 With Me
   .W = Screen.AvailableWidth
   .H = Screen.AvailableHeight
   .Arrangement = Arrange.Fill
 End With  

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

End


Public Sub DrawingArea1_Draw()

 With Paint
   .Brush = .LinearGradient(0, 20, 15, 0, c, f)
' Imposta il fulcro/punto della rotazione - ad esempio - al centro dell'area di disegno:
   .Translate(DrawingArea1.W / 2, DrawingArea1.H / 2)
   .Rotate(Rad(ang))
   .LineWidth = 2.0
' Disegna il Triangolo.
' Siccome l'angolo ruota su se stesso, avendo come centro di rotazione il proprio "Incentro", ad ogni coordinata del punto, che costituisce un elemento del vettore del Metodo ".Polygon()", si sottrae il valore della corrispondente coordinata del punto dell'Incentro. In questo modo si farà coincidere l'angolo di rotazione con il "Incentro" del Triangolo.
' Non si devono modificare i valori né i segni dei quattro argomenti qui riportati.
   .Polygon([ABC[0] - ix, ABC[1] - iy, ABC[2] - ix, ABC[3] - iy, ABC[4] - ix, ABC[5] - iy])
   .Stroke 
   .End
 End With     

End


Public Sub Form_KeyPress()
  
 Select Case Key.Code
   Case Key.Up
     ang += 1
     If ang = 361 Then ang = 1
   Case Key.Down
     ang -= 1
     If ang = -361 Then ang = -1
 End Select
 
 DrawingArea1.Refresh
  
End


Public Sub Form_MouseWheel()

 ang += Mouse.Delta
 Select Case ang
   Case 361
     ang = 1
   Case -361
     ang = -1
 End Select

 DrawingArea1.Refresh

End


Public Sub Form_Resize()   ' Con questo evento se cambia la dimensione del Form, il disegno non va perso.

 DrawingArea1.Refresh
  
End

oppure quest'altro codice:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private rotationAngle As Float = 0


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.White)
 End With

 Timer1 = New Timer As "Timer1"
 Timer1.Delay = 30
 Timer1.Start()

End


Public Sub Timer1_Timer()

 rotationAngle += Rad(2)
 If rotationAngle >= 2 * Pi Then
   rotationAngle -= 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 base As Float = Min(DrawingArea1.W, DrawingArea1.H) * 0.5
 Dim height As Float = base * 0.7

' Vertici triangolo isoscele (vertice in alto):
 Dim points As New PointF[3]
 points[0] = New PointF(0, -height / 2)           ' vertice superiore A
 points[1] = New PointF(-base / 2, height / 2)    ' vertice basso sinistro B
 points[2] = New PointF(base / 2, height / 2)     ' vertice basso destro C

' Calcola lunghezze lati:
 Dim a As Float = Sqr((points[1].X - points[2].X) ^ 2 + (points[1].Y - points[2].Y) ^ 2) ' BC
 Dim b As Float = Sqr((points[0].X - points[2].X) ^ 2 + (points[0].Y - points[2].Y) ^ 2) ' AC
 Dim c As Float = Sqr((points[0].X - points[1].X) ^ 2 + (points[0].Y - points[1].Y) ^ 2) ' AB

' Calcola l'Incentro:
 Dim incentroX As Float = (a * points[0].X + b * points[1].X + c * points[2].X) / (a + b + c)
 Dim incentroY As Float = (a * points[0].Y + b * points[1].Y + c * points[2].Y) / (a + b + c)

' Ruota attorno all'incentro e trasla nel centro DrawingArea:
 For i As Integer = 0 To 2
   Dim xOld As Float = points[i].X - incentroX
   Dim yOld As Float = points[i].Y - incentroY

   points[i].X = xOld * Cos(rotationAngle) - yOld * Sin(rotationAngle) + incentroX + cx
   points[i].Y = xOld * Sin(rotationAngle) + yOld * Cos(rotationAngle) + incentroY + cy
 Next

 With Paint
   .Brush = Paint.Color(Color.Black)
   .LineWidth = 2
   .MoveTo(points[0].X, points[0].Y)
   For i As Integer = 1 To 2
     .LineTo(points[i].X, points[i].Y)
   Next
   .LineTo(points[0].X, points[0].Y)
   .Stroke

' Punto nero sul incentro:
   .Arc(cx + incentroX, cy + incentroY, 5, Rad(0), Rad(360), False)
   .Fill
 End With

End

Il seguente codice disegna e ruota un Triangolo scaleno intorno al suo Incentro:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private rotationAngle As Float


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.White)
 End With

 Timer1 = New Timer As "Timer1"
 Timer1.Delay = 30
 Timer1.Start()

End


Public Sub Timer1_Timer()

 rotationAngle += Rad(2)
 If rotationAngle >= 2 * Pi Then
   rotationAngle -= 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

' Vertici di un triangolo scaleno senza angoli retti:
 Dim points As New PointF[3]
 points[0] = New PointF(-160, -80)   ' Vertice A
 points[1] = New PointF(210, 50)     ' Vertice B
 points[2] = New PointF(50, 190)     ' Vertice C

' Calcola le lunghezze dei lati:
 Dim a As Float = Sqr((points[1].X - points[2].X) ^ 2 + (points[1].Y - points[2].Y) ^ 2) ' BC
 Dim b As Float = Sqr((points[0].X - points[2].X) ^ 2 + (points[0].Y - points[2].Y) ^ 2) ' AC
 Dim c As Float = Sqr((points[0].X - points[1].X) ^ 2 + (points[0].Y - points[1].Y) ^ 2) ' AB

' Calcola l'incentro:
 Dim incentroX As Float = (a * points[0].X + b * points[1].X + c * points[2].X) / (a + b + c)
 Dim incentroY As Float = (a * points[0].Y + b * points[1].Y + c * points[2].Y) / (a + b + c)

' Ruota i punti attorno all'incentro e trasla nel centro della DrawingArea:
 For i As Integer = 0 To 2
   Dim xOld As Float = points[i].X - incentroX
   Dim yOld As Float = points[i].Y - incentroY

   points[i].X = xOld * Cos(rotationAngle) - yOld * Sin(rotationAngle) + incentroX + cx
   points[i].Y = xOld * Sin(rotationAngle) + yOld * Cos(rotationAngle) + incentroY + cy
 Next

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

' Disegna il triangolo:
   .MoveTo(points[0].X, points[0].Y)
   For i As Integer = 1 To 2
     .LineTo(points[i].X, points[i].Y)
   Next
   .LineTo(points[0].X, points[0].Y)
   .Stroke

' Disegna il punto nero sull'incentro:
   .Arc(cx + incentroX, cy + incentroY, 5, Rad(0), Rad(360), False)
   .Fill
 End With

End


Rotazione in 3D

Rotazione 3D attorno all'asse Y

Nel seguente codice faremo ruotare un triangolo isoscele attorno all'asse Y (cioè in spazio 3D):

Private angle As Float   ' Variabile globale per memorizzare l'angolo corrente della rotazione


Public Sub Form_Open()

 With Me
   .Title = "Rotazione di un Triangolo isoscele attorno all'asse Y"
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 Timer1.Delay = 16
 Timer1.Start()

End


Public Sub Timer1_Timer()

' Aumenta l’angolo di rotazione:
 angle += 2
 If angle >= 360 Then angle = 0
' Richiede il ridisegno della DrawingArea:
 DrawingArea1.Refresh

End


Public Sub DrawingArea1_Draw()

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

' Parametri del triangolo:
 Dim baseHalf As Float = 1.0     ' Metà base
 Dim height As Float = 1.5       ' Altezza del triangolo
 Dim d As Float = 4.0            ' Distanza simulata dalla "camera", ossia dall'osservatore

' Angolo in radianti:
 Dim radAngle As Float = Rad(angle)

' Definizione dei 3 vertici del triangolo in coordinate 3D (x, y, z):
 Dim v1 As Float[] = [0.0, height / 2, 0.0]         ' Vertice superiore
 Dim v2 As Float[] = [-baseHalf, -height / 2, 0.0]  ' Vertice sinistro della base
 Dim v3 As Float[] = [baseHalf, -height / 2, 0.0]   ' Vertice destro della base

' Applica la rotazione 3D attorno all’asse Y, quindi proietta in 2D:
 Dim p1 As PointF = Project3D(RotateY(v1, radAngle), d, cx, cy)
 Dim p2 As PointF = Project3D(RotateY(v2, radAngle), d, cx, cy)
 Dim p3 As PointF = Project3D(RotateY(v3, radAngle), d, cx, cy)

' Costruisce un array di coordinate [x0, y0, x1, y1, x2, y2]:
 Dim coords As Float[] = [p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y]

' Disegna e riempie il triangolo:
 Paint.Brush = Paint.Color(Color.Red)  ' Imposta il colore rosso
 Paint.Polygon(coords)                 ' Definisce la forma
 Paint.Fill()                          ' Riempe il triangolo

 Paint.End()                           ' Termina il disegno

End


Private Function RotateY(v As Float[], angle As Float) As Float[]   ' Funzione che ruota un punto 3D attorno all’asse Y
 
 Dim x As Float = v[0]
 Dim y As Float = v[1]
 Dim z As Float = v[2]

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

' Restituisce il punto ruotato:
 Return [xr, y, zr]

End


Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF   ' Funzione che proietta un punto 3D nello spazio 2D (prospettiva)

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

' Fattore di proiezione prospettica (più z è grande, più il punto è vicino):
 Dim factor As Float = d / (z + d + 0.001)  ' +0.001 per evitare divisione per zero

' Coordinate proiettate in 2D:
 Dim x2D As Float = x * factor
 Dim y2D As Float = y * factor

' Trasla e scala nel sistema della DrawingArea (inverte Y per avere l'alto verso l'alto):
 Return New PointF(cx + x2D * 100, cy - y2D * 100)

End


Rotazione 3D attorno agli assi X, Y e Z

Nel seguente codice faremo ruotare un triangolo isoscele attorno ai suoi assi X, Y e Z:

' Variabili globali per gli angoli di rotazione su ciascun asse:
Private angleX As Float
Private angleY As Float
Private angleZ As Float


Public Sub Form_Open()

 With Me
   .Title = "Rotazione di un Triangolo isoscele attorno agli assi X, Y e Z"
   .Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
   .Arrangement = Arrange.Fill
 End With

 Timer1.Delay = 16
 Timer1.Start()

End


Public Sub Timer1_Timer()

' Aumenta l’angolo di rotazione:
 angleX += 1            ' Ruota di 1 grado sull'asse X
 angleY += 2            ' Ruota di 2 gradi sull'asse Y
 angleZ += 1.5          ' Ruota di 1.5 gradi sull'asse Z
 
' Richiede il ridisegno della DrawingArea:
 DrawingArea1.Refresh

End


Public Sub DrawingArea1_Draw()

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

' Dimensioni del triangolo:
 Dim baseHalf As Float = 1.0       ' metà della base (±x)
 Dim height As Float = 1.5         ' altezza verticale
 Dim d As Float = 4.0              ' distanza "camera", ossia dell'osservatore, per simulare la prospettiva

' Converte gli angoli da gradi a radianti (richiesto per Sin/Cos):
 Dim ax As Float = Rad(angleX)
 Dim ay As Float = Rad(angleY)
 Dim az As Float = Rad(angleZ)

' Vertici iniziali del triangolo in 3D (sul piano XZ):
 Dim v1 As Float[] = [0.0, height / 2, 0.0]         ' vertice superiore (centro in alto)
 Dim v2 As Float[] = [-baseHalf, -height / 2, 0.0]  ' vertice base sinistra
 Dim v3 As Float[] = [baseHalf, -height / 2, 0.0]   ' vertice base destra

' Applica rotazione 3D a ciascun vertice: prima X, poi Y, poi Z:
 v1 = RotateZ(RotateY(RotateX(v1, ax), ay), az)
 v2 = RotateZ(RotateY(RotateX(v2, ax), ay), az)
 v3 = RotateZ(RotateY(RotateX(v3, ax), ay), az)

' Proietta i vertici ruotati da 3D → 2D (con prospettiva):
 Dim p1 As PointF = Project3D(v1, d, cx, cy)
 Dim p2 As PointF = Project3D(v2, d, cx, cy)
 Dim p3 As PointF = Project3D(v3, d, cx, cy)

' Costruisce l'array di coordinate 2D [x0, y0, x1, y1, x2, y2]:
 Dim coords As Float[] = [p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y]

' Disegna e riempie il triangolo con colore rosso:
 Paint.Brush = Paint.Color(Color.Red)
 Paint.Polygon(coords)   ' Definisce il contorno
 Paint.Fill()            ' Riempe il triangolo

 Paint.End()

End


Private Function RotateX(v As Float[], angle As Float) As Float[]   ' Ruota un punto attorno all'asse X (varia y, z)

 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


Private Function RotateY(v As Float[], angle As Float) As Float[]   ' Ruota un punto attorno all'asse Y (varia x, z)

 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


Private Function RotateZ(v As Float[], angle As Float) As Float[]   ' Ruota un punto attorno all'asse Z (varia x, y)

 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


Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF   ' Proietta un punto 3D in coordinate 2D con prospettiva

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

' Calcola il fattore di scala prospettico:
 Dim factor As Float = d / (z + d + 0.001)   ' Evita divisione per 0

' Proietta x e y in base alla profondità (z):
 Dim x2D As Float = x * factor
 Dim y2D As Float = y * factor

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

End



Note

[1] Vedere anche queste pagine: