orthographic/tileprep.py

376 lines
14 KiB
Python
Raw Normal View History

# -------------------------------------------------------------------
# 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
# -------------------------------------------------------------------
# tileprep.py
# This prepares a zoom level 18 tile for ortho generation. This class
# performs the edge detection, selects the required sources for each
# layer, and stores this information into files which are then used
# by layergen.
# -------------------------------------------------------------------
import glob
from os import MFD_ALLOW_SEALING
from random import randrange
from PIL import Image
from osmxml import *
from maskgen import *
from defines import *
from functions import *
from log import *
from tileinfo import *
class mstr_tileprep:
# For this to work we need some fundamentals.
def __init__(self, lat, lng, v, h, tag, value, mask, is_completion):
self._lat = lat
self._lng = lng
self._tile_h = h
self._tile_v = v
self._tag = tag
self._value = value
self._edges = "" # To be filled by _edgeDetect call
self._source = ""
self._mask = mask
latlngfld = xplane_latlng_folder([lat, lng])
self._tileinfo = mstr_tileinfo(lat, lng, v, h, latlngfld)
# Special case for the final step of an ortho
self._is_completion = is_completion
def _findCorrectTextureFolder(self):
srcfld = []
for lyr in mstr_ortho_layers:
if lyr[0] == self._tag and lyr[1] == self._value:
srcfld.append(lyr[2])
srcfld.append(lyr[3])
break
return srcfld
# Use the mask to determine the edges
def _determineEdges(self):
# Load the mask pixels
mp = self._mask.load()
imgsize = self._mask.width
# Run scan
# Check if pixels touch the borders of the image, and if so -
# make a not of that in the database.
at=False
ar=False
ab=False
al=False
# Top scan
for i in range(0, imgsize):
p = mp[i,0]
if p[3] > 0:
at=True
break
# Right scan
for i in range(0, imgsize):
p = mp[imgsize-1,i]
if p[3] > 0:
ar=True
break
# Bottom scan
for i in range(0, imgsize):
p = mp[i,imgsize-1]
if p[3] > 0:
ab=True
break
# Left scan
for i in range(0, imgsize):
p = mp[0,i]
if p[3] > 0:
al=True
break
# Construct adjacency string
adjstr = ""
if at==True: adjstr = adjstr + "t"
if ar==True: adjstr = adjstr + "r"
if ab==True: adjstr = adjstr + "b"
if al==True: adjstr = adjstr + "l"
# We will now write this down first, without a source being selected
if adjstr != "":
self._tileinfo.add_adjacency_data(self._tag, self._value, "0", adjstr)
# Set the latlng folder
def _setLatLngFold(self, latlngfld):
self._latlngfld = latlngfld
# Find out if there is already something in place for this tag of this tile
def _getResourceInfo(self, tv, th):
# This either remains 0 or a string different to "0" in the end
src = "0"
df = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(tv) + "_" + str(th)
fnlines = []
if os.path.isfile(df) == True: # It is possible that the requested file does not yet exist
with open(df) as textfile:
fnlines = textfile.readlines()
for ln in fnlines:
l = ln.split(" ")
if l[0] == self._tag and l[1] == self._value:
src = l[2]
return src
# Find the edge touch info
def _getResourceTouch(self, tv, th):
touch = ""
df = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(tv) + "_" + str(th)
fnlines = []
if os.path.isfile(df) == True: # It is possible that the requested file does not yet exist
with open(df) as textfile:
fnlines = textfile.readlines()
for ln in fnlines:
l = ln.split(" ")
if l[0] == self._tag and l[1] == self._value:
touch = l[3]
return touch
# Select a combination of resources
def _selectResources(self):
numbers = list(range(1, 16))
res = random.sample(numbers, 5)
# Construct a string of the array
resstr = ""
for r in range(len(res)):
resstr = resstr + str(res[r])
if r < len(res)-1:
resstr = resstr + ","
return resstr
# Store the required resource information into the appropriate tile
def _storeResourceInfo(self, tile_v, tile_h, res):
# Separate file for contrast values
ctrdata = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/ctrdata"
df = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(tile_v) + "_" + str(tile_h)
fnlines = []
if os.path.isfile(df) == True: # It is possible that the requested file does not yet exist
with open(df) as textfile:
fnlines = textfile.readlines()
curline = 0
for ln in fnlines:
l = ln.split(" ")
if len(l) > 1:
if l[0] == self._tag and l[1] == self._value:
l[2] = res
fnlines[curline] = l[0] + " " + l[1] + " " + l[2] + " " + l[3]
curline = curline+1
lines = ""
for l in range(len(fnlines)):
lines = lines + fnlines[l]
with open(df, 'w') as textfile:
textfile.write(lines)
# Take care of contrast value
ctrcontent = []
if os.path.isfile(ctrdata) == True:
with open(ctrdata) as textfile:
ctrcontent = textfile.readlines()
# Compare if we already have a data string for this particular resource
ctrpresent = False
if len(ctrcontent) > 0:
for ln in range(0, len(ctrcontent)):
cnt = ctrcontent[ln].split(" ")
if cnt[0] == self._tag and cnt[1] == self._value and cnt[2] == res:
ctrpresent = True
break
# Should there not be a contrast value for this resource, add it
if ctrpresent == False:
if (
(self._tag == "landuse" and self._value == "forest") or
(self._tag == "landuse" and self._value == "meadow") or
(self._tag == "landuse" and self._value == "grass") or
(self._tag == "leisure" and self._value == "nature_reserve") or
(self._tag == "natural" and self._value == "grassland") or
(self._tag == "landuse" and self._value == "greenfield") or
(self._tag == "natural" and self._value == "heath") or
(self._tag == "natural" and self._value == "wetland") or
(self._tag == "leisure" and self._value == "park") or
(self._tag == "building")
):
contrast = str(randrange(1, 4))
newline = self._tag + " " + self._value + " " + res + " " + str(contrast) + "\n"
with open(ctrdata, 'a') as textfile:
textfile.write(newline)
# Find neighborinf tiles
def _findNeighbors(self, tv, th):
return [ (tv+1, th), (tv, th+1), (tv-1, th), (tv, th-1) ]
# Walk through the now existing data files and make sure we always pick the correct
# sources for every tile, thus evading previous edge detection errors
def _placeTileSources(self, mlat, mlng):
# None of the edges have reached their end yet
edge_end = [0,0,0,0] # top, right, bottom, left
# Array with info we need
resinfo = ["", ""] # Touch, Resource numbers
# Go through everything until the end is reached (no more options left)
end_reached = False
while end_reached == False:
# Go north
tv = self._tile_v
th = self._tile_h
while edge_end[0] == 0:
resinfo[0] = self._getResourceTouch(tv, th)
resinfo[1] = self._getResourceInfo(tv, th)
# Only do the following steps if we have nothing stored
if resinfo[1] == "0":
neighbors = self._findNeighbors(tv, th)
neighborinfo = ["",""]
for n in range(0, len(neighbors)):
neighborinfo[0] = self._getResourceTouch(neighbors[n][0], neighbors[n][1])
neighborinfo[1] = self._getResourceInfo(neighbors[n][0], neighbors[n][1])
if "b" in neighborinfo[0] and neighborinfo[1] != "0":
resinfo[1] = neighborinfo[1]
break
# Store info. At this point we either have neighboring data, or
# we need to select something
if resinfo[1] == "0": resinfo[1] = self._selectResources()
self._storeResourceInfo(tv, th, resinfo[1])
# Move forward
if "t" in resinfo[0]:
tv=tv+1
else:
edge_end[0] = 1
# Go east
tv = self._tile_v
th = self._tile_h
while edge_end[1] == 0:
resinfo[0] = self._getResourceTouch(tv, th)
resinfo[1] = self._getResourceInfo(tv, th)
# Only do the following steps if we have nothing stored
if resinfo[1] == "0":
neighbors = self._findNeighbors(tv, th)
neighborinfo = ["",""]
for n in range(0, len(neighbors)):
neighborinfo[0] = self._getResourceTouch(neighbors[n][0], neighbors[n][1])
neighborinfo[1] = self._getResourceInfo(neighbors[n][0], neighbors[n][1])
if "l" in neighborinfo[0] and neighborinfo[1] != "0":
resinfo[1] = neighborinfo[1]
break
# Store info. At this point we either have neighboring data, or
# we need to select something
if resinfo[1] == "0": resinfo[1] = self._selectResources()
self._storeResourceInfo(tv, th, resinfo[1])
# Move forward
if "r" in resinfo[0]:
th=th+1
else:
edge_end[1] = 1
# Go south
tv = self._tile_v
th = self._tile_h
while edge_end[2] == 0:
resinfo[0] = self._getResourceTouch(tv, th)
resinfo[1] = self._getResourceInfo(tv, th)
# Only do the following steps if we have nothing stored
if resinfo[1] == "0":
neighbors = self._findNeighbors(tv, th)
neighborinfo = ["",""]
for n in range(0, len(neighbors)):
neighborinfo[0] = self._getResourceTouch(neighbors[n][0], neighbors[n][1])
neighborinfo[1] = self._getResourceInfo(neighbors[n][0], neighbors[n][1])
if "t" in neighborinfo[0] and neighborinfo[1] != "0":
resinfo[1] = neighborinfo[1]
break
# Store info. At this point we either have neighboring data, or
# we need to select something
if resinfo[1] == "0": resinfo[1] = self._selectResources()
self._storeResourceInfo(tv, th, resinfo[1])
# Move forward
if "b" in resinfo[0]:
tv=tv-1
else:
edge_end[2] = 1
# Go west
tv = self._tile_v
th = self._tile_h
while edge_end[3] == 0:
resinfo[0] = self._getResourceTouch(tv, th)
resinfo[1] = self._getResourceInfo(tv, th)
# Only do the following steps if we have nothing stored
if resinfo[1] == "0":
neighbors = self._findNeighbors(tv, th)
neighborinfo = ["",""]
for n in range(0, len(neighbors)):
neighborinfo[0] = self._getResourceTouch(neighbors[n][0], neighbors[n][1])
neighborinfo[1] = self._getResourceInfo(neighbors[n][0], neighbors[n][1])
if "r" in neighborinfo[0] and neighborinfo[1] != "0":
resinfo[1] = neighborinfo[1]
break
# Store info. At this point we either have neighboring data, or
# we need to select something
if resinfo[1] == "0": resinfo[1] = self._selectResources()
self._storeResourceInfo(tv, th, resinfo[1])
# Move forward
if "l" in resinfo[0]:
th=th-1
else:
edge_end[3] = 1
if edge_end[0] == 1 and edge_end[1] == 1 and edge_end[2] == 1 and edge_end[3] == 1:
end_reached = True # <- Break loop