Ruotare una sfera in una DrawingArea: differenze tra le versioni
Vai alla navigazione
Vai alla ricerca
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
| (Una versione intermedia di uno stesso utente non è mostrata) | |||
| Riga 110: | Riga 110: | ||
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2) | Paint.Ellipse(cx - r, cy - r, r * 2, r * 2) | ||
Paint.Stroke() | Paint.Stroke() | ||
End | End | ||
Public Sub Form_KeyPress() ' Gestione della tastiera per controllare lo zoom | Public Sub Form_KeyPress() <FONT Color=gray>' ''Gestione della tastiera per controllare lo zoom''</font> | ||
Select Case Key.Code | Select Case Key.Code | ||
| Riga 131: | Riga 129: | ||
===Caricare una mappa terrestre equirettangolare=== | ===Caricare una mappa terrestre equirettangolare=== | ||
Di seguito mostreremo un codice per adattare sulla sfera una mappa terrestre equirettangolare, al fine di far apparire la sfera come il pianeta terra in rotazione. | Di seguito mostreremo un codice per adattare sulla sfera una mappa terrestre equirettangolare, al fine di far apparire la sfera come il pianeta terra in rotazione. | ||
<FONT Color=gray>' ''=== Costanti e variabili globali ===''</font> | <FONT Color=gray>' ''=== Costanti e variabili globali ===''</font> | ||
Private | Private zoom_raggio_sfera As Integer = 100 <FONT Color=gray>' ''Raggio della sfera da disegnare''</font> | ||
Private angle As Float <FONT Color=gray>' ''Angolo di rotazione attorno all’asse Y''</font> | Private angle As Float <FONT Color=gray>' ''Angolo di rotazione attorno all’asse Y''</font> | ||
Private map As Image <FONT Color=gray>' ''Mappa terrestre in proiezione equirettangolare''</font> | Private map As Image <FONT Color=gray>' ''Mappa terrestre in proiezione equirettangolare''</font> | ||
| Riga 148: | Riga 144: | ||
<FONT Color=gray>' ''Carica la mappa terrestre (proiezione equirettangolare):''</font> | <FONT Color=gray>' ''Carica la mappa terrestre (proiezione equirettangolare):''</font> | ||
map = Image.Load("<FONT Color=darkgreen>''/ | map = Image.Load("<FONT Color=darkgreen>''/percorso/del/file/immagine/proiezione-equirettangolare''</font>") | ||
<FONT Color=gray>' ''Avvia il timer con ~60 fotogrammi al secondo:''</font> | <FONT Color=gray>' ''Avvia il timer con ~60 fotogrammi al secondo:''</font> | ||
| Riga 176: | Riga 172: | ||
Dim cx As Float = DrawingArea1.Width / 2 | Dim cx As Float = DrawingArea1.Width / 2 | ||
Dim cy As Float = DrawingArea1.Height / 2 | Dim cy As Float = DrawingArea1.Height / 2 | ||
Dim r As Float = | Dim r As Float = zoom_raggio_sfera | ||
<FONT Color=gray>' ''Dimensioni dell’immagine mappa:''</font> | <FONT Color=gray>' ''Dimensioni dell’immagine mappa:''</font> | ||
| Riga 242: | Riga 238: | ||
Paint.Stroke() | Paint.Stroke() | ||
End | |||
Public Sub Form_KeyPress() <FONT Color=gray>' ''Gestione della tastiera per controllare lo zoom''</font> | |||
Select Case Key.Code | |||
Case Key["+"] | |||
zoom_raggio_sfera = Min(zoom_raggio_sfera + 25, 1000) | |||
Case Key["-"] | |||
zoom_raggio_sfera = Max(zoom_raggio_sfera - 25, 25) | |||
End Select | |||
DrawingArea1.Refresh | |||
End | End | ||
Versione attuale delle 18:54, 10 ago 2025
Di seguito mostreremo un possibile codice per ottenere l'effetto di una sfera che ruota in senso antiorario.
' Costanti per raggio della sfera e numero di punti visibili:
Private Const NUM_POINTS As Integer = 200
Private Zoom_Raggio_Sfera As Integer = 100
' Angolo di rotazione della sfera (in radianti):
Private angle As Float
' Array contenente i punti 3D generati sulla superficie della sfera
' Ogni elemento è un array [x, y, z] normalizzato:
Private spherePoints As Float[][]
Public Sub Form_Open()
With Me
.Title = "Sfera che ruota in senso antiorario"
.Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
.Arrangement = Arrange.Fill
End With
Timer1.Delay = 16 ' ~60 FPS
Timer1.Start
' Inizializza l'array dei punti:
spherePoints = New Float[][NUM_POINTS]
Dim i As Integer
Dim theta, phi As Float
Dim x, y, z As Float
' Generazione casuale dei punti distribuiti sulla superficie della sfera:
For i = 0 To NUM_POINTS - 1
theta = Rnd(0, 2 * Pi) ' Angolo longitudinale (orizzontale)
phi = Acos(Rnd(-1, 1)) ' Angolo latitudinale (verticale)
' Conversione da coordinate sferiche a coordinate cartesiane:
x = Sin(phi) * Cos(theta)
y = Cos(phi)
z = Sin(phi) * Sin(theta)
' Salvataggio del punto normalizzato nell'array:
spherePoints[i] = [x, y, z]
Next
End
Public Sub Timer1_Timer()
' Rotazione sull'asse Y:
angle += 0.02
DrawingArea1.Refresh
End
Public Sub DrawingArea1_Draw()
' Coordinate del centro della sfera nella DrawingArea:
Dim cx As Float = DrawingArea1.Width / 2
Dim cy As Float = DrawingArea1.Height / 2
Dim r As Float = Zoom_Raggio_Sfera
' Variabili per il ciclo:
Dim i As Integer
Dim p As Float[]
Dim x, y, z As Float
Dim xRot, zRot As Float
Dim sx, sy As Float
' === Disegno del disco blu di base ===
Paint.Brush = Paint.Color(Color.RGB(0, 80, 160))
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2) ' Cerchio centrato
Paint.Fill()
' === Disegno dei punti bianchi "ruotati" ===
For i = 0 To NUM_POINTS - 1
' Estrae il punto dalla lista:
p = spherePoints[i]
x = p[0]
y = p[1]
z = p[2]
' Rotazione attorno all’asse Y.
' Simula la rotazione della sfera da sinistra a destra:
xRot = x * Cos(angle) + z * Sin(angle)
zRot = -x * Sin(angle) + z * Cos(angle)
' Mostra solo i punti "davanti" alla sfera (zRot > 0):
If zRot > 0 Then
' Proiezione del punto 3D sulla 2D DrawingArea:
sx = cx + xRot * r
sy = cy + y * r
' Disegna un piccolo punto bianco (2x2 pixel):
Paint.Brush = Paint.Color(Color.White)
Paint.Ellipse(sx - 1, sy - 1, 2, 2)
Paint.Fill()
Endif
Next
' === Disegna il bordo della sfera ===
Paint.Brush = Paint.Color(&H000000) ' Nero
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2)
Paint.Stroke()
End
Public Sub Form_KeyPress() ' Gestione della tastiera per controllare lo zoom
Select Case Key.Code
Case Key["+"]
Zoom_Raggio_Sfera = Min(Zoom_Raggio_Sfera + 25, 1000)
Case Key["-"]
Zoom_Raggio_Sfera = Max(Zoom_Raggio_Sfera - 25, 25)
End Select
DrawingArea1.Refresh
End
Caricare una mappa terrestre equirettangolare
Di seguito mostreremo un codice per adattare sulla sfera una mappa terrestre equirettangolare, al fine di far apparire la sfera come il pianeta terra in rotazione.
' === Costanti e variabili globali ===
Private zoom_raggio_sfera As Integer = 100 ' Raggio della sfera da disegnare
Private angle As Float ' Angolo di rotazione attorno all’asse Y
Private map As Image ' Mappa terrestre in proiezione equirettangolare
Public Sub Form_Open()
With Me
.Title = "Sfera rotante con mappa terrestre in proiezione equirettangolare"
.Move(0, 0, Screen.AvailableWidth, Screen.AvailableHeight)
.Arrangement = Arrange.Fill
End With
' Carica la mappa terrestre (proiezione equirettangolare):
map = Image.Load("/percorso/del/file/immagine/proiezione-equirettangolare")
' Avvia il timer con ~60 fotogrammi al secondo:
Timer1.Delay = 16
Timer1.Start
End
Public Sub Timer1_Timer()
' Incrementa l’angolo di rotazione (in radianti):
angle += 0.05
' Mantiene l’angolo entro 0–2π:
If angle > 2 * Pi Then angle = 0
' Richiede il ridisegno della DrawingArea:
DrawingArea1.Refresh
End
Public Sub DrawingArea1_Draw()
' Centro della sfera nella finestra:
Dim cx As Float = DrawingArea1.Width / 2
Dim cy As Float = DrawingArea1.Height / 2
Dim r As Float = zoom_raggio_sfera
' Dimensioni dell’immagine mappa:
Dim imgW As Integer = map.Width
Dim imgH As Integer = map.Height
' Variabili per lat/lon, rotazione e proiezione:
Dim u, v As Float ' Coordinate normalizzate [0,1] su X e Y dell’immagine
Dim lon, lat As Float ' Coordinate geografiche in radianti
Dim x, y, z As Float ' Coordinate 3D
Dim xRot, zRot As Float ' Coordinate dopo rotazione sull’asse Y
Dim sx, sy As Float ' Coordinate proiettate 2D
Dim i, j As Integer
Dim cosA, sinA As Float
Dim mapColor As Integer
' Calcola seno e coseno dell’angolo per ottimizzazione:
cosA = Cos(angle)
sinA = Sin(angle)
' Disegna sfondo blu (la sfera base):
Paint.Brush = Paint.Color(Color.RGB(0, 80, 160))
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2)
Paint.Fill()
' === Ciclo per proiettare l’immagine mappa sulla sfera ===
For j = 0 To imgH Step 2
v = j / imgH ' Valore normalizzato verticale (0 = nord, 1 = sud)
lat = v * Pi ' Latitudine da 0 (nord) a Pi (sud)
y = Cos(lat) ' Coordinate verticali (asse Y cartesiano)
For i = 0 To imgW Step 2
u = i / imgW ' Valore normalizzato orizzontale (0 = ovest, 1 = est)
lon = Pi - u * 2 * Pi ' Longitudine da -Pi (est) a +Pi (ovest)
' Conversione sferica → cartesiana (raggio = 1)
x = Sin(lat) * Cos(lon)
z = Sin(lat) * Sin(lon)
' Rotazione attorno all’asse Y (trasformazione 3D)
xRot = x * cosA + z * sinA
zRot = -x * sinA + z * cosA
' Disegna solo i punti "visibili", cioè con zRot > 0:
If zRot > 0 Then
' Proiezione 2D sul piano dello schermo:
sx = cx + xRot * r
sy = cy - y * r ' Invertito perché Y su schermo cresce verso il basso
' Campiona il colore dalla mappa:
mapColor = map[i, j]
' Disegna un punto colorato (pixel 1x1):
Paint.Brush = Paint.Color(mapColor)
Paint.Ellipse(sx, sy, 1, 1)
Paint.Fill()
Endif
Next
Next
' Disegna bordo nero della sfera:
Paint.Brush = Paint.Color(&H000000)
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2)
Paint.Stroke()
End
Public Sub Form_KeyPress() ' Gestione della tastiera per controllare lo zoom
Select Case Key.Code
Case Key["+"]
zoom_raggio_sfera = Min(zoom_raggio_sfera + 25, 1000)
Case Key["-"]
zoom_raggio_sfera = Max(zoom_raggio_sfera - 25, 25)
End Select
DrawingArea1.Refresh
End