Ruotare una sfera in una DrawingArea: differenze tra le versioni
Vai alla navigazione
Vai alla ricerca
(Creata pagina con "Di seguito mostreremo un possibile codice per ottenere l'effetto di una sfera che ruota in senso antiorario. <FONT Color=gray>' ''Costanti per raggio della sfera e numero di...") |
Nessun oggetto della modifica |
||
| (5 versioni intermedie di uno stesso utente non sono mostrate) | |||
| Riga 1: | Riga 1: | ||
Di seguito mostreremo un possibile codice per ottenere l'effetto di una sfera che ruota in senso antiorario. | Di seguito mostreremo un possibile codice per ottenere l'effetto di una sfera che ruota in senso antiorario. | ||
<FONT Color=gray>' ''Costanti per raggio della sfera e numero di punti visibili:''</font> | <FONT Color=gray>' ''Costanti per raggio della sfera e numero di punti visibili:''</font> | ||
Private Const NUM_POINTS As Integer = 200 | Private Const NUM_POINTS As Integer = 200 | ||
Private Zoom_Raggio_Sfera As Integer = 100 | |||
<FONT Color=gray>' ''Angolo di rotazione della sfera (in radianti):''</font> | <FONT Color=gray>' ''Angolo di rotazione della sfera (in radianti):''</font> | ||
| Riga 43: | Riga 43: | ||
spherePoints[i] = [x, y, z] | spherePoints[i] = [x, y, z] | ||
Next | Next | ||
End | |||
Public Sub Timer1_Timer() | |||
<FONT Color=gray>' ''Rotazione sull'asse Y:''</font> | |||
angle += 0.02 | |||
DrawingArea1.Refresh | |||
End | End | ||
| Riga 52: | Riga 62: | ||
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>' ''Variabili per il ciclo:''</font> | <FONT Color=gray>' ''Variabili per il ciclo:''</font> | ||
| Riga 101: | Riga 111: | ||
Paint.Stroke() | Paint.Stroke() | ||
Paint.End | 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 | |||
===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. | |||
<FONT Color=gray>' ''=== Costanti e variabili globali ===''</font> | |||
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 map As Image <FONT Color=gray>' ''Mappa terrestre in proiezione equirettangolare''</font> | |||
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 | |||
<FONT Color=gray>' ''Carica la mappa terrestre (proiezione equirettangolare):''</font> | |||
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> | |||
Timer1.Delay = 16 | |||
Timer1.Start | |||
End | |||
Public Sub Timer1_Timer() | |||
<FONT Color=gray>' ''Incrementa l’angolo di rotazione (in radianti):''</font> | |||
angle += 0.05 | |||
<FONT Color=gray>' ''Mantiene l’angolo entro 0–2π:''</font> | |||
If angle > 2 * Pi Then angle = 0 | |||
<FONT Color=gray>' ''Richiede il ridisegno della DrawingArea:''</font> | |||
DrawingArea1.Refresh | |||
End | |||
Public Sub DrawingArea1_Draw() | |||
<FONT Color=gray>' ''Centro della sfera nella finestra:''</font> | |||
Dim cx As Float = DrawingArea1.Width / 2 | |||
Dim cy As Float = DrawingArea1.Height / 2 | |||
Dim r As Float = zoom_raggio_sfera | |||
<FONT Color=gray>' ''Dimensioni dell’immagine mappa:''</font> | |||
Dim imgW As Integer = map.Width | |||
Dim imgH As Integer = map.Height | |||
<FONT Color=gray>' ''Variabili per lat/lon, rotazione e proiezione:''</font> | |||
Dim u, v As Float <FONT Color=gray>' ''Coordinate normalizzate [0,1] su X e Y dell’immagine''</font> | |||
Dim lon, lat As Float <FONT Color=gray>' ''Coordinate geografiche in radianti''</font> | |||
Dim x, y, z As Float <FONT Color=gray>' ''Coordinate 3D''</font> | |||
Dim xRot, zRot As Float <FONT Color=gray>' ''Coordinate dopo rotazione sull’asse Y''</font> | |||
Dim sx, sy As Float <FONT Color=gray>' ''Coordinate proiettate 2D''</font> | |||
Dim i, j As Integer | |||
Dim cosA, sinA As Float | |||
Dim mapColor As Integer | |||
<FONT Color=gray>' ''Calcola seno e coseno dell’angolo per ottimizzazione:''</font> | |||
cosA = Cos(angle) | |||
sinA = Sin(angle) | |||
<FONT Color=gray>' ''Disegna sfondo blu (la sfera base):''</font> | |||
Paint.Brush = Paint.Color(Color.RGB(0, 80, 160)) | |||
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2) | |||
Paint.Fill() | |||
<FONT Color=gray>' ''=== Ciclo per proiettare l’immagine mappa sulla sfera ===''</font> | |||
For j = 0 To imgH Step 2 | |||
v = j / imgH <FONT Color=gray>' ''Valore normalizzato verticale (0 = nord, 1 = sud)''</font> | |||
lat = v * Pi <FONT Color=gray>' ''Latitudine da 0 (nord) a Pi (sud)''</font> | |||
y = Cos(lat) <FONT Color=gray>' ''Coordinate verticali (asse Y cartesiano)''</font> | |||
For i = 0 To imgW Step 2 | |||
u = i / imgW <FONT Color=gray>' ''Valore normalizzato orizzontale (0 = ovest, 1 = est)''</font> | |||
lon = Pi - u * 2 * Pi <FONT Color=gray>' ''Longitudine da -Pi (est) a +Pi (ovest)''</font> | |||
<FONT Color=gray>' ''Conversione sferica → cartesiana (raggio = 1)''</font> | |||
x = Sin(lat) * Cos(lon) | |||
z = Sin(lat) * Sin(lon) | |||
<FONT Color=gray>' ''Rotazione attorno all’asse Y (trasformazione 3D)''</font> | |||
xRot = x * cosA + z * sinA | |||
zRot = -x * sinA + z * cosA | |||
<FONT Color=gray>' ''Disegna solo i punti "visibili", cioè con zRot > 0:''</font> | |||
If zRot > 0 Then | |||
<FONT Color=gray>' ''Proiezione 2D sul piano dello schermo:''</font> | |||
sx = cx + xRot * r | |||
sy = cy - y * r <FONT Color=gray>' ''Invertito perché Y su schermo cresce verso il basso''</font> | |||
<FONT Color=gray>' ''Campiona il colore dalla mappa:''</font> | |||
mapColor = map[i, j] | |||
<FONT Color=gray>' ''Disegna un punto colorato (pixel 1x1):''</font> | |||
Paint.Brush = Paint.Color(mapColor) | |||
Paint.Ellipse(sx, sy, 1, 1) | |||
Paint.Fill() | |||
Endif | |||
Next | |||
Next | |||
<FONT Color=gray>' ''Disegna bordo nero della sfera:''</font> | |||
Paint.Brush = Paint.Color(&H000000) | |||
Paint.Ellipse(cx - r, cy - r, r * 2, r * 2) | |||
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