app.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import uuid
  2. import os
  3. import zipfile
  4. import urllib.request
  5. import gzip
  6. from io import BytesIO
  7. import time
  8. from flask import Flask # using flask as the framework
  9. from flask import render_template
  10. from flask import request
  11. from terrain_gen import add_offset
  12. # Directory of this file
  13. this_path = os.path.dirname(os.path.realpath(__file__))
  14. # Where the user requested tile are stored
  15. output_path = os.path.join(this_path, '..', 'userRequestTerrain')
  16. # Where the data database is
  17. tile_path = os.path.join(this_path, '..', 'data', 'tiles')
  18. # The output folder for all gzipped terrain requests
  19. app = Flask(__name__, static_url_path='/terrain', static_folder=output_path,)
  20. def clamp(n, smallest, largest):
  21. return max(smallest, min(n, largest))
  22. def getDatFile(lat, lon):
  23. '''Get file'''
  24. if lat < 0:
  25. NS = 'S'
  26. else:
  27. NS = 'N'
  28. if lon < 0:
  29. EW = 'W'
  30. else:
  31. EW = 'E'
  32. return "%c%02u%c%03u.DAT.gz" % (NS, min(abs(int(lat)), 99), EW, min(abs(int(lon)), 999))
  33. def compressFiles(fileList, uuidkey):
  34. # create a zip file comprised of dat.gz tiles
  35. zipthis = os.path.join(output_path, uuidkey + '.zip')
  36. # create output dirs if needed
  37. try:
  38. os.makedirs(output_path)
  39. except OSError:
  40. pass
  41. try:
  42. os.makedirs(tile_path)
  43. except OSError:
  44. pass
  45. try:
  46. with zipfile.ZipFile(zipthis, 'w') as terrain_zip:
  47. for fn in fileList:
  48. if not os.path.exists(fn):
  49. #download if required
  50. print("Downloading " + os.path.basename(fn))
  51. g = urllib.request.urlopen('https://terrain.ardupilot.org/data/tiles/' +
  52. os.path.basename(fn))
  53. print("Downloaded " + os.path.basename(fn))
  54. with open(fn, 'b+w') as f:
  55. f.write(g.read())
  56. # need to decompress file and pass to zip
  57. with gzip.open(fn, 'r') as f_in:
  58. myio = BytesIO(f_in.read())
  59. print("Decomp " + os.path.basename(fn))
  60. # and add file to zip
  61. terrain_zip.writestr(os.path.basename(fn)[:-3], myio.read(),
  62. compress_type=zipfile.ZIP_DEFLATED)
  63. except Exception as ex:
  64. print("Unexpected error: {0}".format(ex))
  65. return False
  66. return True
  67. @app.route('/')
  68. def index():
  69. return render_template('index.html')
  70. @app.route('/generate', methods=['GET', 'POST'])
  71. def generate():
  72. if request.method == 'POST':
  73. # request.form['username']
  74. features = []
  75. for i in range(1,8):
  76. value = request.form["option" + str(i)]
  77. features.append(value)
  78. undefine = "undef " + value.split()[1]
  79. features.insert(0,undefine)
  80. extra_hwdef = '\n'.join(features)
  81. print("running...")
  82. file = open('extra_hwdef.dat',"w")
  83. file.write(extra_hwdef)
  84. file.close()
  85. # UUID for this terrain generation
  86. uuidkey = str(uuid.uuid1())
  87. # get a list of files required to cover area
  88. filelist = []
  89. done = set()
  90. for dx in range(-radius, radius):
  91. for dy in range(-radius, radius):
  92. (lat2, lon2) = add_offset(lat*1e7, lon*1e7, dx*1000.0, dy*1000.0)
  93. lat_int = int(round(lat2 * 1.0e-7))
  94. lon_int = int(round(lon2 * 1.0e-7))
  95. tag = (lat_int, lon_int)
  96. if tag in done:
  97. continue
  98. done.add(tag)
  99. # make sure tile is inside the 60deg latitude limit
  100. if abs(lat_int) <= 60:
  101. filelist.append(os.path.join(tile_path, getDatFile(lat_int, lon_int)))
  102. else:
  103. outsideLat = True
  104. # make sure tile is inside the 60deg latitude limit
  105. if abs(lat_int) <= 60:
  106. filelist.append(os.path.join(tile_path, getDatFile(lat_int, lon_int)))
  107. else:
  108. outsideLat = True
  109. # remove duplicates
  110. filelist = list(dict.fromkeys(filelist))
  111. print(filelist)
  112. #compress
  113. success = compressFiles(filelist, uuidkey)
  114. # as a cleanup, remove any generated terrain older than 24H
  115. for f in os.listdir(output_path):
  116. if os.stat(os.path.join(output_path, f)).st_mtime < time.time() - 24 * 60 * 60:
  117. print("Removing old file: " + str(os.path.join(output_path, f)))
  118. os.remove(os.path.join(output_path, f))
  119. if success:
  120. print("Generated " + "/terrain/" + uuidkey + ".zip")
  121. return render_template('generate.html', urlkey="/terrain/" + uuidkey + ".zip",
  122. uuidkey=uuidkey, outsideLat=outsideLat)
  123. else:
  124. print("Failed " + "/terrain/" + uuidkey + ".zip")
  125. return render_template('generate.html', error="Cannot generate terrain",
  126. uuidkey=uuidkey)
  127. else:
  128. print("Bad get")
  129. return render_template('generate.html', error="Need to use POST, not GET")
  130. if __name__ == "__main__":
  131. app.run()