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