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
 
(14 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Mostriamo un possibile codice per far ruotare su se stesso, e più specificatamente <SPAN Style="text-decoration:underline">intorno al proprio ''[https://it.wikipedia.org/wiki/Baricentro_(geometria) Baricentro]''</span>, un triangolo disegnato su una ''DrawingArea''. <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>
Mostriamo due possibili codice per far ruotare su se stesso un Triangolo disegnato su una ''DrawingArea''. <SUP>&#091;[[#Note|Nota 1]]&#093;</sup>
 
=Rotazione in 2D=
 
==Ruotare un Triangolo intorno al suo Baricentro==
Di seguito mostreremo un possibile codice per ruotare un Triangolo intorno al suo <SPAN Style="text-decoration:underline">''[https://it.wikipedia.org/wiki/Baricentro_(geometria) Baricentro]''</span>.
<BR>Il fulcro del Metodo ".Translate()" agisce da vortice, ossia da centro di rotazione intorno a una ipotetica circonferenza.
<BR>La rotazione del triangolo viene effettuata premendo i tasti freccia in su e freccia in giù della tastiera oppure ruotando la rotellina del mouse.
<BR>La rotazione del triangolo viene effettuata premendo i tasti freccia in su e freccia in giù della tastiera oppure ruotando la rotellina del mouse.
<BR>Il fulcro del Metodo ".Translate()" agisce da vortice, ossia da centro di rotazione intorno a una ipotetica circonferenza.
  Private DrawingArea1 As DrawingArea
  Private DrawingArea1 As DrawingArea
  <FONT Color=gray>' ''Imposta le coordinate dei tre vertici del triangolo, con il primo vertice nel punto di rotazione (0, 0):''</font>
  <FONT Color=gray>' ''Imposta le coordinate dei tre vertici del triangolo, con il primo vertice nel punto di rotazione (0, 0):''</font>
  Private ABC As Single[] = [0, 0, 200, 0, 100, 300]
  Private ABC As Single[] = [0, 0, 200, 0, 100, 300]
  <FONT Color=gray>' ''Calcoli per ottenere il "Baricentro" del triangolo:''</font>
  <FONT Color=gray>' ''Calcoli per ottenere il "Baricentro" del triangolo:''</font>
  Private xg As Single = (ABC[0] + ABC[2] + ABC[4]) / 3
  Private xb As Single = (ABC[0] + ABC[2] + ABC[4]) / 3
  Private yg As Single = (ABC[1] + ABC[3] + ABC[5]) / 3
  Private yb As Single = (ABC[1] + ABC[3] + ABC[5]) / 3
  <FONT Color=gray>' ''Memorizza i gradi dell'angolo:''</font>
  <FONT Color=gray>' ''Memorizza i gradi dell'angolo:''</font>
  Private ang As Float
  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()   
  Public Sub Form_Open()   
   
   
With Me
  With Me
  .W = Screen.AvailableWidth
    .W = Screen.AvailableWidth
  .H = Screen.AvailableHeight
    .H = Screen.AvailableHeight
  .Arrangement = Arrange.Fill
    .Arrangement = Arrange.Fill
End With   
  End With   
   
   
With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
  With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
  .Background = Color.White
    .Background = Color.White
End With
  End With
   
   
  '''End'''
  End
   
   
'''Public''' Sub DrawingArea1_Draw()
   
   
  Dim c As Integer[] = [Color.Blue, Color.Green, Color.Yellow, Color.Red]
Public Sub DrawingArea1_Draw()
  Dim f As Float[] = [0, 0.34, 0.67, 1]
   
   
   With Paint
   With Paint
Riga 38: Riga 43:
     .LineWidth = 2.0
     .LineWidth = 2.0
  <FONT Color=gray>' ''Disegna il Triangolo.''
  <FONT Color=gray>' ''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.''
  ' ''Giacché 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.''</font>
  ' ''Non si devono modificare i valori né i segni dei quattro argomenti qui riportati.''</font>
     .Polygon([ABC[0] - xg, ABC[1] - yg, ABC[2] - xg, ABC[3] - yg, ABC[4] - xg, ABC[5] - yg])
     .Polygon([ABC[0] - xb, ABC[1] - yb, ABC[2] - xb, ABC[3] - yb, ABC[4] - xb, ABC[5] - yb])
     .Stroke  
     .Stroke  
    .End
   End With     
   End With     
   
   
  '''End'''
  End
   
   
  '''Public''' Sub Form_KeyPress()
  Public Sub Form_KeyPress()
    
    
   Select Case Key.Code
   Select Case Key.Code
Riga 60: Riga 65:
   DrawingArea1.Refresh
   DrawingArea1.Refresh
    
    
  '''End'''
  End
   
   
  '''Public''' Sub Form_MouseWheel()
  Public Sub Form_MouseWheel()
   
   
   ang += Mouse.Delta
   ang += Mouse.Delta
Riga 74: Riga 80:
   DrawingArea1.Refresh
   DrawingArea1.Refresh
   
   
  '''End'''
  End
   
   
  '''Public''' Sub Form_Resize()  <FONT Color=gray>' ''Con questo evento se cambia la dimensione del Form, il disegna non va perso.''</font>
  Public Sub Form_Resize()  <FONT Color=gray>' ''Con questo evento se cambia la dimensione del Form, il disegno non va perso.''</font>
    
    
   DrawingArea1.Refresh
   DrawingArea1.Refresh
    
    
  '''End'''
  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)          <FONT Color=gray>' ''ruota di 2 gradi ogni frame''</font>
  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
<FONT Color=gray>' ''Definisci i vertici del triangolo (posizionati attorno a (0,0)):''</font>
  Dim points As New PointF[3]
  points[0] = New PointF(0, -size / 2)          <FONT Color=gray>' ''vertice superiore''</font>
  points[1] = New PointF(-size / 2, size / 2)  <FONT Color=gray>' ''vertice basso sinistro''</font>
  points[2] = New PointF(size / 2, size / 2)    <FONT Color=gray>' ''vertice basso destro''</font>
<FONT Color=gray>' ''Calcola baricentro (centroide):''</font>
  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
<FONT Color=gray>' ''Ruota i punti attorno al baricentro e trasla al centro DrawingArea:''</font>
  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
<FONT Color=gray>' ''Punto nero sul baricentro (traslato):''</font>
    .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
<FONT Color=gray>' ''Vertici di un triangolo scaleno (modificabili):''</font>
  Dim points As New PointF[3]
  points[0] = New PointF(-160, -80)  <FONT Color=gray>' 'Vertice A''</font>
  points[1] = New PointF(210, 50)    <FONT Color=gray>' 'Vertice B''</font>
  points[2] = New PointF(50, 190)    <FONT Color=gray>' 'Vertice C''</font>
<FONT Color=gray>' ''Calcola il baricentro (media delle coordinate):''</font>
  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
<FONT Color=gray>' ''Ruota i punti attorno al baricentro:''</font>
  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
<FONT Color=gray>' ''Trasla il triangolo per centrarlo nella DrawingArea:''</font>
    points[i].X += cx
    points[i].Y += cy
  Next
  With Paint
    .Brush = Paint.Color(Color.Black)
    .LineWidth = 2
<FONT Color=gray>' ''Disegna il triangolo:''</font>
    .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
<FONT Color=gray>' ''Disegna il punto nero sul baricentro traslato correttamente:''</font>
    .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 <SPAN Style="text-decoration:underline">''[https://it.wikipedia.org/wiki/Incentro Incentro]''</span>.
<BR>La rotazione del triangolo viene effettuata premendo i tasti freccia in su e freccia in giù della tastiera oppure ruotando la rotellina del mouse.
<BR>Il fulcro del Metodo ".Translate()" agisce da vortice, ossia da centro di rotazione intorno a una ipotetica circonferenza.
Private DrawingArea1 As DrawingArea
<FONT Color=gray>' ''Imposta le coordinate dei tre vertici del triangolo, con il primo vertice nel punto di rotazione (0, 0):''</font>
Private ABC As Single[] = [0, 0, 200, 0, 100, 300]
<FONT Color=gray>' ''Calcola la [https://www.youmath.it/formulari/formulari-di-geometria-analitica/426-distanza-tra-due-punti-nel-piano.html distanza euclidea] fra due punti, per ottenere la lunghezza di ciascun lato del triangolo:''</font>
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))
<FONT Color=gray>' ''Calcoli per ottenere il "Incentro" del triangolo:''</font>
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)
<FONT Color=gray>' ''Memorizza i gradi dell'angolo:''</font>
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)
<FONT Color=gray>' ''Imposta il fulcro/punto della rotazione - ad esempio - al centro dell'area di disegno:''</font>
    .Translate(DrawingArea1.W / 2, DrawingArea1.H / 2)
    .Rotate(Rad(ang))
    .LineWidth = 2.0
<FONT Color=gray>' ''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.''</font>
    .Polygon([ABC[0] - ix, ABC[1] - iy, ABC[2] - ix, ABC[3] - iy, ABC[4] - ix, ABC[5] - iy])
    .Stroke
  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()  <FONT Color=gray>' ''Con questo evento se cambia la dimensione del Form, il disegno non va perso.''</font>
  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
<FONT Color=gray>' ''Vertici triangolo isoscele (vertice in alto):''</font>
  Dim points As New PointF[3]
  points[0] = New PointF(0, -height / 2)          <FONT Color=gray>' ''vertice superiore A''</font>
  points[1] = New PointF(-base / 2, height / 2)    <FONT Color=gray>' ''vertice basso sinistro B''</font>
  points[2] = New PointF(base / 2, height / 2)    <FONT Color=gray>' ''vertice basso destro C''</font>
<FONT Color=gray>' ''Calcola lunghezze lati:''</font>
  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
<FONT Color=gray>' ''Calcola l'Incentro:''</font>
  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)
<FONT Color=gray>' ''Ruota attorno all'incentro e trasla nel centro DrawingArea:''</font>
  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
<FONT Color=gray>' ''Punto nero sul incentro:''</font>
    .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
<FONT Color=gray>' ''Vertici di un triangolo scaleno senza angoli retti:''</font>
  Dim points As New PointF[3]
  points[0] = New PointF(-160, -80)  <FONT Color=gray>' ''Vertice A''</font>
  points[1] = New PointF(210, 50)    <FONT Color=gray>' ''Vertice B''</font>
  points[2] = New PointF(50, 190)    <FONT Color=gray>' ''Vertice C''</font>
<FONT Color=gray>' ''Calcola le lunghezze dei lati:''</font>
  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
<FONT Color=gray>' ''Calcola l'incentro:''</font>
  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)
<FONT Color=gray>' ''Ruota i punti attorno all'incentro e trasla nel centro della DrawingArea:''</font>
  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
<FONT Color=gray>' ''Disegna il triangolo:''</font>
    .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
<FONT Color=gray>' ''Disegna il punto nero sull'incentro:''</font>
    .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 DrawingArea1 As DrawingArea
Private Timer1 As Timer
Private angle As Float  <FONT Color=gray>' ''Variabile globale per memorizzare l'angolo corrente della rotazione''</font>
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
  With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
    .Background = Color.White
  End With
Timer1 = New Timer As "Timer1"
  Timer1.Delay = 16
  Timer1.Start()
End
Public Sub Timer1_Timer()
<FONT Color=gray>' ''Aumenta l’angolo di rotazione:''</font>
  angle += 2
  If angle >= 360 Then angle = 0
<FONT Color=gray>' ''Richiede il ridisegno della DrawingArea:''</font>
  DrawingArea1.Refresh
End
Public Sub DrawingArea1_Draw()
<FONT Color=gray>' ''Calcola il centro della DrawingArea:''</font>
  Dim cx As Float = DrawingArea1.Width / 2
  Dim cy As Float = DrawingArea1.Height / 2
<FONT Color=gray>' ''Parametri del triangolo:''</font>
  Dim baseHalf As Float = 1.0    <FONT Color=gray>' ''Metà base''</font>
  Dim height As Float = 1.5      <FONT Color=gray>' ''Altezza del triangolo''</font>
  Dim d As Float = 4.0            <FONT Color=gray>' ''Distanza simulata dalla "camera", ossia dall'osservatore''</font>
<FONT Color=gray>' ''Angolo in radianti:''</font>
  Dim radAngle As Float = Rad(angle)
<FONT Color=gray>' ''Definizione dei 3 vertici del triangolo in coordinate 3D (x, y, z):''</font>
  Dim v1 As Float[] = [0.0, height / 2, 0.0]        <FONT Color=gray>' ''Vertice superiore''</font>
  Dim v2 As Float[] = [-baseHalf, -height / 2, 0.0]  <FONT Color=gray>' ''Vertice sinistro della base''</font>
  Dim v3 As Float[] = [baseHalf, -height / 2, 0.0]  <FONT Color=gray>' ''Vertice destro della base''</font>
<FONT Color=gray>' ''Applica la rotazione 3D attorno all’asse Y, quindi proietta in 2D:''</font>
  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)
<FONT Color=gray>' ''Costruisce un array di coordinate [x0, y0, x1, y1, x2, y2]:''</font>
  Dim coords As Float[] = [p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y]
<FONT Color=gray>' ''Disegna e riempie il triangolo:''</font>
  Paint.Brush = Paint.Color(Color.Red)  <FONT Color=gray>' ''Imposta il colore rosso''</font>
  Paint.Polygon(coords)                <FONT Color=gray>' ''Definisce la forma''</font>
  Paint.Fill()                          <FONT Color=gray>' ''Riempe il triangolo''</font>
End
Private Function RotateY(v As Float[], angle As Float) As Float[]  <FONT Color=gray>' ''Funzione che ruota un punto 3D attorno all’asse Y''</font>
 
  Dim x As Float = v[0]
  Dim y As Float = v[1]
  Dim z As Float = v[2]
<FONT Color=gray>' ''Formula di rotazione attorno all'asse Y:''</font>
  Dim xr As Float = x * Cos(angle) + z * Sin(angle)
  Dim zr As Float = -x * Sin(angle) + z * Cos(angle)
<FONT Color=gray>' ''Restituisce il punto ruotato:''</font>
  Return [xr, y, zr]
End
Private Function Project3D(v As Float[], d As Float, cx As Float, cy As Float) As PointF  <FONT Color=gray>' ''Funzione che proietta un punto 3D nello spazio 2D (prospettiva)''</font>
  Dim x As Float = v[0]
  Dim y As Float = v[1]
  Dim z As Float = v[2]
<FONT Color=gray>' ''Fattore di proiezione prospettica (più z è grande, più il punto è vicino):''</font>
  Dim factor As Float = d / (z + d + 0.001)  ' +0.001 per evitare divisione per zero
<FONT Color=gray>' ''Coordinate proiettate in 2D:''</font>
  Dim x2D As Float = x * factor
  Dim y2D As Float = y * factor
<FONT Color=gray>' ''Trasla e scala nel sistema della DrawingArea (inverte Y per avere l'alto verso l'alto):''</font>
  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:
Private DrawingArea1 As DrawingArea
Private Timer1 As Timer
<FONT Color=gray>' ''Variabili globali per gli angoli di rotazione su ciascun asse:''</font>
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
  With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
    .Background = Color.White
  End With
  Timer1 = New Timer As "Timer1"
  Timer1.Delay = 16
  Timer1.Start()
End
Public Sub Timer1_Timer()
<FONT Color=gray>' ''Aumenta l’angolo di rotazione:''</font>
  angleX += 1            <FONT Color=gray>' ''Ruota di 1 grado sull'asse X''</font>
  angleY += 2            <FONT Color=gray>' ''Ruota di 2 gradi sull'asse Y''</font>
  angleZ += 1.5          <FONT Color=gray>' ''Ruota di 1.5 gradi sull'asse Z''</font>
 
<FONT Color=gray>' ''Richiede il ridisegno della DrawingArea:''</font>
  DrawingArea1.Refresh
End
Public Sub DrawingArea1_Draw()
<FONT Color=gray>' ''Centro della DrawingArea (origine della scena):''</font>
  Dim cx As Float = DrawingArea1.Width / 2
  Dim cy As Float = DrawingArea1.Height / 2
<FONT Color=gray>' ''Dimensioni del triangolo:''</font>
  Dim baseHalf As Float = 2.0      <FONT Color=gray>' ''metà della base (±x)''</font>
  Dim height As Float = 3.0        <FONT Color=gray>' ''altezza verticale''</font>
  Dim d As Float = 4.0              <FONT Color=gray>' ''distanza "camera", ossia dell'osservatore, per simulare la prospettiva''</font>
<FONT Color=gray>' ''Converte gli angoli da gradi a radianti (richiesto per Sin/Cos):''</font>
  Dim ax As Float = Rad(angleX)
  Dim ay As Float = Rad(angleY)
  Dim az As Float = Rad(angleZ)
<FONT Color=gray>' ''Vertici iniziali del triangolo in 3D (sul piano XZ):''</font>
  Dim v1 As Float[] = [0.0, height / 2, 0.0]        <FONT Color=gray>' ''vertice superiore (centro in alto)''</font>
  Dim v2 As Float[] = [-baseHalf, -height / 2, 0.0]  <FONT Color=gray>' ''vertice base sinistra''</font>
  Dim v3 As Float[] = [baseHalf, -height / 2, 0.0]  <FONT Color=gray>' ''vertice base destra''</font>
<FONT Color=gray>' ''Applica rotazione 3D a ciascun vertice: prima X, poi Y, poi Z:''</font>
  v1 = RotateZ(RotateY(RotateX(v1, ax), ay), az)
  v2 = RotateZ(RotateY(RotateX(v2, ax), ay), az)
  v3 = RotateZ(RotateY(RotateX(v3, ax), ay), az)
<FONT Color=gray>' ''Proietta i vertici ruotati da 3D → 2D (con prospettiva):''</font>
  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)
<FONT Color=gray>' ''Costruisce l'array di coordinate 2D [x0, y0, x1, y1, x2, y2]:''</font>
  Dim coords As Float[] = [p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y]
<FONT Color=gray>' ''Disegna e riempie il triangolo con colore rosso:''</font>
  Paint.Brush = Paint.Color(Color.Red)
  Paint.Polygon(coords)  <FONT Color=gray>' ''Definisce il contorno''</font>
  Paint.Fill()            <FONT Color=gray>' ''Riempe il triangolo''</font>
End
Private Function RotateX(v As Float[], angle As Float) As Float[]  <FONT Color=gray>' ''Ruota un punto attorno all'asse X (varia y, z)''</font>
  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[]  <FONT Color=gray>' ''Ruota un punto attorno all'asse Y (varia x, z)''</font>
  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[]  <FONT Color=gray>' ''Ruota un punto attorno all'asse Z (varia x, y)''</font>
  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  <FONT Color=gray>' ''Proietta un punto 3D in coordinate 2D con prospettiva''</font>
  Dim x As Float = v[0]
  Dim y As Float = v[1]
  Dim z As Float = v[2]
<FONT Color=gray>' ''Calcola il fattore di scala prospettico:''</font>
  Dim factor As Float = d / (z + d + 0.001)  <FONT Color=gray>' ''Evita divisione per 0''</font>
<FONT Color=gray>' ''Proietta x e y in base alla profondità (z):''</font>
  Dim x2D As Float = x * factor
  Dim y2D As Float = y * factor
<FONT Color=gray>' ''Trasla e scala nel sistema di coordinate della DrawingArea:''</font>
  Return New PointF(cx + x2D * 100, cy - y2D * 100)  <FONT Color=gray>' ''*100 = scala visiva''</font>
End






----
=Note=
=Note=
[1] Vedere anche queste pagine:
[1] Vedere anche queste pagine:
* [[Ruotare_un_cerchio_disegnato_in_una_DrawingArea|Ruotare un cerchio disegnato in una DrawingArea]]
* [[Ruotare un cerchio disegnato in una DrawingArea]]
* [[Ruotare_un_quadrato_ed_un_rettangolo_in_una_DrawingArea|Ruotare un quadrato ed un rettangolo in una DrawingArea]]
* [[Ruotare un quadrato ed un rettangolo in una DrawingArea]]
* [[Ruotare_qualsiasi_elemento_da_disegnare_in_una_DrawingArea|Ruotare qualsiasi elemento da disegnare in una DrawingArea]]
* [[Ruotare qualsiasi elemento da disegnare in una DrawingArea]]
* [[Ruotare_una_immagine_sul_proprio_asse_centrale|Ruotare una immagine sul proprio asse centrale]]
* [[Ruotare una immagine sul proprio asse centrale]]

Versione attuale delle 18:50, 10 ago 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.
' Giacché 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 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 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 DrawingArea1 As DrawingArea
Private Timer1 As Timer
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
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

Timer1 = New Timer As "Timer1"
 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

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:

Private DrawingArea1 As DrawingArea
Private Timer1 As Timer

' 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
 With DrawingArea1 = New DrawingArea(Me) As "DrawingArea1"
   .Background = Color.White
 End With

 Timer1 = New Timer As "Timer1"
 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 = 2.0       ' metà della base (±x)
 Dim height As Float = 3.0         ' 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

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: