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