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