171 lines
6.8 KiB
Python
171 lines
6.8 KiB
Python
|
|
# -------------------------------------------------------------------
|
|
# 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)
|
|
|
|
# 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")
|
|
|
|
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
|
|
'''
|