Finito il primo script per l'importazione della mappa lunare DTMTCO_02_00823N200E0310SC pubblicata dalla JAXA.
Allego la schermata
Come si vede molto semplice, ma funzionante.
Adesso scala il modello in automatico, e le normali sono corrette.
Basta inserire le coordinate della zona che interessa, controllare il numero di vertici che ne risulta e premere Importa.
L'unica mancanza è la possibilità di scegliere il file, per ora è scritto direttamente dentro lo script.
Da qui potete scaricare il file con lo script.
Dal prossimo post, inizierò a lavorare sul dataset a più alta definizione, sempre della sonda Kaguya, ci vorrà un po' di tempo in quanto il formato è completamente diverso, e c'è da gestire la texture.
Ciao
VB
Visualizzazione post con etichetta Kaguya. Mostra tutti i post
Visualizzazione post con etichetta Kaguya. Mostra tutti i post
sabato 27 marzo 2010
Alta risoluzione
Ci ho messo un po' di tempo perché nella routine che disegna la sfera c'era qualcosa che non andava e son diventato matto a cercare un routine corretta, adesso il problema l'ho risolto.
Quindi prima di iniziare la parte relativa all'interfaccia riscriviamo la routine precedente.
In questo caso ho fatto che passare direttamente alla risoluzione massima (leggo tutti i punti), ma limito l'importazione a una parte della luna. Per ora gli estremi da visualizzare sono all'interno dello script, basta indicare latitudine iniziale, latitudine finale, longitudine iniziale e longitudine finale.
Questo è il risultato (clicca sull'immagine per un ingrandimento):
Questa è la metà destra della luna.come si vede dalla terra, tagliando una fetta sopra e una fetta sotto. E' il massimo che riesco a riprodurre, se aumento ancora i punti Blender va in crash per problemi di memoria.
Qui sotto lo script, non credo servano molti commenti in quanto penso di averlo documentata in maniera sufficiente.
Una volta eseguito lo script, bisogna scalarlo (io lo scalo di 0.001) e bisogna anche ricalcolare le normali, ci deve essere un errore nella routine che unisce i vertici.
Se qualcuno sa come fare da Python queste 2 operazioni me lo faccia sapere così correggo.
Per vedere la luna come la vediamo dalla terra, bisogna mettere la visuale dall'alto.
import math, array, bpy, Blender
from Blender import *
#Dati prelevati direttamente dal file
GRID_RES=0.0625 #Risoluzione della griglia
START_LONG=0.03125 #Prima longitudine
START_LAT=89.96875 #Prima Latitudine
RAGGIO_LUNA=1737.4 #Raggio della luna
PUNTI=5760 #Numero di punti per ogni riga
#Tutte le funzioni trigonometriche utilizzano i radianti.
#er trasformare gradi in radianti basta moltiplicare per Pi greco/180
TO_RAD=math.pi/180 #Serve per trasformare i gradi in radianti
Vertici=[] #Array che conterra' i vertici da disegnare
Facce=[] #Array che conterra' l'ordine dei vertici per creare le facce
DatiAltezza=[] #Array che contiene tutti i dati del file
#Dando un valore di longitudine
#restituisce il numero del punto piu' vicino in
#maniera da far sempre riferimento a una longitudinhe valida
def Punto(Long):
return round((Long-START_LONG)/GRID_RES+1)
#Dando un valore di latitudine
#restituisce il numero della linea piu' vicina in
#maniera da far sempre riferimento a una latitudine valida
def Linea(Lat):
return round((START_LAT-Lat)/GRID_RES+1)
#Dando un numero di linea restituisce la latitudine
def Lat(Linea):
return START_LAT-(Linea-1)*GRID_RES
#Dando un punto restituisce la longitudine
def Long(Punto):
return START_LONG+(Punto-1)*GRID_RES
#Dando una latitudine e una longitudine
#restituisce l'altezza di quella coordinata
def Altezza(Lat,Long):
return DatiAltezza[int((Linea(Lat)-1)*PUNTI+Punto(Long))]
def LeggoFile(NomeFile):
#Apro il file con i dati
f=open(NomeFile,'rb')
#Leggo i primi 9558 byte per posizionarmi sul primo byte di dati
DatiLetti=f.read(9558)
#Leggo fino alla fine del file
DatiLetti=f.read()
#Assegno i dati letti in un array di tipo float
DatiTemp=array.array("f",DatiLetti)
f.close
return DatiTemp
#Questa funzione disegna la luna
def DisegnaLuna(Da_Lat, A_Lat, Da_Long, A_Long):
tmpDa_Long=Da_Long
#Calcolo il numero di linee da leggere
NumeroLinee=int(Linea(A_Lat)-Linea(Da_Lat)+1)
#Calcolo il numero di punti da leggere
NumeroPunti=int(Punto(A_Long)-Punto(Da_Long)+1)
while (Da_Lat>=A_Lat): #Loop dalla prima all'ultima latitudine
while (Da_Long<=A_Long): #Loop dalla prima all'ultima longitudine
Raggio=Altezza(Da_Lat,Da_Long)+RAGGIO_LUNA
RaggioCorrente=Raggio*(math.cos(Da_Lat*TO_RAD))
X=RaggioCorrente*(math.sin(Da_Long*TO_RAD))
Y=Raggio*math.sin(Da_Lat*TO_RAD)
Z=RaggioCorrente*math.cos(Da_Long*TO_RAD)
#Assegna le coordinate al vertice
Vertici.append((float(X),float(Y),float(Z)))
Da_Long = Da_Long+GRID_RES
Da_Long=tmpDa_Long
Da_Lat=Da_Lat-GRID_RES
#Disegno i vertici
me=Mesh.New('Luna')
me.verts.extend(Vertici)
#Loop per creare le facce
for Linee in range(1,NumeroLinee):
for Punti in range(1, NumeroPunti):
v1=Punti+(Linee-1)*NumeroPunti
v2=v1-1
v3=v1+NumeroPunti-1
v4=v3+1
Facce.append((v1,v2,v3,v4))
me.faces.extend(Facce)
Scene.GetCurrent().objects.new(me,"Luna")
Blender.Redraw()
DatiAltezza=None
#Qui inizia il programma
#Leggo i dati dal file e li inserisco nell'array
DatiAltezza=LeggoFile("E:\Apollo 11\Mappa completa\LALT_GGT_MAP.IMG")
#I valori indicati qua rappresentano la zona che ci interessa disegnare
#Le latitudini vanno dalla piu' grande alla piu' piccola
#le longitudini vanno dalla piu' piccola alla piu' grande
Zona di atterraggio dell'Apollo 11 Confrontata con un'immagine reale da telescopio (qui il link all'originale della NASA)
Ciao
VB
Quindi prima di iniziare la parte relativa all'interfaccia riscriviamo la routine precedente.
In questo caso ho fatto che passare direttamente alla risoluzione massima (leggo tutti i punti), ma limito l'importazione a una parte della luna. Per ora gli estremi da visualizzare sono all'interno dello script, basta indicare latitudine iniziale, latitudine finale, longitudine iniziale e longitudine finale.
Questo è il risultato (clicca sull'immagine per un ingrandimento):
Questa è la metà destra della luna.come si vede dalla terra, tagliando una fetta sopra e una fetta sotto. E' il massimo che riesco a riprodurre, se aumento ancora i punti Blender va in crash per problemi di memoria.
Qui sotto lo script, non credo servano molti commenti in quanto penso di averlo documentata in maniera sufficiente.
Una volta eseguito lo script, bisogna scalarlo (io lo scalo di 0.001) e bisogna anche ricalcolare le normali, ci deve essere un errore nella routine che unisce i vertici.
Se qualcuno sa come fare da Python queste 2 operazioni me lo faccia sapere così correggo.
Per vedere la luna come la vediamo dalla terra, bisogna mettere la visuale dall'alto.
import math, array, bpy, Blender
from Blender import *
#Dati prelevati direttamente dal file
GRID_RES=0.0625 #Risoluzione della griglia
START_LONG=0.03125 #Prima longitudine
START_LAT=89.96875 #Prima Latitudine
RAGGIO_LUNA=1737.4 #Raggio della luna
PUNTI=5760 #Numero di punti per ogni riga
#Tutte le funzioni trigonometriche utilizzano i radianti.
#er trasformare gradi in radianti basta moltiplicare per Pi greco/180
TO_RAD=math.pi/180 #Serve per trasformare i gradi in radianti
Vertici=[] #Array che conterra' i vertici da disegnare
Facce=[] #Array che conterra' l'ordine dei vertici per creare le facce
DatiAltezza=[] #Array che contiene tutti i dati del file
#Dando un valore di longitudine
#restituisce il numero del punto piu' vicino in
#maniera da far sempre riferimento a una longitudinhe valida
def Punto(Long):
return round((Long-START_LONG)/GRID_RES+1)
#Dando un valore di latitudine
#restituisce il numero della linea piu' vicina in
#maniera da far sempre riferimento a una latitudine valida
def Linea(Lat):
return round((START_LAT-Lat)/GRID_RES+1)
#Dando un numero di linea restituisce la latitudine
def Lat(Linea):
return START_LAT-(Linea-1)*GRID_RES
#Dando un punto restituisce la longitudine
def Long(Punto):
return START_LONG+(Punto-1)*GRID_RES
#Dando una latitudine e una longitudine
#restituisce l'altezza di quella coordinata
def Altezza(Lat,Long):
return DatiAltezza[int((Linea(Lat)-1)*PUNTI+Punto(Long))]
def LeggoFile(NomeFile):
#Apro il file con i dati
f=open(NomeFile,'rb')
#Leggo i primi 9558 byte per posizionarmi sul primo byte di dati
DatiLetti=f.read(9558)
#Leggo fino alla fine del file
DatiLetti=f.read()
#Assegno i dati letti in un array di tipo float
DatiTemp=array.array("f",DatiLetti)
f.close
return DatiTemp
#Questa funzione disegna la luna
def DisegnaLuna(Da_Lat, A_Lat, Da_Long, A_Long):
tmpDa_Long=Da_Long
#Calcolo il numero di linee da leggere
NumeroLinee=int(Linea(A_Lat)-Linea(Da_Lat)+1)
#Calcolo il numero di punti da leggere
NumeroPunti=int(Punto(A_Long)-Punto(Da_Long)+1)
while (Da_Lat>=A_Lat): #Loop dalla prima all'ultima latitudine
while (Da_Long<=A_Long): #Loop dalla prima all'ultima longitudine
Raggio=Altezza(Da_Lat,Da_Long)+RAGGIO_LUNA
RaggioCorrente=Raggio*(math.cos(Da_Lat*TO_RAD))
X=RaggioCorrente*(math.sin(Da_Long*TO_RAD))
Y=Raggio*math.sin(Da_Lat*TO_RAD)
Z=RaggioCorrente*math.cos(Da_Long*TO_RAD)
#Assegna le coordinate al vertice
Vertici.append((float(X),float(Y),float(Z)))
Da_Long = Da_Long+GRID_RES
Da_Long=tmpDa_Long
Da_Lat=Da_Lat-GRID_RES
#Disegno i vertici
me=Mesh.New('Luna')
me.verts.extend(Vertici)
#Loop per creare le facce
for Linee in range(1,NumeroLinee):
for Punti in range(1, NumeroPunti):
v1=Punti+(Linee-1)*NumeroPunti
v2=v1-1
v3=v1+NumeroPunti-1
v4=v3+1
Facce.append((v1,v2,v3,v4))
me.faces.extend(Facce)
Scene.GetCurrent().objects.new(me,"Luna")
Blender.Redraw()
DatiAltezza=None
#Qui inizia il programma
#Leggo i dati dal file e li inserisco nell'array
DatiAltezza=LeggoFile("E:\Apollo 11\Mappa completa\LALT_GGT_MAP.IMG")
#I valori indicati qua rappresentano la zona che ci interessa disegnare
#Le latitudini vanno dalla piu' grande alla piu' piccola
#le longitudini vanno dalla piu' piccola alla piu' grande
DisegnaLuna(Lat(Linea(-30)),Lat(Linea(-50)),Long(Punto(340)),Long(Punto(360)))
Zona di atterraggio dell'Apollo 11 Confrontata con un'immagine reale da telescopio (qui il link all'originale della NASA)
Ciao
VB
giovedì 18 marzo 2010
Un po' di matematica, ma non solo
Non spaventiamoci, ma per capire come fare una mappa 3D da dei dati altimetrici, dobbiamo conoscere almeno come rappresentare graficamente una sfera in uno spazio 3D.
La formula per fare ciò è la seguente:
X, Y e Z rappresentano le coordinate del punto da disegnare
X0, Y0, Z0 rappresentano le coordinate del centro della sfera
r rappresenta il raggio della sfera.
Theta (il simbolo con il trattino orizzontale) e Phi (il simbolo con il trattino verticale) rappresentano rispettivamente la latitudine e la longitudine del punto.
Ora assegnando a Theta un valore che va da 0 a Pi greco e a Phi un valore che va da -Pi greco a Pi greco, otteniamo un serie di punti che rappresentano la nostra sfera, importando questi punti in Blender otteniamo un risultato come questo:
Per chi conosce un minimo di programmazione questo si può fare con 2 semplici loop annidati uno dentro l'altro.
Per importare dei punti in Blender, la soluzione più semplice è utilizzare il formato OBJ, praticamente un formato testo composto da tante righe quanti sono i punti da disegnare, ogni riga, se contiene le coordinate di un punto, inizia con la lettera v seguita dalle 3 coordinate x,y e z separando i vari campi con uno spazio.
Esempio di 3 vertici::
v 0 0 2
v 2,126506617006E-17 -0,347296355333861 1,96961550602442
v 4,18840040651854E-17 -0,684040286651337 1,87938524157182
Edit del 20/03/2010
Fine Edit
Qui c'è una semplice routine scritta in Visual Basic per generare il file da importare in Blender, facilmente adattabile in altri inguaggi. L'unica variante è che anzichè i radianti sono stati usati i gradi.
Ora vediamo come vengono effettuati i rilievi altimetrici per la ricostruzione dellle mappe 3D.
Il satellite gira intorno alla luna a una distanza fissa, emettendo, a intervalli regolari un impulso laser che rimbalza sul terreno e torna indietro. Il tempo che ci mette a andare e tornare permette di calcolare la distanza fra il satellite e il terreno sottostante, meno tempo ci mette più il punto è elevato. Man mano che il satellite compie delle orbite attorno alla luna i punti rilevati aumentano permettendo di migliorare la qualità della mappa, ma rendendo estremamente pesante da elaborare i dati
Per dare un'idea, la Jaxa ha rilasciato una mappa completa della luna a bassa risoluzione composta da 16588800 punti (2880 linee composta ognuna da 5760 punti), questo significa che ogni punto dista dall'altro poco meno di 2 Km, ottimo per una visione completa della luna, ma scarsa per dei dettagli ravvicinati.
Per dare un'idea questa immagine e composta da 160x160 punti rappresenta la zona di allunaggio dell'Apollo 11. La zona è più di 300 Km per lato.
Naturalmente questa è una semplificazione, in quanto per funzionare correttamente, la sonda deve sapere esattamente dov'è rispetto alla luna, e sulla luna il GPS non funziona, inoltre per ridurre gli errori si deve tenere conto della temperatura di tutta l'attrezzatura, in quanto al variare della temperatura i dati rilevati non sono più omogenei.
Ciao
VB
La formula per fare ciò è la seguente:
X, Y e Z rappresentano le coordinate del punto da disegnare
X0, Y0, Z0 rappresentano le coordinate del centro della sfera
r rappresenta il raggio della sfera.
Theta (il simbolo con il trattino orizzontale) e Phi (il simbolo con il trattino verticale) rappresentano rispettivamente la latitudine e la longitudine del punto.
Ora assegnando a Theta un valore che va da 0 a Pi greco e a Phi un valore che va da -Pi greco a Pi greco, otteniamo un serie di punti che rappresentano la nostra sfera, importando questi punti in Blender otteniamo un risultato come questo:
Per chi conosce un minimo di programmazione questo si può fare con 2 semplici loop annidati uno dentro l'altro.
Per importare dei punti in Blender, la soluzione più semplice è utilizzare il formato OBJ, praticamente un formato testo composto da tante righe quanti sono i punti da disegnare, ogni riga, se contiene le coordinate di un punto, inizia con la lettera v seguita dalle 3 coordinate x,y e z separando i vari campi con uno spazio.
Esempio di 3 vertici::
v 0 0 2
v 2,126506617006E-17 -0,347296355333861 1,96961550602442
v 4,18840040651854E-17 -0,684040286651337 1,87938524157182
Edit del 20/03/2010
Qui una routine in pyton da utilizzare direttamente dentro Blender 2.49.
Per utilizzarla:
Selezionare la finestra Text editor
Premere Alt N
Incollare il codice
Eseguire premendo Alt P
import Blender
from Blender import *
import bpy
import math #Importa le funzioni trigonometriche
passo=float(math.pi/20)
vertice=[]
me = bpy.data.meshes.new('myMesh') # crea una nuova mesh
for i in range(0, 20):
for j in range(0,40):
x=math.sin(-math.pi+j*passo)*math.cos(i*passo)
y=math.sin(-math.pi+j*passo)*math.sin(i*passo)
z=math.cos(-math.pi+j*passo)
vertice.append((float(x),float(y),float(z)))
me = Mesh.New('Sfera')
me.verts.extend(vertice)
Scene.GetCurrent().objects.new(me,"Sfera")
Blender.Redraw()
from Blender import *
import bpy
import math #Importa le funzioni trigonometriche
passo=float(math.pi/20)
vertice=[]
me = bpy.data.meshes.new('myMesh') # crea una nuova mesh
for i in range(0, 20):
for j in range(0,40):
x=math.sin(-math.pi+j*passo)*math.cos(i*passo)
y=math.sin(-math.pi+j*passo)*math.sin(i*passo)
z=math.cos(-math.pi+j*passo)
vertice.append((float(x),float(y),float(z)))
me = Mesh.New('Sfera')
me.verts.extend(vertice)
Scene.GetCurrent().objects.new(me,"Sfera")
Blender.Redraw()
Qui c'è una semplice routine scritta in Visual Basic per generare il file da importare in Blender, facilmente adattabile in altri inguaggi. L'unica variante è che anzichè i radianti sono stati usati i gradi.
Ora vediamo come vengono effettuati i rilievi altimetrici per la ricostruzione dellle mappe 3D.
Il satellite gira intorno alla luna a una distanza fissa, emettendo, a intervalli regolari un impulso laser che rimbalza sul terreno e torna indietro. Il tempo che ci mette a andare e tornare permette di calcolare la distanza fra il satellite e il terreno sottostante, meno tempo ci mette più il punto è elevato. Man mano che il satellite compie delle orbite attorno alla luna i punti rilevati aumentano permettendo di migliorare la qualità della mappa, ma rendendo estremamente pesante da elaborare i dati
Per dare un'idea, la Jaxa ha rilasciato una mappa completa della luna a bassa risoluzione composta da 16588800 punti (2880 linee composta ognuna da 5760 punti), questo significa che ogni punto dista dall'altro poco meno di 2 Km, ottimo per una visione completa della luna, ma scarsa per dei dettagli ravvicinati.
Per dare un'idea questa immagine e composta da 160x160 punti rappresenta la zona di allunaggio dell'Apollo 11. La zona è più di 300 Km per lato.
Naturalmente questa è una semplificazione, in quanto per funzionare correttamente, la sonda deve sapere esattamente dov'è rispetto alla luna, e sulla luna il GPS non funziona, inoltre per ridurre gli errori si deve tenere conto della temperatura di tutta l'attrezzatura, in quanto al variare della temperatura i dati rilevati non sono più omogenei.
Ciao
VB
Etichette:
Blender,
Jaxa,
Kaguya,
matematica,
Sfera,
Visual Basic
mercoledì 17 marzo 2010
Perché questo BLOG?
Da qualche giorno la NASA ha iniziato a pubblicare i dati della sonda LRO.
Siccome qualche tempo fa mi sono divertito a cercare di ricreare in 3D porzioni della luna utilizzando i dati della sonda Kaguya elaborandoli con Blender, ho deciso di provarci in maniera un po' più articolata.
In questo blog riporterò esperimenti, risultati, domande, link per tenerne traccia.
Qua l'esperimento meglio riuscito fino ad ora con i dati altimetrici della sonda Kaguya. Il palo rosso indica la zona approssimativa dell'atterraggio (o si dice alllunaggio?) dell'Apollo 17
Apollo 17 (2) from ValterVB on Vimeo.
Qua invece la ricostruzione fatta direttamente dalla Jaxa (Agenzia Spaziale Giapponese)
Ciao
VB
Iscriviti a:
Post (Atom)







