Paste Code
Paste Blends
Paste Images
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####

bl_addon_info = {
"name": "LRO Lola & MGS Mola img Importer",
"author": "ValterVB",
"version": (0, 1, 2),
"blender": (2, 5, 6),
"api": 34043,
"location": "3D window > Tool Shelf",
"description": "Import DTM from LRO Lola and MGS Mola",
"warning": "May consume a lot of memory",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Import-Export/NASA_IMG_Importer",
"tracker_url":"http://projects.blender.org/tracker/index.php?func=detail&aid=25462&group_id=153&atid=467",
"category": "Import-Export"}

#***************************************************************
#ver. 0.0.1: -First version
#ver. 0.0.2: -Add check on path and file
# -Check on selected coordinates more complete
#ver. 1.1.0: -Optimized for less memory
#ver. 1.1.1: -Correct bug for real value of the High (bad error).
# now it's less artistic, bat more real Always possible use
# the old formula. check Exaggerate the high
# -Correct the bug for directory with dot in the name
# -Add some warning and more information
# -Add slider for the scale and info on it
#ver. 1.1.2: -Word correction
# -Correct the problem for Unix. If the Ext of the file
# selected from user is Upper, than the second file
# is Upper and Viceversa. (I can't verify)
#****************************************************************

import bpy
import os.path
import math, array, mathutils
from mathutils import *

TO_RAD=math.pi/180 #From degrees to radians

# turning off relative path - it causes an error if it was true
if bpy.context.user_preferences.filepaths.use_relative_paths == True:
bpy.context.user_preferences.filepaths.use_relative_paths = False

# A very simple "bridge" tool.
# Connects two equally long vertex rows with faces.
# Returns a list of the new faces (list of lists)
#
# vertIdx1 ... First vertex list (list of vertex indices).
# vertIdx2 ... Second vertex list (list of vertex indices).
# closed ... Creates a loop (first & last are closed).
# flipped ... Invert the normal of the face(s).
#
# Note: You can set vertIdx1 to a single vertex index to create a fan/star of faces.
# Note: If both vertex idx list are the same length they have to have at least 2 vertices.
def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
faces = []

if not vertIdx1 or not vertIdx2:
return None

if len(vertIdx1) < 2 and len(vertIdx2) < 2:
return None

fan = False
if (len(vertIdx1) != len(vertIdx2)):
if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
fan = True
else:
return None

total = len(vertIdx2)

if closed:
# Bridge the start with the end.
if flipped:
face = [
vertIdx1[0],
vertIdx2[0],
vertIdx2[total - 1]]
if not fan:
face.append(vertIdx1[total - 1])
faces.append(face)

else:
face = [vertIdx2[0], vertIdx1[0]]
if not fan:
face.append(vertIdx1[total - 1])
face.append(vertIdx2[total - 1])
faces.append(face)

# Bridge the rest of the faces.
for num in range(total - 1):
if flipped:
if fan:
face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
else:
face = [vertIdx2[num], vertIdx1[num],
vertIdx1[num + 1], vertIdx2[num + 1]]
faces.append(face)
else:
if fan:
face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
else:
face = [vertIdx1[num], vertIdx2[num],
vertIdx2[num + 1], vertIdx1[num + 1]]
faces.append(face)
return faces

#Utility Function ********************************************************
#
#Input: Latitude Output: Number of the line (1 to n)
def LatToLine(Latitude):
tmpLines=round((MAXIMUM_LATITUDE-Latitude)*MAP_RESOLUTION+1.0)
if tmpLines>LINES:tmpLines=LINES
return tmpLines

#Input: Number of the line (1 to n) Output: Latitude
def LineToLat(Line):
if MAP_RESOLUTION==0:
return 0
else:
return float(MAXIMUM_LATITUDE-(Line-1)/MAP_RESOLUTION)

#Input: Longitude Output: Number of the point (1 to n)
def LongToPoint(Longitude):
tmpPoints=round((Longitude-WESTERNMOST_LONGITUDE)*MAP_RESOLUTION+1.0)
if tmpPoints>LINE_SAMPLES:tmpPoints=LINE_SAMPLES
return tmpPoints

#Input: Number of the Point (1 to n) Output: Longitude
def PointToLong(Point):
if MAP_RESOLUTION==0:
return 0
else:
return float(WESTERNMOST_LONGITUDE+(Point-1)/MAP_RESOLUTION)

#Input: Latitude Output: Neareast real Latitude on grid
def RealLat(Latitude):
return float(LineToLat(LatToLine(Latitude)))

#Input: Longitude Output: Neareast real Longitude on grid
def RealLong(Longitude):
return float(PointToLong(LongToPoint(Longitude)))
#**************************************************************************


#Read the LBL file
def ReadLabel(FileName):
global FileAndPath
global LINES, LINE_SAMPLES, SAMPLE_TYPE, SAMPLE_BITS, UNIT, MAP_RESOLUTION, MAXIMUM_LATITUDE, MINIMUM_LATITUDE
global WESTERNMOST_LONGITUDE, EASTERNMOST_LONGITUDE, SCALING_FACTOR,OFFSET, RadiusUM, TARGET_NAME
global Message

if FileName=='':
LINES=LINE_SAMPLES=SAMPLE_BITS=MAP_RESOLUTION=0
MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=0.0
SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""
return

FileAndPath=FileName
FileAndExt=os.path.splitext(FileAndPath)
try:
#Check for UNIX that is case sensitive
#If the Ext of the file selected from user is Upper, than the second file is Upper and Viceversa
if FileAndExt[1].isupper:
f = open(FileAndExt[0] + ".LBL", 'r') #Open the label file
else:
f = open(FileAndExt[0] + ".lbl", 'r') #Open the label file
Message=""
except:
Message="FILE LBL NOT AVAILABLE OR YOU HAVEN'T SELECTED A FILE"
return

block=""
OFFSET=0
for line in f:
tmp=line.split("=")
if tmp[0].strip()=="OBJECT" and tmp[1].strip()=="IMAGE":
block="IMAGE"
elif tmp[0].strip()=="OBJECT" and tmp[1].strip()=="IMAGE_MAP_PROJECTION":
block="IMAGE_MAP_PROJECTION"
elif tmp[0].strip()=="END_OBJECT" and tmp[1].strip()=="IMAGE":
block=""
elif tmp[0].strip()=="END_OBJECT" and tmp[1].strip()=="IMAGE_MAP_PROJECTION":
block=""
elif tmp[0].strip()=="TARGET_NAME":
block=""
TARGET_NAME=tmp[1].strip()
if block=="IMAGE":
if line.find("LINES") !=-1 and not(line.startswith("/*")):
tmp=line.split("=")
LINES=int(tmp[1].strip())
elif line.find("LINE_SAMPLES") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
LINE_SAMPLES=int(tmp[1].strip())
elif line.find("UNIT") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
UNIT=tmp[1].strip()
elif line.find("SAMPLE_TYPE") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
SAMPLE_TYPE=tmp[1].strip()
elif line.find("SAMPLE_BITS") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
SAMPLE_BITS=int(tmp[1].strip())
elif line.find("SCALING_FACTOR") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
SCALING_FACTOR=float(tmp[0].replace(" ", ""))
elif line.find("OFFSET") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
if tmp[0].find("OFFSET")!=-1 and len(tmp) > 1:
tmp=tmp[1].split("<")
tmp[0]=tmp[0].replace(".", "")
OFFSET=float(tmp[0].replace(" ", ""))
elif block=="IMAGE_MAP_PROJECTION":
if line.find("A_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
A_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
RadiusUM=tmp[1].rstrip().replace(">","")
elif line.find("B_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
B_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
elif line.find("C_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
C_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
elif line.find("MAXIMUM_LATITUDE") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
MAXIMUM_LATITUDE=float(tmp[0].replace(" ", ""))
elif line.find("MINIMUM_LATITUDE") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
MINIMUM_LATITUDE=float(tmp[0].replace(" ", ""))
elif line.find("WESTERNMOST_LONGITUDE") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
WESTERNMOST_LONGITUDE=float(tmp[0].replace(" ", ""))
elif line.find("EASTERNMOST_LONGITUDE") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
EASTERNMOST_LONGITUDE=float(tmp[0].replace(" ", ""))
elif line.find("MAP_RESOLUTION") != -1 and not(line.startswith("/*")):
tmp=line.split("=")
tmp=tmp[1].split("<")
MAP_RESOLUTION=float(tmp[0].replace(" ", ""))
f.close
MAXIMUM_LATITUDE=MAXIMUM_LATITUDE-1/MAP_RESOLUTION/2
MINIMUM_LATITUDE=MINIMUM_LATITUDE+1/MAP_RESOLUTION/2
WESTERNMOST_LONGITUDE=WESTERNMOST_LONGITUDE+1/MAP_RESOLUTION/2
EASTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE-1/MAP_RESOLUTION/2
if OFFSET==0: #When OFFSET isn't available I use the medium of the radius
OFFSET=(A_AXIS_RADIUS+B_AXIS_RADIUS+C_AXIS_RADIUS)/3
else:
OFFSET=OFFSET/1000 #Convert m to Km
if SCALING_FACTOR==0: SCALING_FACTOR=1.0 #When isn'tavailable I set it to 1

def MakeMaterialMars(obj):
#Copied from io_convert_image_to_mesh_img
mat = bpy.data.materials.new("Mars")
mat.diffuse_shader = 'MINNAERT'
mat.diffuse_color=(0.426, 0.213, 0.136)
mat.darkness=0.8

mat.specular_shader = 'WARDISO'
mat.specular_color= (1.000, 0.242, 0.010)
mat.specular_intensity=0.010
mat.specular_slope= 0.100
obj.data.materials.append(mat)

def MakeMaterialMoon(obj):
#Same as Mars Material, but i have canged the color
mat = bpy.data.materials.new("Moon")
mat.diffuse_shader = 'MINNAERT'
mat.diffuse_color=(0.426, 0.426, 0.426)
mat.darkness=0.8

mat.specular_shader = 'WARDISO'
mat.specular_color= (0.6, 0.6, 0.6)
mat.specular_intensity=0.010
mat.specular_slope= 0.100
obj.data.materials.append(mat)

def clear_properties():
# can happen on reload
if bpy.context.scene is None:
return

LINES=LINE_SAMPLES=SAMPLE_BITS=0
MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=MAP_RESOLUTION=0.0
SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""

props = ["FromLat", "ToLat", "FromLong", "ToLong", "Scale"]
for p in props:
if p in bpy.types.Scene.bl_rna.properties:
exec("del bpy.types.Scene."+p)
if p in bpy.context.scene:
del bpy.context.scene[p]

#Import the data and draw the planet - NEW
class Import(bpy.types.Operator):
bl_idname = 'Import'
bl_label = 'Start Import'
bl_description = 'Import the data'

def execute(self, context):
From_Lat=RealLat(bpy.context.scene['FromLat'])
To_Lat=RealLat(bpy.context.scene['ToLat'])
From_Long=RealLong(bpy.context.scene['FromLong'])
To_Long=RealLong(bpy.context.scene['ToLong'])
BlenderScale=bpy.context.scene['Scale']
Exag=bpy.context.scene['Exaggerate']
Vertex=[] #Vertex array
Faces=[] #Faces arrays
FirstRow=[]
SecondRow=[]
print('*** Start create vertex ***')
FileAndPath=bpy.context.scene['fpath']
FileAndExt=os.path.splitext(FileAndPath)
#Check for UNIX that is case sensitive
#If the Ext of the file selected from user is Upper, than the second file is Upper and Viceversa
if FileAndExt[1].isupper:
FileName=FileAndExt[0] + ".IMG"
else:
FileName=FileAndExt[0] + ".img"
f=open(FileName,'rb')
f.seek(int((int(LatToLine(From_Lat))-1)*(LINE_SAMPLES*(SAMPLE_BITS/8))),1)#Skip the first n line of point
SkipFirstPoint=int((LongToPoint(From_Long)-1)*(SAMPLE_BITS/8)) #Nunmber of points to skip
PointsToRead=(LongToPoint(To_Long)-LongToPoint(From_Long)+1)*(int(SAMPLE_BITS)/8) #Number of points to be read
SkipLastPoint=(LINE_SAMPLES*(SAMPLE_BITS/8))-PointsToRead-SkipFirstPoint #Nunmber of points to skip
LatToRead=From_Lat
while (LatToRead>=To_Lat):
f.seek(SkipFirstPoint,1) #Skip the first n point
Altitudes=f.read(int(PointsToRead)) #Read all the point
Altitudes=array.array("h",Altitudes) #Change to Array of signed short
if SAMPLE_TYPE=="MSB_INTEGER":
Altitudes.byteswap() #Change from MSB (big endian) to LSB (little endian)
LongToRead=From_Long
PointToRead=0
while (LongToRead<=To_Long):
if Exag:
tmpRadius=(Altitudes[PointToRead]/SCALING_FACTOR/1000+OFFSET)/BlenderScale #Exagerate scale, old formula
else:
tmpRadius=((Altitudes[PointToRead]*SCALING_FACTOR)/1000+OFFSET)/BlenderScale #Correct scale
CurrentRadius=tmpRadius*(math.cos(LatToRead*TO_RAD))
X=CurrentRadius*(math.sin(LongToRead*TO_RAD))
Y=tmpRadius*math.sin(LatToRead*TO_RAD)
Z=CurrentRadius*math.cos(LongToRead*TO_RAD)
Vertex.append(Vector((float(X),float(Y),float(Z))))
LongToRead+=(1/MAP_RESOLUTION)
PointToRead+=1
f.seek(int(SkipLastPoint),1)
LatToRead-=(1/MAP_RESOLUTION)
f.close
del Altitudes
print('*** End create Vertex ***')

print('*** Start create faces ***')
LinesToRead=int(LatToLine(To_Lat)-LatToLine(From_Lat)+1) #Number of the lines to read
PointsToRead=int(LongToPoint(To_Long)-LongToPoint(From_Long)+1) #Number of the points to read
for Point in range(0,PointsToRead):
FirstRow.append(Point)
SecondRow.append(Point+PointsToRead)
if int(PointsToRead)==LINE_SAMPLES:
FaceTemp=createFaces(FirstRow,SecondRow,closed=True,flipped=True)
else:
FaceTemp=createFaces(FirstRow,SecondRow,closed=False,flipped=True)
Faces.extend(FaceTemp)

FaceTemp=[]
for Line in range(1,(LinesToRead-1)):
FirstRow=SecondRow
SecondRow=[]
FacesTemp=[]
for Point in range(0,PointsToRead):
SecondRow.append(Point+(Line+1)*PointsToRead)
if int(PointsToRead)==LINE_SAMPLES:
FaceTemp=createFaces(FirstRow,SecondRow,closed=True,flipped=True)
else:
FaceTemp=createFaces(FirstRow,SecondRow,closed=False,flipped=True)
Faces.extend(FaceTemp)
del FaceTemp
print('*** End create faces ***')

print ('*** Start draw ***')
mesh = bpy.data.meshes.new(TARGET_NAME)
mesh.from_pydata(Vertex, [], Faces)
del Faces
del Vertex
mesh.update()
ob_new = bpy.data.objects.new(TARGET_NAME, mesh)
ob_new.data = mesh
scene = bpy.context.scene
scene.objects.link(ob_new)
scene.objects.active = ob_new
ob_new.select = True
print ('*** End draw ***')
print('*** Start Smooth ***')
bpy.ops.object.shade_smooth()
print('*** End Smooth ***')
if TARGET_NAME=="MOON":
MakeMaterialMoon(ob_new)
elif TARGET_NAME=="MARS":
MakeMaterialMars(ob_new)
print('*** FINISHED ***')
return {'FINISHED'}

# drawing the user interface
class Img_Importer(bpy.types.Panel):
bl_space_type = "VIEW_3D"
bl_region_type = "TOOL_PROPS"
bl_label = "LRO Lola & MGS Mola IMG Importer"

def __init__(self, context):
LINES=LINE_SAMPLES=SAMPLE_BITS=MAP_RESOLUTION=0
MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=0.0
SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""

# intializing variables
props = [("FromLat",0.0),("ToLat",0.0),("FromLong",0.0),("ToLong",0.0),("Scale",1),("Exaggerate",False)]
for p, num in props:
if not p in bpy.context.scene.keys():
bpy.context.scene[p] = num

def draw(self, context):
obj = context.object
typ = bpy.types.Scene
var = bpy.props
typ.fpath = var.StringProperty(name="Import File ", description="Select your img file", subtype="FILE_PATH", default="")

ReadLabel(bpy.context.scene.fpath)

typ.FromLat=var.FloatProperty(description="From Latitude", min=float(MINIMUM_LATITUDE), max=float(MAXIMUM_LATITUDE),precision=3)
typ.ToLat=var.FloatProperty(description="To Latitude", min=float(MINIMUM_LATITUDE), max=float(MAXIMUM_LATITUDE),precision=3)
typ.FromLong=var.FloatProperty(description="From Longitude", min=float(WESTERNMOST_LONGITUDE), max=float(EASTERNMOST_LONGITUDE),precision=3)
typ.ToLong=var.FloatProperty(description="To Longitude", min=float(WESTERNMOST_LONGITUDE), max=float(EASTERNMOST_LONGITUDE),precision=3)
typ.Scale=var.IntProperty(description="Scale", min=1, max=100,default=1)
typ.Exaggerate=var.BoolProperty(description="Magnify", default=False)

layout = self.layout
layout.prop(context.scene, "fpath")

col = layout.column()
split = col.split(align=True)
split.label("Minimum Latitude: "+str(MINIMUM_LATITUDE)+" deg")
split.label("Maximum Latitude: "+str(MAXIMUM_LATITUDE)+" deg")

split = col.split(align=True)
split.label("Westernmost Longitude: "+str(WESTERNMOST_LONGITUDE)+" deg")
split.label("Easternmost Longitude: "+str(EASTERNMOST_LONGITUDE)+" deg")

split = col.split(align=True)
split.label("Lines: " + str(LINES))
split.label("Line samples: " + str(LINE_SAMPLES))

split = col.split(align=True)
split.label("Sample type: "+str(SAMPLE_TYPE))
split.label("Sample bits: "+str(SAMPLE_BITS))

split = col.split(align=True)
split.label("Unit: "+UNIT)
split.label("Map resolution: "+str(MAP_RESOLUTION) + " pix/deg")

split = col.split(align=True)
split.label("Radius: "+str(OFFSET)+ " " + RadiusUM)
split.label("Scale: "+str(SCALING_FACTOR))

split = col.split(align=True)
split.label("Target: ")
split.label(TARGET_NAME)

col = layout.column()
split = col.split(align=True)
split.prop(context.scene, "FromLat", "Northernmost Lat.")
split.prop(context.scene, "ToLat", "Southernmost Lat.")
if bpy.context.scene['FromLat'] < bpy.context.scene['ToLat']:
col = layout.column()
split = col.split(align=True)
split.label("Warning: Northernmost must be greater than Southernmost")

col = layout.column()
split = col.split(align=True)
split.prop(context.scene, "FromLong", "Westernmost Long.")
split.prop(context.scene, "ToLong", "Easternmost Long.")
if bpy.context.scene['FromLong'] > bpy.context.scene['ToLong']:
col = layout.column()
split = col.split(align=True)
split.label("Warning: Easternmost must be greater than Westernmost")

col = layout.column()
split = col.split(align=True)
split.prop(context.scene, "Scale", "Scale")
split.prop(context.scene, "Exaggerate", "Magnify (x4)")
if bpy.context.scene.fpath !="":
col = layout.column()
split = col.split(align=True)
split.label("1 Blender unit = " + str(bpy.context.scene['Scale']) +RadiusUM)

if Message!="":
col = layout.column()
split = col.split(align=True)
split.label("Message: " + Message)

if bpy.context.scene.fpath.upper().endswith("IMG") or bpy.context.scene.fpath.upper().endswith("LBL"): #Check if is selected the correct file
VertNumbers=(((RealLat(bpy.context.scene['FromLat'])-RealLat(bpy.context.scene['ToLat']))*MAP_RESOLUTION)+1)*((RealLong(bpy.context.scene['ToLong'])-RealLong(bpy.context.scene['FromLong']))*MAP_RESOLUTION+1)
else:
VertNumbers=0
#If I have 4 or plus vertex and at least 2 row and at least 2 point, I can import
if VertNumbers>3 and (RealLat(bpy.context.scene['FromLat'])> RealLat(bpy.context.scene['ToLat'])) and (RealLong(bpy.context.scene['FromLong'])<RealLong(bpy.context.scene['ToLong'])): #If I have 4 or plus vertex I can import
split = col.split(align=True)
split.label("Map resolution on the equator: ")
split.label(str(2*math.pi*OFFSET/360/MAP_RESOLUTION) + " " + RadiusUM + "/pix")
col = layout.column()
split = col.split(align=True)
split.label("Real Northernmost Lat.: " + str(RealLat(bpy.context.scene['FromLat']))+" deg")
split.label("Real Southernmost Long.: " + str(RealLat(bpy.context.scene['ToLat']))+" deg")
split = col.split(align=True)
split.label("Real Westernmost Long.: " + str(RealLong(bpy.context.scene['FromLong']))+" deg")
split.label("Real Easternmost Long.: " + str(RealLong(bpy.context.scene['ToLong']))+"deg")
split = col.split(align=True)
VertNumbers=(((RealLat(bpy.context.scene['FromLat'])-RealLat(bpy.context.scene['ToLat']))*MAP_RESOLUTION)+1)*((RealLong(bpy.context.scene['ToLong'])-RealLong(bpy.context.scene['FromLong']))*MAP_RESOLUTION+1)
split.label("Numbers of vertex to be imported: "+ str(int(VertNumbers)))
col.separator()
col.operator('Import', text='Import')

# registering the script
def register():
pass

def unregister():
clear_properties()

if __name__ == "__main__":
register()
  1. # ##### BEGIN GPL LICENSE BLOCK #####
  2. #
  3. #  This program is free software; you can redistribute it and/or
  4. #  modify it under the terms of the GNU General Public License
  5. #  as published by the Free Software Foundation; either version 2
  6. #  of the License, or (at your option) any later version.
  7. #
  8. #  This program is distributed in the hope that it will be useful,
  9. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. #  GNU General Public License for more details.
  12. #
  13. #  You should have received a copy of the GNU General Public License
  14. #  along with this program; if not, write to the Free Software Foundation,
  15. #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. #
  17. # ##### END GPL LICENSE BLOCK #####
  18.  
  19. bl_addon_info = {
  20.     "name": "LRO Lola & MGS Mola img Importer",
  21.     "author": "ValterVB",
  22.     "version": (0, 1, 2),
  23.     "blender": (2, 5, 6),
  24.     "api": 34043,
  25.     "location": "3D window > Tool Shelf",
  26.     "description": "Import DTM from LRO Lola and MGS Mola",
  27.     "warning": "May consume a lot of memory",
  28.     "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/Scripts/Import-Export/NASA_IMG_Importer",
  29.     "tracker_url":"http://projects.blender.org/tracker/index.php?func=detail&aid=25462&group_id=153&atid=467",
  30.     "category": "Import-Export"}
  31.  
  32. #***************************************************************
  33. #ver. 0.0.1: -First version
  34. #ver. 0.0.2: -Add check on path and file
  35. #            -Check on selected coordinates more complete
  36. #ver. 1.1.0: -Optimized for less memory
  37. #ver. 1.1.1: -Correct bug for real value of the High (bad error).
  38. #             now it's less artistic, bat more real Always possible use
  39. #             the old formula. check Exaggerate the high
  40. #            -Correct the bug for directory with dot in the name
  41. #            -Add some warning and more information
  42. #            -Add slider for the scale and info on it
  43. #ver. 1.1.2: -Word correction
  44. #            -Correct the problem for Unix. If the Ext of the file
  45. #              selected from user is Upper, than the second file
  46. #              is Upper and Viceversa. (I can't verify)
  47. #****************************************************************
  48.  
  49. import bpy
  50. import os.path
  51. import math, array,  mathutils
  52. from mathutils import *
  53.  
  54. TO_RAD=math.pi/180 #From degrees to radians
  55.  
  56. # turning off relative path - it causes an error if it was true
  57. if bpy.context.user_preferences.filepaths.use_relative_paths == True:
  58.    bpy.context.user_preferences.filepaths.use_relative_paths = False
  59.    
  60. # A very simple "bridge" tool.
  61. # Connects two equally long vertex rows with faces.
  62. # Returns a list of the new faces (list of  lists)
  63. #
  64. # vertIdx1 ... First vertex list (list of vertex indices).
  65. # vertIdx2 ... Second vertex list (list of vertex indices).
  66. # closed ... Creates a loop (first & last are closed).
  67. # flipped ... Invert the normal of the face(s).
  68. #
  69. # Note: You can set vertIdx1 to a single vertex index to create a fan/star of faces.
  70. # Note: If both vertex idx list are the same length they have to have at least 2 vertices.
  71. def createFaces(vertIdx1, vertIdx2, closed=False, flipped=False):
  72.     faces = []
  73.  
  74.     if not vertIdx1 or not vertIdx2:
  75.         return None
  76.  
  77.     if len(vertIdx1) < 2 and len(vertIdx2) < 2:
  78.         return None
  79.  
  80.     fan = False
  81.     if (len(vertIdx1) != len(vertIdx2)):
  82.         if (len(vertIdx1) == 1 and len(vertIdx2) > 1):
  83.             fan = True
  84.         else:
  85.             return None
  86.  
  87.     total = len(vertIdx2)
  88.  
  89.     if closed:
  90.         # Bridge the start with the end.
  91.         if flipped:
  92.             face = [
  93.                 vertIdx1[0],
  94.                 vertIdx2[0],
  95.                 vertIdx2[total - 1]]
  96.             if not fan:
  97.                 face.append(vertIdx1[total - 1])
  98.             faces.append(face)
  99.  
  100.         else:
  101.             face = [vertIdx2[0], vertIdx1[0]]
  102.             if not fan:
  103.                 face.append(vertIdx1[total - 1])
  104.             face.append(vertIdx2[total - 1])
  105.             faces.append(face)
  106.  
  107.     # Bridge the rest of the faces.
  108.     for num in range(total - 1):
  109.         if flipped:
  110.             if fan:
  111.                 face = [vertIdx2[num], vertIdx1[0], vertIdx2[num + 1]]
  112.             else:
  113.                 face = [vertIdx2[num], vertIdx1[num],
  114.                     vertIdx1[num + 1], vertIdx2[num + 1]]
  115.             faces.append(face)
  116.         else:
  117.             if fan:
  118.                 face = [vertIdx1[0], vertIdx2[num], vertIdx2[num + 1]]
  119.             else:
  120.                 face = [vertIdx1[num], vertIdx2[num],
  121.                     vertIdx2[num + 1], vertIdx1[num + 1]]
  122.             faces.append(face)
  123.     return faces
  124.    
  125. #Utility Function ********************************************************
  126. #
  127. #Input: Latitude Output: Number of the line (1 to n)
  128. def LatToLine(Latitude):
  129.     tmpLines=round((MAXIMUM_LATITUDE-Latitude)*MAP_RESOLUTION+1.0)
  130.     if tmpLines>LINES:tmpLines=LINES
  131.     return tmpLines
  132.        
  133. #Input: Number of the line (1 to n) Output: Latitude
  134. def LineToLat(Line):
  135.     if MAP_RESOLUTION==0:
  136.         return 0
  137.     else:
  138.         return float(MAXIMUM_LATITUDE-(Line-1)/MAP_RESOLUTION)
  139.  
  140. #Input: Longitude Output: Number of the point (1 to n)
  141. def LongToPoint(Longitude):
  142.     tmpPoints=round((Longitude-WESTERNMOST_LONGITUDE)*MAP_RESOLUTION+1.0)
  143.     if tmpPoints>LINE_SAMPLES:tmpPoints=LINE_SAMPLES
  144.     return tmpPoints
  145.  
  146. #Input: Number of the Point (1 to n) Output: Longitude
  147. def PointToLong(Point):
  148.     if MAP_RESOLUTION==0:
  149.         return 0
  150.     else:
  151.             return float(WESTERNMOST_LONGITUDE+(Point-1)/MAP_RESOLUTION)
  152.  
  153. #Input: Latitude Output: Neareast real Latitude on grid
  154. def RealLat(Latitude):
  155.         return float(LineToLat(LatToLine(Latitude)))
  156.  
  157. #Input: Longitude Output: Neareast real Longitude on grid       
  158. def RealLong(Longitude):
  159.         return float(PointToLong(LongToPoint(Longitude)))
  160. #**************************************************************************
  161.  
  162.  
  163. #Read the LBL file    
  164. def ReadLabel(FileName):
  165.     global FileAndPath
  166.     global LINES, LINE_SAMPLES, SAMPLE_TYPE, SAMPLE_BITS, UNIT, MAP_RESOLUTION, MAXIMUM_LATITUDE, MINIMUM_LATITUDE
  167.     global WESTERNMOST_LONGITUDE, EASTERNMOST_LONGITUDE, SCALING_FACTOR,OFFSET, RadiusUM, TARGET_NAME
  168.     global Message
  169.  
  170.     if FileName=='':
  171.         LINES=LINE_SAMPLES=SAMPLE_BITS=MAP_RESOLUTION=0
  172.         MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=0.0
  173.         SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""
  174.         return
  175.        
  176.     FileAndPath=FileName
  177.     FileAndExt=os.path.splitext(FileAndPath)
  178.     try:
  179.         #Check for UNIX that is case sensitive
  180.         #If the Ext of the file selected from user is Upper, than the second file is Upper and Viceversa
  181.         if FileAndExt[1].isupper:
  182.             f = open(FileAndExt[0] + ".LBL", 'r')  #Open the label file
  183.         else:
  184.             f = open(FileAndExt[0] + ".lbl", 'r')  #Open the label file
  185.         Message=""
  186.     except:
  187.         Message="FILE LBL NOT AVAILABLE OR YOU HAVEN'T SELECTED A FILE"
  188.         return
  189.    
  190.     block=""
  191.     OFFSET=0
  192.     for line in f:
  193.         tmp=line.split("=")
  194.         if tmp[0].strip()=="OBJECT" and tmp[1].strip()=="IMAGE":       
  195.             block="IMAGE"
  196.         elif tmp[0].strip()=="OBJECT" and tmp[1].strip()=="IMAGE_MAP_PROJECTION":       
  197.             block="IMAGE_MAP_PROJECTION"
  198.         elif tmp[0].strip()=="END_OBJECT" and tmp[1].strip()=="IMAGE": 
  199.             block=""
  200.         elif tmp[0].strip()=="END_OBJECT" and tmp[1].strip()=="IMAGE_MAP_PROJECTION":   
  201.             block=""
  202.         elif tmp[0].strip()=="TARGET_NAME":
  203.             block=""
  204.             TARGET_NAME=tmp[1].strip()
  205.         if block=="IMAGE":
  206.             if line.find("LINES") !=-1 and not(line.startswith("/*")):
  207.                 tmp=line.split("=")
  208.                 LINES=int(tmp[1].strip())
  209.             elif line.find("LINE_SAMPLES") != -1 and not(line.startswith("/*")):
  210.                 tmp=line.split("=")
  211.                 LINE_SAMPLES=int(tmp[1].strip())
  212.             elif line.find("UNIT") != -1 and not(line.startswith("/*")):
  213.                 tmp=line.split("=")
  214.                 UNIT=tmp[1].strip()
  215.             elif line.find("SAMPLE_TYPE") != -1 and not(line.startswith("/*")):
  216.                 tmp=line.split("=")
  217.                 SAMPLE_TYPE=tmp[1].strip()
  218.             elif line.find("SAMPLE_BITS") != -1 and not(line.startswith("/*")):
  219.                 tmp=line.split("=")
  220.                 SAMPLE_BITS=int(tmp[1].strip())
  221.             elif line.find("SCALING_FACTOR") != -1 and not(line.startswith("/*")):
  222.                 tmp=line.split("=")
  223.                 tmp=tmp[1].split("<")
  224.                 SCALING_FACTOR=float(tmp[0].replace(" ", ""))
  225.             elif line.find("OFFSET") != -1 and not(line.startswith("/*")):
  226.                 tmp=line.split("=")
  227.                 if tmp[0].find("OFFSET")!=-1 and len(tmp) > 1:
  228.                     tmp=tmp[1].split("<")
  229.                     tmp[0]=tmp[0].replace(".", "")
  230.                     OFFSET=float(tmp[0].replace(" ", ""))
  231.         elif block=="IMAGE_MAP_PROJECTION":
  232.             if line.find("A_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
  233.                 tmp=line.split("=")
  234.                 tmp=tmp[1].split("<")
  235.                 A_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
  236.                 RadiusUM=tmp[1].rstrip().replace(">","")
  237.             elif line.find("B_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
  238.                 tmp=line.split("=")
  239.                 tmp=tmp[1].split("<")
  240.                 B_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
  241.             elif line.find("C_AXIS_RADIUS") != -1 and not(line.startswith("/*")):
  242.                 tmp=line.split("=")
  243.                 tmp=tmp[1].split("<")
  244.                 C_AXIS_RADIUS=float(tmp[0].replace(" ", ""))
  245.             elif line.find("MAXIMUM_LATITUDE") != -1 and not(line.startswith("/*")):
  246.                 tmp=line.split("=")
  247.                 tmp=tmp[1].split("<")
  248.                 MAXIMUM_LATITUDE=float(tmp[0].replace(" ", ""))
  249.             elif line.find("MINIMUM_LATITUDE") != -1 and not(line.startswith("/*")):
  250.                 tmp=line.split("=")
  251.                 tmp=tmp[1].split("<")
  252.                 MINIMUM_LATITUDE=float(tmp[0].replace(" ", ""))
  253.             elif line.find("WESTERNMOST_LONGITUDE") != -1 and not(line.startswith("/*")):
  254.                 tmp=line.split("=")
  255.                 tmp=tmp[1].split("<")
  256.                 WESTERNMOST_LONGITUDE=float(tmp[0].replace(" ", ""))
  257.             elif line.find("EASTERNMOST_LONGITUDE") != -1 and not(line.startswith("/*")):
  258.                 tmp=line.split("=")
  259.                 tmp=tmp[1].split("<")
  260.                 EASTERNMOST_LONGITUDE=float(tmp[0].replace(" ", ""))
  261.             elif line.find("MAP_RESOLUTION") != -1 and not(line.startswith("/*")):
  262.                 tmp=line.split("=")
  263.                 tmp=tmp[1].split("<")
  264.                 MAP_RESOLUTION=float(tmp[0].replace(" ", ""))
  265.     f.close
  266.     MAXIMUM_LATITUDE=MAXIMUM_LATITUDE-1/MAP_RESOLUTION/2
  267.     MINIMUM_LATITUDE=MINIMUM_LATITUDE+1/MAP_RESOLUTION/2
  268.     WESTERNMOST_LONGITUDE=WESTERNMOST_LONGITUDE+1/MAP_RESOLUTION/2
  269.     EASTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE-1/MAP_RESOLUTION/2
  270.     if OFFSET==0: #When OFFSET isn't available I use the medium of the radius
  271.         OFFSET=(A_AXIS_RADIUS+B_AXIS_RADIUS+C_AXIS_RADIUS)/3
  272.     else:
  273.         OFFSET=OFFSET/1000 #Convert m to Km
  274.     if SCALING_FACTOR==0: SCALING_FACTOR=1.0 #When isn'tavailable I set it to 1
  275.  
  276. def MakeMaterialMars(obj):
  277.     #Copied from io_convert_image_to_mesh_img
  278.     mat = bpy.data.materials.new("Mars")
  279.     mat.diffuse_shader = 'MINNAERT'
  280.     mat.diffuse_color=(0.426, 0.213, 0.136)
  281.     mat.darkness=0.8
  282.    
  283.     mat.specular_shader = 'WARDISO'
  284.     mat.specular_color= (1.000, 0.242, 0.010)
  285.     mat.specular_intensity=0.010
  286.     mat.specular_slope= 0.100
  287.     obj.data.materials.append(mat)
  288.  
  289. def MakeMaterialMoon(obj):
  290.     #Same as Mars Material, but i have canged the color
  291.     mat = bpy.data.materials.new("Moon")
  292.     mat.diffuse_shader = 'MINNAERT'
  293.     mat.diffuse_color=(0.426, 0.426, 0.426)
  294.     mat.darkness=0.8
  295.    
  296.     mat.specular_shader = 'WARDISO'
  297.     mat.specular_color= (0.6, 0.6, 0.6)
  298.     mat.specular_intensity=0.010
  299.     mat.specular_slope= 0.100
  300.     obj.data.materials.append(mat)
  301.    
  302. def clear_properties():
  303.     # can happen on reload
  304.     if bpy.context.scene is None:
  305.         return
  306.  
  307.     LINES=LINE_SAMPLES=SAMPLE_BITS=0
  308.     MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=MAP_RESOLUTION=0.0
  309.     SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""
  310.        
  311.     props = ["FromLat", "ToLat", "FromLong", "ToLong", "Scale"]
  312.     for p in props:
  313.         if p in bpy.types.Scene.bl_rna.properties:
  314.             exec("del bpy.types.Scene."+p)
  315.         if p in bpy.context.scene:
  316.             del bpy.context.scene[p]
  317.            
  318. #Import the data and draw the planet - NEW            
  319. class Import(bpy.types.Operator):
  320.     bl_idname = 'Import'
  321.     bl_label = 'Start Import'
  322.     bl_description = 'Import the data'
  323.  
  324.     def execute(self, context):
  325.         From_Lat=RealLat(bpy.context.scene['FromLat'])
  326.         To_Lat=RealLat(bpy.context.scene['ToLat'])
  327.         From_Long=RealLong(bpy.context.scene['FromLong'])
  328.         To_Long=RealLong(bpy.context.scene['ToLong'])
  329.         BlenderScale=bpy.context.scene['Scale']
  330.         Exag=bpy.context.scene['Exaggerate']
  331.         Vertex=[] #Vertex array
  332.         Faces=[]   #Faces arrays
  333.         FirstRow=[]
  334.         SecondRow=[]
  335.         print('*** Start create vertex ***')
  336.         FileAndPath=bpy.context.scene['fpath']
  337.         FileAndExt=os.path.splitext(FileAndPath)
  338.         #Check for UNIX that is case sensitive
  339.         #If the Ext of the file selected from user is Upper, than the second file is Upper and Viceversa
  340.         if FileAndExt[1].isupper:
  341.             FileName=FileAndExt[0] + ".IMG"
  342.         else:
  343.             FileName=FileAndExt[0] + ".img"
  344.         f=open(FileName,'rb')
  345.         f.seek(int((int(LatToLine(From_Lat))-1)*(LINE_SAMPLES*(SAMPLE_BITS/8))),1)#Skip the first n line of point
  346.         SkipFirstPoint=int((LongToPoint(From_Long)-1)*(SAMPLE_BITS/8)) #Nunmber of points to skip
  347.         PointsToRead=(LongToPoint(To_Long)-LongToPoint(From_Long)+1)*(int(SAMPLE_BITS)/8) #Number of points to be read
  348.         SkipLastPoint=(LINE_SAMPLES*(SAMPLE_BITS/8))-PointsToRead-SkipFirstPoint #Nunmber of points to skip
  349.         LatToRead=From_Lat
  350.         while (LatToRead>=To_Lat):
  351.             f.seek(SkipFirstPoint,1) #Skip the first n point
  352.             Altitudes=f.read(int(PointsToRead)) #Read all the point
  353.             Altitudes=array.array("h",Altitudes) #Change to Array of signed short
  354.             if SAMPLE_TYPE=="MSB_INTEGER":
  355.                 Altitudes.byteswap() #Change from MSB (big endian) to LSB (little endian)
  356.             LongToRead=From_Long
  357.             PointToRead=0
  358.             while (LongToRead<=To_Long):
  359.                 if Exag:
  360.                     tmpRadius=(Altitudes[PointToRead]/SCALING_FACTOR/1000+OFFSET)/BlenderScale #Exagerate scale, old formula
  361.                 else:
  362.                     tmpRadius=((Altitudes[PointToRead]*SCALING_FACTOR)/1000+OFFSET)/BlenderScale #Correct scale
  363.                 CurrentRadius=tmpRadius*(math.cos(LatToRead*TO_RAD))
  364.                 X=CurrentRadius*(math.sin(LongToRead*TO_RAD))
  365.                 Y=tmpRadius*math.sin(LatToRead*TO_RAD)
  366.                 Z=CurrentRadius*math.cos(LongToRead*TO_RAD)
  367.                 Vertex.append(Vector((float(X),float(Y),float(Z))))
  368.                 LongToRead+=(1/MAP_RESOLUTION)
  369.                 PointToRead+=1
  370.             f.seek(int(SkipLastPoint),1)       
  371.             LatToRead-=(1/MAP_RESOLUTION)
  372.         f.close
  373.         del Altitudes
  374.         print('*** End create Vertex   ***')
  375.  
  376.         print('*** Start create faces ***')
  377.         LinesToRead=int(LatToLine(To_Lat)-LatToLine(From_Lat)+1)   #Number of the lines to read
  378.         PointsToRead=int(LongToPoint(To_Long)-LongToPoint(From_Long)+1) #Number of the points to read
  379.         for Point in range(0,PointsToRead):
  380.             FirstRow.append(Point)
  381.             SecondRow.append(Point+PointsToRead)
  382.         if int(PointsToRead)==LINE_SAMPLES:
  383.             FaceTemp=createFaces(FirstRow,SecondRow,closed=True,flipped=True)
  384.         else:
  385.             FaceTemp=createFaces(FirstRow,SecondRow,closed=False,flipped=True)
  386.         Faces.extend(FaceTemp)
  387.        
  388.         FaceTemp=[]
  389.         for Line in range(1,(LinesToRead-1)):
  390.             FirstRow=SecondRow
  391.             SecondRow=[]
  392.             FacesTemp=[]
  393.             for Point in range(0,PointsToRead):
  394.                 SecondRow.append(Point+(Line+1)*PointsToRead)
  395.             if int(PointsToRead)==LINE_SAMPLES:
  396.                 FaceTemp=createFaces(FirstRow,SecondRow,closed=True,flipped=True)
  397.             else:
  398.                 FaceTemp=createFaces(FirstRow,SecondRow,closed=False,flipped=True)
  399.             Faces.extend(FaceTemp)
  400.         del FaceTemp
  401.         print('*** End create faces   ***')
  402.  
  403.         print ('*** Start draw ***')        
  404.         mesh = bpy.data.meshes.new(TARGET_NAME)
  405.         mesh.from_pydata(Vertex, [], Faces)
  406.         del Faces
  407.         del Vertex
  408.         mesh.update()
  409.         ob_new = bpy.data.objects.new(TARGET_NAME, mesh)
  410.         ob_new.data = mesh
  411.         scene = bpy.context.scene
  412.         scene.objects.link(ob_new)
  413.         scene.objects.active = ob_new
  414.         ob_new.select = True
  415.         print ('*** End draw   ***')        
  416.         print('*** Start Smooth ***')
  417.         bpy.ops.object.shade_smooth()
  418.         print('*** End Smooth   ***')
  419.         if TARGET_NAME=="MOON":
  420.             MakeMaterialMoon(ob_new)
  421.         elif TARGET_NAME=="MARS":
  422.             MakeMaterialMars(ob_new)
  423.         print('*** FINISHED ***')
  424.         return {'FINISHED'}
  425.        
  426. # drawing the user interface
  427. class Img_Importer(bpy.types.Panel):
  428.     bl_space_type = "VIEW_3D"
  429.     bl_region_type = "TOOL_PROPS"
  430.     bl_label = "LRO Lola & MGS Mola IMG Importer"
  431.  
  432.     def __init__(self, context):
  433.         LINES=LINE_SAMPLES=SAMPLE_BITS=MAP_RESOLUTION=0
  434.         MAXIMUM_LATITUDE=MINIMUM_LATITUDE=WESTERNMOST_LONGITUDE=EASTERNMOST_LONGITUDE=OFFSET=SCALING_FACTOR=0.0
  435.         SAMPLE_TYPE=UNIT=TARGET_NAME=RadiusUM=Message=""
  436.  
  437.         # intializing variables
  438.         props = [("FromLat",0.0),("ToLat",0.0),("FromLong",0.0),("ToLong",0.0),("Scale",1),("Exaggerate",False)]
  439.         for p, num in props:
  440.             if not p in bpy.context.scene.keys():
  441.                 bpy.context.scene[p] = num
  442.  
  443.     def draw(self, context):
  444.         obj = context.object
  445.         typ = bpy.types.Scene
  446.         var = bpy.props
  447.         typ.fpath = var.StringProperty(name="Import File ", description="Select your img file", subtype="FILE_PATH", default="")
  448.        
  449.         ReadLabel(bpy.context.scene.fpath)
  450.        
  451.         typ.FromLat=var.FloatProperty(description="From Latitude", min=float(MINIMUM_LATITUDE), max=float(MAXIMUM_LATITUDE),precision=3)
  452.         typ.ToLat=var.FloatProperty(description="To Latitude", min=float(MINIMUM_LATITUDE), max=float(MAXIMUM_LATITUDE),precision=3)
  453.         typ.FromLong=var.FloatProperty(description="From Longitude", min=float(WESTERNMOST_LONGITUDE), max=float(EASTERNMOST_LONGITUDE),precision=3)
  454.         typ.ToLong=var.FloatProperty(description="To Longitude", min=float(WESTERNMOST_LONGITUDE), max=float(EASTERNMOST_LONGITUDE),precision=3)
  455.         typ.Scale=var.IntProperty(description="Scale", min=1, max=100,default=1)
  456.         typ.Exaggerate=var.BoolProperty(description="Magnify", default=False)
  457.  
  458.         layout = self.layout
  459.         layout.prop(context.scene, "fpath")
  460.        
  461.         col = layout.column()
  462.         split = col.split(align=True)
  463.         split.label("Minimum Latitude: "+str(MINIMUM_LATITUDE)+" deg")
  464.         split.label("Maximum Latitude: "+str(MAXIMUM_LATITUDE)+" deg")
  465.        
  466.         split = col.split(align=True)
  467.         split.label("Westernmost Longitude: "+str(WESTERNMOST_LONGITUDE)+" deg")
  468.         split.label("Easternmost Longitude: "+str(EASTERNMOST_LONGITUDE)+" deg")        
  469.  
  470.         split = col.split(align=True)
  471.         split.label("Lines: " + str(LINES))
  472.         split.label("Line samples: " + str(LINE_SAMPLES))
  473.        
  474.         split = col.split(align=True)
  475.         split.label("Sample type: "+str(SAMPLE_TYPE))
  476.         split.label("Sample bits: "+str(SAMPLE_BITS))
  477.  
  478.         split = col.split(align=True)
  479.         split.label("Unit: "+UNIT)
  480.         split.label("Map resolution: "+str(MAP_RESOLUTION) + " pix/deg")
  481.        
  482.         split = col.split(align=True)
  483.         split.label("Radius: "+str(OFFSET)+ " " + RadiusUM)
  484.         split.label("Scale: "+str(SCALING_FACTOR))
  485.        
  486.         split = col.split(align=True)
  487.         split.label("Target: ")
  488.         split.label(TARGET_NAME)
  489.                
  490.         col = layout.column()
  491.         split = col.split(align=True)
  492.         split.prop(context.scene, "FromLat", "Northernmost Lat.")
  493.         split.prop(context.scene, "ToLat", "Southernmost Lat.")
  494.         if bpy.context.scene['FromLat'] < bpy.context.scene['ToLat']:
  495.             col = layout.column()
  496.             split = col.split(align=True)
  497.             split.label("Warning: Northernmost must be greater than Southernmost")
  498.        
  499.         col = layout.column()
  500.         split = col.split(align=True)
  501.         split.prop(context.scene, "FromLong", "Westernmost Long.")
  502.         split.prop(context.scene, "ToLong", "Easternmost Long.")
  503.         if bpy.context.scene['FromLong'] > bpy.context.scene['ToLong']:
  504.             col = layout.column()
  505.             split = col.split(align=True)
  506.             split.label("Warning: Easternmost must be greater than Westernmost")
  507.        
  508.         col = layout.column()
  509.         split = col.split(align=True)
  510.         split.prop(context.scene, "Scale", "Scale")
  511.         split.prop(context.scene, "Exaggerate", "Magnify (x4)")
  512.         if bpy.context.scene.fpath !="":
  513.             col = layout.column()
  514.             split = col.split(align=True)
  515.             split.label("1 Blender unit = " + str(bpy.context.scene['Scale']) +RadiusUM)  
  516.            
  517.         if Message!="":
  518.             col = layout.column()
  519.             split = col.split(align=True)
  520.             split.label("Message: " + Message)
  521.        
  522.         if bpy.context.scene.fpath.upper().endswith("IMG") or bpy.context.scene.fpath.upper().endswith("LBL"): #Check if is selected the correct file
  523.             VertNumbers=(((RealLat(bpy.context.scene['FromLat'])-RealLat(bpy.context.scene['ToLat']))*MAP_RESOLUTION)+1)*((RealLong(bpy.context.scene['ToLong'])-RealLong(bpy.context.scene['FromLong']))*MAP_RESOLUTION+1)
  524.         else:
  525.             VertNumbers=0
  526.         #If I have 4 or plus vertex and at least 2 row and at least 2 point, I can import
  527.         if VertNumbers>3 and (RealLat(bpy.context.scene['FromLat'])> RealLat(bpy.context.scene['ToLat'])) and (RealLong(bpy.context.scene['FromLong'])<RealLong(bpy.context.scene['ToLong'])): #If I have 4 or plus vertex I can import
  528.             split = col.split(align=True)
  529.             split.label("Map resolution on the equator: ")
  530.             split.label(str(2*math.pi*OFFSET/360/MAP_RESOLUTION) + " " + RadiusUM + "/pix")
  531.             col = layout.column()
  532.             split = col.split(align=True)
  533.             split.label("Real Northernmost Lat.: " + str(RealLat(bpy.context.scene['FromLat']))+" deg")
  534.             split.label("Real Southernmost Long.: " + str(RealLat(bpy.context.scene['ToLat']))+" deg")
  535.             split = col.split(align=True)
  536.             split.label("Real Westernmost Long.: " + str(RealLong(bpy.context.scene['FromLong']))+" deg")
  537.             split.label("Real Easternmost Long.: " + str(RealLong(bpy.context.scene['ToLong']))+"deg")
  538.             split = col.split(align=True)
  539.             VertNumbers=(((RealLat(bpy.context.scene['FromLat'])-RealLat(bpy.context.scene['ToLat']))*MAP_RESOLUTION)+1)*((RealLong(bpy.context.scene['ToLong'])-RealLong(bpy.context.scene['FromLong']))*MAP_RESOLUTION+1)
  540.             split.label("Numbers of vertex to be imported: "+ str(int(VertNumbers)))
  541.             col.separator()
  542.             col.operator('Import', text='Import')
  543.    
  544. # registering the script
  545. def register():
  546.     pass
  547.  
  548. def unregister():
  549.     clear_properties()
  550.  
  551. if __name__ == "__main__":
  552.     register()
go to heaven