# ------------------------------------------------------------------- # ORTHOGRAPHIC # Your personal aerial satellite. Always on. At any altitude.* # Developed by MarStrMind # License: Open Software License 3.0 # Up to date version always on marstr.online # ------------------------------------------------------------------- # tilegen.py # Generates ZL16 tiles from the generated material, while checking on # presence of airports, and keeping ZL18 tiles of the specified # radius in defines.py. This also writes down the correspoding .ter # files for X-Plane. Be careful: the unneeded ZL18 tiles will be # removed. # ------------------------------------------------------------------- from PIL import Image, ImageFilter from log import * from functions import * from tiledb import * import math import os import glob class mstr_tilegen: # We only need some values. Also sets up connection to DB def __init__(self, lat, lng, vstep, max_lat, max_lng): self._lat = lat self._lng = lng self._vstep = vstep self._maxlat = max_lat self._maxlng = max_lng # Connection to DB self._tiledb = mstr_tiledb(lat, lng) mstr_msg("tilegen", "Tilegen initialized") # To write down X-Plane .ter files, we will need to know the exact size # of the particular longitude we are in, as this value varies depending # on where you are on a sphere. # Returned values is in meters. # The current latitude is needed. def _findWidthOfLongitude(self, lat): dm = math.cos(math.radians(lat)) * 111.321 # <- 1 deg width at equator in km return round(dm * 1000, 3) # Generates the ZL16 tiles and stores them. # We generate ZL16 tiles first, then we check which tiles to keep near airports def genTiles(self): # The current lat and lng tile numbers cur_lat = 1 cur_lng = 1 # Actual starting coordinates for ZL16 a_lat = self._lat + self._vstep * 2 a_lng = self._lng + mstr_zl_18 * 2 # Scaled res scaled_res = int(mstr_photores/4) # For example, 512 for a photo res of 2048 # Find out how many steps we can walk in every direction steps_lat = int(math.ceil(self._maxlat/4)) steps_lng = int(math.ceil(self._maxlng/4)) mstr_msg("tilegen", "Latitude and longitude steps determined") # OK... so. Let's finish this. for lt in range(1, steps_lat): for ln in range(1, steps_lng): # Check if we need to do something if os.path.isfile(mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/Textures/" + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg") == False: mstr_msg("tilegen", "Generating missing zoom level 16 ortho " + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg") # Find out which tiles to process tiles = findZL16tiles(cur_lat, cur_lng) # Generate the ZL16 image zl16 = Image.new("RGB", (mstr_photores, mstr_photores)) # Walk through this array xpos = 0 ypos = int(scaled_res*3) for i in range(0, 3): for j in range(0, 3): # We may run into situations where ask for tiles that don't exist... # Let's make sure we can continue fpath = mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/Textures/" + str(tiles[i][j][0]) + "_" + str(tiles[i][j][1]) + ".jpg" if os.path.isfile( fpath ): tlimg = Image.open(fpath) tlimg = tlimg.resize((scaled_res,scaled_res), Image.Resampling.BILINEAR) zl16.paste(tlimg, (xpos, ypos)) xpos = xpos + scaled_res xpos = 0 ypos = ypos - scaled_res # Now save this image zl16.save(mstr_datafolder + "Tiles/" + str(self._lat) + "_" + str(self._lng) + "/Textures/" + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG16.jpg", format='JPEG', subsampling=0, quality=100) # Store a terrain file dmt = self._findWidthOfLongitude(a_lat) * mstr_zl_16 ter_content = """A 800 TERRAIN LOAD_CENTER """ + str(a_lat) + " " + str(a_lng) + " " + str(dmt) + " " + "../Textures/" + str(self._lat) + "-" + str(ln) + "_" + str(self._lng) + "-" + str(lt) + "_OG_16.jpg"+""" NO_ALPHA""" with open(mstr_datafolder + "/Tiles/"+str(self._lat)+"_"+str(self._lng)+"/terrain/"+str(self._lat)+"_"+str(lt)+"-"+str(self._lng)+"-"+str(ln)+"_OG16.ter", 'w') as textfile: textfile.write(ter_content) mstr_msg("tilegen", "Wrote .ter file") # Adjust a_lng = a_lng + (mstr_zl_16 * 4) cur_lng = cur_lng + 4 mstr_msg("tilegen", "Adjusted coordinate values") # Adjust a_lng = self._lat + (mstr_zl_16 * 2) a_lat = a_lat + (self._vstep * 4) cur_lat = cur_lat + 4 cur_lng = self._lng mstr_msg("tilegen", "Adjusted coordinate values for next tile loop") mstr_msg("tilegen", "Tile generation... completed (wow.jpg)") # BUT! This is not the end. Yet. # Make sure we keep tiles around airports. airports = self._tiledb.get_tiles_with_airports() mstr_msg("tilegen", "Filtering ZL18 tiles for airports") # The ZL 18 tiles to keep in the end tiles = [] mstr_msg("tilegen", "Finding ZL18 tiles to keep") for a in airports: tiles.append(findAirportTiles(int(a[1]), int(a[2]))) mstr_msg("tilegen", "Determined ZL18 tiles") # Create a final array to make life easier mstr_msg("tilegen", "Generating arrays for tiles to keep") keeping = [] for t in tiles: for i in t: keeping.append(i) # Perform the cleanup mstr_msg("tilegen", "Cleaning up non-needed tiles") for y in range(1, self._maxlat): for x in range(1, self._maxlng): fn = str(y) + "_" + str(x) + ".jpg" found = False for k in keeping: kfn = str(k[0]) + "_" + str(k[1]) + ".jpg" if fn == kfn: found = True break if found == False: os.remove(mstr_datafolder + "/Tiles/" + str(self._lat) + "_" + str(self._lng) + "/Textures/" + fn) mstr_msg("tilegen", "Cleanup completed") # And now for the final act of tonight's entertainment mstr_msg("tilegen", "Writing .ter files for ZL18 tiles") for k in keeping: k_lat = self._lat + (k[0] * self._vstep) + (self._vstep * 0.5) k_lng = self._lat + (k[1] * mstr_zl_18) + (mstr_zl_18 * 0.5) k_dmt = self._findWidthOfLongitude(self._lng * mstr_zl_18) k_fln = mstr_datafolder + "/Tiles/" + str(self._lat) + "_" + str(self._lng) + "/terrain/" + str(k[0]) + "_" + str(k[1]) + ".ter" ter_content = """A 800 TERRAIN LOAD_CENTER """ + str(k_lat) + " " + str(k_lng) + " " + str(k_dmt) + " " + "../Textures/" + str(k[0]) + "_" + str(k[1]) + ".jpg"+""" NO_ALPHA""" with open(k_fln, 'w') as textfile: textfile.write(ter_content) mstr_msg("tilegen", "Wrote all .ter files for ZL18 tiles.") mstr_msg("tilegen", "Work complete.") ''' Did we fly to the moon too soon? Did we squander the chance? In the rush of the race The reason we chase is lost in romance And still we try To justify the waste For a taste of man's greatest adventure I blame you for the moonlit sky And the dream that died With the eagles' flights I blame you for the moonlit nights When I wonder why Are the seas still dry Don't blame this sleeping satellite '''