1085 lines
57 KiB
Python
1085 lines
57 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
|
|
# -------------------------------------------------------------------
|
|
# layergen.py
|
|
# Generates a full-sized geo layer image, based on the required layer
|
|
# type. We use a simple randomization method to generate such an
|
|
# image, which is then used for the final photo in photogen.
|
|
# -------------------------------------------------------------------
|
|
|
|
import glob
|
|
import os
|
|
from random import randrange
|
|
import random
|
|
from PIL import Image, ImageFilter, ImageDraw
|
|
from defines import *
|
|
from log import *
|
|
from tileinfo import *
|
|
from osmxml import *
|
|
from functions import *
|
|
|
|
class mstr_layergen:
|
|
|
|
# Initializes the layer generator. can_choose will go false if we need
|
|
# a pre-determined layer from another tile, should this be adjacent to it.
|
|
# In this case layer_needed will be populated with the appropriate number.
|
|
# You also need the zoom level so that we can generate a scaled version.
|
|
def __init__(self, tag, value, lat, latnum, lng, lngnum, is_line, is_completion=False):
|
|
self._tag = tag
|
|
self._value = value
|
|
self._latitude = lat
|
|
self._lat_number = latnum
|
|
self._longitude = lng
|
|
self._lng_number = lngnum
|
|
self._layerborder = -1
|
|
self._is_completion = is_completion
|
|
# Define layer size depending on what is wanted
|
|
self._imgsize = 0
|
|
self._isline = is_line
|
|
if mstr_photores == 2048: self._imgsize = 2048
|
|
#if mstr_photores == 4096: self._imgsize = 6000
|
|
#mstr_msg("layergen", "Layer gen initialized")
|
|
|
|
# Define maximum latitude and longitude tile numbers
|
|
def set_max_latlng_tile(self, maxlatlng):
|
|
self._maxlat = maxlatlng[0]
|
|
self._maxlng = maxlatlng[1]
|
|
mstr_msg("layergen", "Maximum latitude and longitude tile numbers received")
|
|
|
|
# Set latlng folder
|
|
def set_latlng_folder(self, latlngfld):
|
|
self._latlngfld = latlngfld
|
|
|
|
# Tile info object
|
|
def open_tile_info(self):
|
|
self._tileinfo = mstr_tileinfo(self._latitude, self._longitude, self._lat_number, self._lng_number, self._latlngfld)
|
|
|
|
# This generates a "border" image, for example farmland usually has a small space of grass
|
|
# before the actual crop of farm field itself. This generates this "border" layer,
|
|
# and returns it.
|
|
# Needs the actual edge mask, and the tag and value to be used as border.
|
|
# Perform necessary adjustments on the mask prior to this call, for example blurring or
|
|
# other effects.
|
|
def genborder(self, edgemask, tag, value):
|
|
layer = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
root_folder = mstr_datafolder + "textures/" + tag + "/" + value
|
|
|
|
# Determine which sources we use
|
|
brd = glob.glob(root_folder + "/brd/b*.png")
|
|
src = -1
|
|
if len(brd) == 1: src=1
|
|
if len(brd) >= 2:
|
|
src = randrange(1, len(brd)+1)
|
|
ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")
|
|
|
|
# Load in the sources to work with
|
|
brd_src = Image.open(root_folder + "/brd/b" + str(src) + ".png")
|
|
ptc_src = []
|
|
for p in ptc:
|
|
pimg = Image.open(p)
|
|
pimg = pimg.rotate(randrange(0, 360), expand=True)
|
|
ptc_src.append(pimg)
|
|
mstr_msg("layergen", "Border sources selected")
|
|
|
|
# Begin producing a largely random image
|
|
samples = 250 # <- We need this in a moment
|
|
for i in range(samples):
|
|
imgid = 0
|
|
if len(ptc_src) == 1: imgid = 0
|
|
if len(ptc_src) >= 2:
|
|
imgid = randrange(1, len(ptc_src)+1) - 1
|
|
l = 0 - int(ptc_src[imgid].width / 2)
|
|
r = layer.width - int(ptc_src[imgid].width / 2)
|
|
t = 0 - int(ptc_src[imgid].height / 2)
|
|
b = layer.height - int(ptc_src[imgid].height / 2)
|
|
layer.alpha_composite( ptc_src[imgid], ( randrange(l, r), randrange(t, b) ) )
|
|
mstr_msg("layergen", "Border image generated")
|
|
|
|
# We now need to add the seamless border
|
|
layer.alpha_composite( brd_src )
|
|
mstr_msg("layergen", "Layer image completed")
|
|
|
|
# And now for the Big Mac.
|
|
# Generate the layer from the mask.
|
|
layer_comp = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
layer_final = Image.composite(layer, layer_comp, edgemask)
|
|
|
|
# Provide the image
|
|
return layer_final
|
|
|
|
|
|
# Find the source to use pre-determined in phase one
|
|
def findLayerSource(self):
|
|
# The source number
|
|
src = -1
|
|
|
|
# The already existing source data
|
|
srcfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(self._lng_number)
|
|
|
|
# Let's open the file and find our entry
|
|
with open(srcfile) as file:
|
|
for line in file:
|
|
linedata = line.split(" ")
|
|
if linedata[2] == self._tag and linedata[3] == self._value:
|
|
src = int(linedata[4])
|
|
break
|
|
|
|
# Should we encounter a -1 at this point, we can choose something
|
|
# It means it touches no border as it was not found in the file
|
|
if src == -1:
|
|
root_folder = mstr_datafolder + "textures/"
|
|
for s in mstr_ortho_layers:
|
|
if s[0] == self._tag and s[1] == self._value:
|
|
fld_main = len(s)-2
|
|
fld_sub = len(s)-1
|
|
root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]
|
|
|
|
brd = glob.glob(root_folder + "/brd/b*.png")
|
|
src = randrange(1, len(brd)+1)
|
|
|
|
return src
|
|
|
|
|
|
|
|
# This generates the layer from the defined mask
|
|
def genlayer(self, mask, xml):
|
|
|
|
mstr_msg("layergen", "Layer to be generated: " + str(self._latitude) + "-" + str(self._lat_number) + ":" + str(self._longitude) + "-" + str(self._lng_number) + " -- tag: " + self._tag + " - value: " + self._value )
|
|
|
|
# Before we generate the layer, let's check for airports in this chunk
|
|
mstr_msg("layergen", "Checking for airport/s with ICAO code")
|
|
|
|
icao = None
|
|
if xml != None:
|
|
icao = xml.find_icao_codes()
|
|
mstr_msg("layergen", "Found " + str(len(icao)) + " airport/s")
|
|
# Runway surface, if any other than concrete/asphalt
|
|
rw_surface = ""
|
|
# If we find an airport, make a note ...
|
|
if icao != None:
|
|
if len(icao) >= 1 and self._is_completion == False:
|
|
#for i in icao:
|
|
# ... but only, if this airport is not already noted
|
|
#iccheck = self._tiledb.perform_query("SELECT * FROM airports WHERE icao='" + i +"';")
|
|
#if len(iccheck) == 0:
|
|
#self._tiledb.insert_icao(i, self._lat_number, self._lng_number, self._latitude, self._longitude)
|
|
# mstr_msg("layergen", "Airport/s noted in data file")
|
|
rw_surface = xml.find_runway_surface()
|
|
|
|
# The image for the layer itself
|
|
layer = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
layer_pix = layer.load()
|
|
|
|
# There are some things we need to use sources for, and some things, we do not.
|
|
# We need to differentiate that.
|
|
|
|
if (self._isline == False and self._tag != "building") or (self._is_completion == True):
|
|
# Determine where we get the our source material from
|
|
root_folder = mstr_datafolder + "textures/"
|
|
for s in mstr_ortho_layers:
|
|
if s[0] == self._tag and s[1] == self._value:
|
|
fld_main = len(s)-2
|
|
fld_sub = len(s)-1
|
|
root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]
|
|
|
|
# Determine which sources to use.
|
|
src = self.findLayerSource()
|
|
|
|
ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")
|
|
|
|
# Load in the sources to work with
|
|
brd_src = Image.open(root_folder + "/brd/b" + str(src) + ".png")
|
|
ptc_src = []
|
|
for p in ptc:
|
|
ptc_src.append(Image.open(p))
|
|
mstr_msg("layergen", "Layer sources selected")
|
|
|
|
# Generate an edge mask from the original
|
|
osm_edge = mask.filter(ImageFilter.FIND_EDGES)
|
|
osm_edge = osm_edge.filter(ImageFilter.MaxFilter)
|
|
mstr_msg("layergen", "Edge mask generated")
|
|
|
|
# This adds some natural looking shapes to these types of features
|
|
if self._value == "forest" or self._value == "nature_reserve":
|
|
epx = osm_edge.load()
|
|
imgd = ImageDraw.Draw(mask)
|
|
|
|
# Walk through a grid of 100x100 - on the edge image
|
|
for y in range(0, mask.height, int(mask.height/100)):
|
|
for x in range(0, mask.width, int(mask.width/100)):
|
|
px = epx[x,y]
|
|
if px[3] == 255:
|
|
rx = randrange(24,60)
|
|
ry = randrange(24,60)
|
|
f = randrange(1,10)
|
|
|
|
# Randomize the found locations a little
|
|
psx = randrange(x-11, x+11)
|
|
psy = randrange(y-11, y+11)
|
|
|
|
# Do some magic - but not on edges
|
|
if x > 0 and x < mask.width and y > 0 and y < mask.height:
|
|
if f != 5:
|
|
imgd.ellipse((psx-int(rx/2), psy-int(ry/2), psx+rx, psy+ry), fill="black")
|
|
if f == 3 or f == 7:
|
|
imgd.ellipse((psx-int(rx/2), psy-int(ry/2), psx+rx, psy+ry), fill=(0,0,0,0))
|
|
|
|
|
|
# We need to change the image in certain conditions
|
|
if self._value == "hedge" and self._tag == "barrier":
|
|
mask = osm_edge
|
|
|
|
# From here on in we will need to perform some adjustments on the masks, depending
|
|
# on what they are.
|
|
for i in mstr_mask_blur:
|
|
if i[0] == self._tag and i[1] == self._value:
|
|
if self._tag != "place" and (self._value != "sea" or self._value != "ocean"):
|
|
mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))
|
|
break
|
|
|
|
# Begin producing a largely random image
|
|
samples = 250 # <- We need this in a moment
|
|
for i in range(samples):
|
|
imgid = 0
|
|
if len(ptc_src) == 1: imgid = 0
|
|
if len(ptc_src) >= 2:
|
|
imgid = randrange(1, len(ptc_src)+1) - 1
|
|
l = 0 - int(ptc_src[imgid].width / 2)
|
|
r = layer.width - int(ptc_src[imgid].width / 2)
|
|
t = 0 - int(ptc_src[imgid].height / 2)
|
|
b = layer.height - int(ptc_src[imgid].height / 2)
|
|
layer.alpha_composite( ptc_src[imgid], ( randrange(l, r), randrange(t, b) ) )
|
|
mstr_msg("layergen", "Layer image generated")
|
|
|
|
# We now need to add the seamless border
|
|
layer.alpha_composite( brd_src )
|
|
|
|
# Here we need to do some magic to make some features look more natural
|
|
if (self._tag == "landuse" and self._value == "meadow") or (self._tag == "natural" and self._value == "grassland") or (self._tag == "natural" and self._value == "heath") or (self._tag == "landuse" and self._value == "cemetery") or (self._tag == "landuse" and self._value == "residential"):
|
|
if self._is_completion == False:
|
|
amt = randrange(2, 9)
|
|
for i in range(1, amt+1):
|
|
ptc = randrange(1, 14)
|
|
img = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(ptc)+".png")
|
|
img = img.rotate(randrange(0, 360), expand=True)
|
|
a = img.getchannel("A")
|
|
bbox = a.getbbox()
|
|
img = img.crop(bbox)
|
|
lx = randrange( self._imgsize - img.width )
|
|
ly = randrange( self._imgsize - img.height )
|
|
layer.alpha_composite( img, (lx, ly) )
|
|
if self._is_completion == True:
|
|
mp = mask.load()
|
|
edn = self.xplane_latlng_folder(self.find_earthnavdata_number())
|
|
idx = 0
|
|
for r in mstr_completion_colors:
|
|
if r[0] == edn:
|
|
break
|
|
else:
|
|
idx = idx+1
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mp[x,y][3] > 0:
|
|
# Pick a color
|
|
a = mp[x,y]
|
|
cidx = randrange(len(mstr_completion_colors[idx][1]))
|
|
clr = mstr_completion_colors[idx][1][cidx]
|
|
layer_pix[x,y] = (clr[0], clr[1], clr[2], a[3])
|
|
amt = randrange(1,51)
|
|
for i in range(1, amt+1):
|
|
ptc = randrange(1, 14)
|
|
img = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(ptc)+".png")
|
|
img = img.rotate(randrange(0, 360), expand=True)
|
|
a = img.getchannel("A")
|
|
bbox = a.getbbox()
|
|
img = img.crop(bbox)
|
|
imgp = img.load()
|
|
for y in range(img.height):
|
|
for x in range(img.width):
|
|
c = imgp[x,y]
|
|
nc = (c[0], c[1], c[2], int(imgp[x,y][3]*0.4))
|
|
imgp[x,y] = nc
|
|
lx = randrange( self._imgsize - img.width )
|
|
ly = randrange( self._imgsize - img.height )
|
|
layer.alpha_composite( img, (lx, ly))
|
|
layer = layer.filter(ImageFilter.GaussianBlur(radius=1))
|
|
|
|
|
|
# Add trees only in some features
|
|
if (self._tag == "landuse" and self._value == "cemetery") or (self._tag == "landuse" and self._value == "residential") or (self._tag == "leisure" and self._value == "park"):
|
|
trees = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
amt = 3500
|
|
for i in range(1, amt+1):
|
|
p = randrange(1, 16)
|
|
tree = Image.open(mstr_datafolder + "textures/building/area/p" + str(p) + ".png")
|
|
lx = randrange( self._imgsize - tree.width )
|
|
ly = randrange( self._imgsize - tree.height )
|
|
trees.alpha_composite(tree, (lx, ly))
|
|
|
|
tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
tree_pix = trees.load()
|
|
shadow_pix = tree_shadow.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
tp = tree_pix[x,y]
|
|
if tp[3] > 0:
|
|
rndshd = randrange(5, 210)
|
|
sc = (0,0,0,rndshd)
|
|
if x+8 < self._imgsize and y+5 < self._imgsize:
|
|
shadow_pix[x+8,y+5] = sc
|
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
|
tree_shadow.alpha_composite(trees)
|
|
layer.alpha_composite(tree_shadow)
|
|
|
|
mstr_msg("layergen", "Layer image completed")
|
|
|
|
|
|
# And now for the Big Mac.
|
|
# Generate the layer from the mask.
|
|
layer_comp = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
layer_pix = layer.load()
|
|
mask_pix = mask.load()
|
|
layer_comp_pix = layer_comp.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mask_pix[x, y][3] > 0:
|
|
rgb=layer_pix[x,y]
|
|
a=mask_pix[x,y]
|
|
layer_comp_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])
|
|
|
|
# For some things, we will need to add a border and then add this to the layer.
|
|
layer_border = None
|
|
if self._tag == "landuse":
|
|
if self._value == "forest" or self._value == "farmland":
|
|
osm_edge = osm_edge.filter(ImageFilter.ModeFilter(size=15))
|
|
osm_edge = osm_edge.filter(ImageFilter.BoxBlur(radius=2))
|
|
layer_border = self.genborder(osm_edge, "landuse", "meadow")
|
|
layer_comp.alpha_composite(layer_border)
|
|
|
|
|
|
# Here we want to make sure that the generated image fits well with others, so
|
|
# let's do that.
|
|
mstr_msg("layergen", "Generating adjacent fades")
|
|
adjfade = self.generate_adjacent_fades(mask)
|
|
|
|
layer_comp.alpha_composite(adjfade)
|
|
mstr_msg("layergen", "Adjacent fading completed")
|
|
|
|
|
|
# Add a white-ish border around pitches
|
|
if self._tag == "leisure" and self._value == "pitch":
|
|
epx = osm_edge.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
ep = epx[x,y]
|
|
if ep[3] > 0:
|
|
d = randrange(10,101)
|
|
nw = (200-d,200-d,200-d,255)
|
|
layer_comp_pix[x,y] = nw
|
|
|
|
# I need to put this special sub-call here to solve an otherwise unsolvable
|
|
# conflict with layer order
|
|
if self._tag == "landuse" and self._value == "forest":
|
|
# The residential layer MUST exist before we reach the forest part.
|
|
fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_landuse-residential_layer.png"
|
|
if os.path.isfile(fn):
|
|
rsd = Image.open(fn)
|
|
rsd_pix = rsd.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
rpix = rsd_pix[x,y]
|
|
lpix = layer_comp_pix[x,y]
|
|
if rpix[3] > 0 and lpix[3] > 0:
|
|
layer_comp_pix[x,y] = (lpix[0], lpix[1], lpix[2], 255-rpix[3])
|
|
|
|
# Store layer
|
|
#if self._is_completion == False:
|
|
# layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
|
#if self._is_completion == True:
|
|
# layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion_layer.png" )
|
|
#layer_final.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
|
mstr_msg("layergen", "Layer image finalized and saved.")
|
|
|
|
|
|
# Depending on if scenery for XP should be made, AND if normal maps should be made, we would
|
|
# need to make them at this exact point
|
|
"""
|
|
if mstr_xp_genscenery == True:
|
|
if mstr_xp_scn_normalmaps == True and self._is_completion == False:
|
|
nm = False
|
|
for n in mstr_xp_normal_maps:
|
|
if n[0] == self._tag and (n[1] == self._value or n[1] == "*"):
|
|
nm = True
|
|
break
|
|
if nm == True:
|
|
nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)
|
|
nrm.build_normalmap(layer_comp)
|
|
"""
|
|
|
|
|
|
# Let's try our hand at pseudo shadows
|
|
if mstr_shadow_enabled == True:
|
|
if mstr_shadow_shift >= 2:
|
|
shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
for sh in mstr_shadow_casters:
|
|
if self._tag == sh[0] and self._value == sh[1]:
|
|
mstr_msg("layergen", "Generating shadow for layer")
|
|
shadow_pix = shadow.load()
|
|
mask_pix = mask.load()
|
|
shf = 1
|
|
while shf < mstr_shadow_shift:
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
mp = layer_comp_pix[x,y]
|
|
if mp[3] == 255:
|
|
if x+(shf*2) < self._imgsize and y+shf < self._imgsize:
|
|
rndshd = randrange(5, 210)
|
|
shadow_pix[x+(shf*2), y+shf] = (0,0,0,rndshd)
|
|
shf = shf+1
|
|
|
|
# Tree removal
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
lp = layer_comp_pix[x,y]
|
|
if lp[3] >= 250:
|
|
shadow_pix[x,y] = (0,0,0,0)
|
|
|
|
shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1.5))
|
|
|
|
#shadow.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_shadow.png")
|
|
shadow.alpha_composite(layer_comp)
|
|
layer_comp = shadow
|
|
mstr_msg("layergen", "Shadow layer completed")
|
|
|
|
|
|
# Create a water mask we need to remove from the DDS later
|
|
"""
|
|
if (self._tag == "natural" and self._value == "water") or (self._tag == "water" and self._value == "lake") or (self._tag == "water" and self._value == "pond") or (self._tag == "water" and self._value == "river") or (self._tag == "leisure" and self._value == "swimming_pool"):
|
|
mstr_msg("layergen", "Generating inland water mask")
|
|
water_file = mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(self._lng_number) + "_water.png"
|
|
inl_mask = None
|
|
if os.path.isfile(water_file):
|
|
inl_mask = Image.open(water_file)
|
|
else:
|
|
inl_mask = Image.new("L", (self._imgsize, self._imgsize), (255))
|
|
lyr_pix = layer_comp.load()
|
|
inl_pix = inl_mask.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
l = lyr_pix[x,y]
|
|
if l[3] > 50:
|
|
clr = 255-l[3]
|
|
c = (clr)
|
|
inl_pix[x,y] = c
|
|
inl_mask.save(water_file)
|
|
#if l[3] > 65:
|
|
# b = 255 - l[3]
|
|
# inl_pix[x,y] = (255,0,255,255)
|
|
#inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")
|
|
#layer_comp = inl_mask
|
|
mstr_msg("layergen", "Inland water mask generated and saved")
|
|
"""
|
|
|
|
# Return the completed image
|
|
return layer_comp
|
|
|
|
|
|
# ---------------------------------------------------------------------------------------
|
|
# ---------------------------------------------------------------------------------------
|
|
# ---------------------------------------------------------------------------------------
|
|
|
|
# If we encounter one of these road-specific tags, we need to proceed differently.
|
|
|
|
if self._isline == True or self._tag == "building":
|
|
|
|
# We will need the mask in question
|
|
#mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )
|
|
|
|
# Generate an edge mask from the original
|
|
osm_edge = mask.filter(ImageFilter.FIND_EDGES)
|
|
osm_edge = osm_edge.filter(ImageFilter.MaxFilter)
|
|
mstr_msg("layergen", "Edge mask generated")
|
|
|
|
# As above, we will apply the blur as noted in the defines
|
|
# Except for buildings
|
|
if self._tag != "building":
|
|
for i in mstr_mask_blur:
|
|
if i[0] == self._tag and i[1] == self._value:
|
|
mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))
|
|
break
|
|
|
|
|
|
# And now for the Big Mac.
|
|
# Generate the layer from the mask. Same as above - except!
|
|
# This time we have no source material - instead we will fill the
|
|
# mask with a color that is appropriate for this street type.
|
|
layer_comp = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
mask_pix = mask.load()
|
|
edge_pix = osm_edge.load()
|
|
layer_comp_pix = layer_comp.load()
|
|
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mask_pix[x, y][3] > 0:
|
|
a=mask_pix[x,y]
|
|
e=edge_pix[x,y]
|
|
# Find a suitable color
|
|
d = 0
|
|
if self._tag == "aeroway" and self._value == "runway":
|
|
# It seems only runways with any other surface than concrete
|
|
# are mentioned in OSM. So we need to make sure when to render
|
|
# "concrete" and when to leave it. Only sometimes the word
|
|
# "asphalt" is mentioned
|
|
if rw_surface == "" or rw_surface == "asphalt":
|
|
d = randrange(81, 101)
|
|
layer_comp_pix[x, y] = ( d,d,d,a[3] )
|
|
if self._tag == "aeroway" and self._value == "taxiway":
|
|
# Almost the same as above
|
|
d = randrange(81, 101)
|
|
layer_comp_pix[x, y] = ( d,d,d,a[3] )
|
|
if self._tag == "railway":
|
|
d = randrange(41, 61)
|
|
layer_comp_pix[x, y] = ( d,d,d,a[3] )
|
|
if self._tag == "highway" and self._value != "motorway":
|
|
dr = randrange(110,121)
|
|
dg = randrange(110,121)
|
|
db = randrange(115,130)
|
|
layer_comp_pix[x, y] = ( dr,dg,db,a[3] )
|
|
if self._tag == "highway" and self._value == "motorway":
|
|
dr = randrange(77,89)
|
|
dg = randrange(88,96)
|
|
db = randrange(90,101)
|
|
layer_comp_pix[x, y] = ( dr,dg,db,a[3] )
|
|
if self._tag == "waterway" and (self._value == "stream" or self._value == "river"):
|
|
d = randrange(1, 15)
|
|
# Rock, grass, water
|
|
mats = [ (48-d, 45-d, 42-d), (58-d, 81-d, 41-d), (129-d, 148-d, 159-d) ]
|
|
# Pick one of those
|
|
#pick = randrange(1,4)
|
|
pick = 2
|
|
t = a[3]-d
|
|
if t < 0: t = 0
|
|
if e[3] > 0:
|
|
layer_comp_pix[x, y] = ( mats[pick-1][0], mats[pick-1][1], mats[pick-1][2], 35 )
|
|
|
|
# A bit special here
|
|
if self._tag == "building":
|
|
# Find a color range for the pixel
|
|
d = randrange(1,21)
|
|
nr = a[0]+40 - d
|
|
ng = a[1]+40 - d
|
|
nb = a[2]+40 - d
|
|
if nr < 0: nr = 0
|
|
if ng < 0: ng = 0
|
|
if nb < 0: nb = 0
|
|
if nr > 255: nr = 255
|
|
if ng > 255: ng = 255
|
|
if nb > 255: nb = 255
|
|
nc = (nr, ng, nb, 255)
|
|
layer_comp_pix[x,y] = (nr,ng,nb,255)
|
|
|
|
if self._value == "track" or self._value == "path":
|
|
d = randrange(1,20)
|
|
r = 164 - d
|
|
g = 159 - d
|
|
b = 138 - d
|
|
layer_comp_pix[x, y] = ( r,g,b,a[3] )
|
|
|
|
# A bit different for tree rows
|
|
if self._tag == "natural" and self._value == "tree_row":
|
|
trees = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
for t in range(20001):
|
|
lx = randrange(self._imgsize)
|
|
ly = randrange(self._imgsize)
|
|
a = mask_pix[lx,ly]
|
|
if a[3] > 0:
|
|
if lx < self._imgsize and ly < self._imgsize:
|
|
p = randrange(1,16)
|
|
tree = Image.open(mstr_datafolder + "textures/building/area/p" + str(p) + ".png")
|
|
trees.alpha_composite(tree, (lx, ly))
|
|
if mstr_shadow_enabled == True:
|
|
tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
tree_pix = trees.load()
|
|
shadow_pix = tree_shadow.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
tp = tree_pix[x,y]
|
|
if tp[3] > 0:
|
|
rndshd = randrange(5, 210)
|
|
sc = (0,0,0,rndshd)
|
|
if x+8 < self._imgsize and y+5 < self._imgsize:
|
|
shadow_pix[x+8,y+5] = sc
|
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
|
tree_shadow.alpha_composite(trees)
|
|
layer_comp.alpha_composite(tree_shadow)
|
|
|
|
# We will do some super magic here to let houses look more realistic
|
|
if self._tag == "building":
|
|
|
|
details = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
trees = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
roof_details = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
|
|
if mstr_shadow_enabled == True:
|
|
fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_building-" + self._value + "_layer_shadow.png"
|
|
if os.path.isfile(fn):
|
|
shadow = Image.open(fn)
|
|
|
|
vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]
|
|
if self._value in vls:
|
|
# Generate a new image
|
|
details_pix = details.load()
|
|
layer_pix = layer_comp.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
p = layer_pix[x,y]
|
|
if p[3] > 0:
|
|
shf_x = x+randrange(1, 16)
|
|
shf_y = y+randrange(1, 16)
|
|
shf_x2 = x-randrange(1, 16)
|
|
shf_y2 = y-randrange(1, 16)
|
|
if shf_x < self._imgsize and shf_y < self._imgsize and shf_x2 < self._imgsize and shf_y2 < self._imgsize:
|
|
st = random.uniform(0.65, 0.85)
|
|
ca = 255 * st
|
|
aa = int(ca)
|
|
d = randrange(1,26)
|
|
d2 = randrange(1,26)
|
|
details_pix[shf_x, shf_y] = (187-d, 179-d, 176-d, aa)
|
|
details_pix[shf_x2, shf_y2] = (187-d2, 179-d2, 176-d2, aa)
|
|
|
|
# Image for roof details
|
|
roof_det_pix = roof_details.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
mp = mask_pix[x,y]
|
|
if mp[3] == 255:
|
|
# Determine if we render some pixel
|
|
rnd = randrange(1, 3)
|
|
if rnd == 2:
|
|
# Find a range for the base color of the pixel
|
|
d = randrange(21)
|
|
# Find a random alpha value
|
|
a = randrange(1, 151)
|
|
nc = (mstr_building_detail_colors[0][0]-d, mstr_building_detail_colors[0][1]-d, mstr_building_detail_colors[0][2]-d, a)
|
|
roof_det_pix[x,y] = nc
|
|
|
|
|
|
# Let's see how it works with this method
|
|
#details.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_details.png")
|
|
#layer_comp.alpha_composite(details)
|
|
|
|
# Add some random trees
|
|
div = int(self._imgsize/200)
|
|
for y in range(0, self._imgsize, div):
|
|
for x in range(0, self._imgsize, div):
|
|
if x > 0 and x < self._imgsize and y > 0 and y < self._imgsize:
|
|
p = mask_pix[x, y]
|
|
if p[3] != 0:
|
|
# We found something...
|
|
# Determine if we put something somewhere
|
|
placement = randrange(0, 5)
|
|
if placement == 1:
|
|
# Do some random shift away from this location
|
|
shf_x = randrange(x-11, x+11)
|
|
shf_y = randrange(y-11, y+11)
|
|
if shf_x < self._imgsize and shf_y < self._imgsize:
|
|
# Pick a number of trees to place
|
|
numtrees = randrange(1, 16)
|
|
for i in range(1, numtrees+1):
|
|
# Pick some file
|
|
pick = str(randrange(1, 16))
|
|
tree = Image.open(mstr_datafolder + "textures/building/area/p" + pick + ".png")
|
|
# Do a correction for the location if needed
|
|
if shf_x < 1: shf_x = 1
|
|
if shf_y < 1: shf_y = 1
|
|
if shf_x > self._imgsize - tree.width: shf_x = self._imgsize - tree.width - 1
|
|
if shf_y > self._imgsize - tree.height: shf_y = self._imgsize - tree.height - 1
|
|
trees.alpha_composite(tree, (shf_x, shf_y))
|
|
|
|
|
|
if mstr_shadow_enabled == True:
|
|
tree_pix = trees.load()
|
|
shadow_pix = tree_shadow.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
tp = tree_pix[x,y]
|
|
if tp[3] > 0:
|
|
rndshd = randrange(5, 210)
|
|
sc = (0,0,0,rndshd)
|
|
if x+8 < self._imgsize and y+5 < self._imgsize:
|
|
shadow_pix[x+8,y+5] = sc
|
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
|
tree_shadow.alpha_composite(trees)
|
|
|
|
# Let's try this one on for size
|
|
bld_comp = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
details = details.filter(ImageFilter.GaussianBlur(radius=1))
|
|
bld_comp.alpha_composite(details)
|
|
bld_comp.alpha_composite(tree_shadow)
|
|
bld_comp.alpha_composite(trees)
|
|
shd_p = shadow.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
c = shd_p[x,y]
|
|
if c[3] > 0:
|
|
s = (0,0,0,120-(randrange(0,21)))
|
|
shd_p[x,y] = s
|
|
shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1))
|
|
bld_comp.alpha_composite(shadow)
|
|
layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1.1))
|
|
bld_comp.alpha_composite(layer_comp)
|
|
layer_comp = bld_comp
|
|
layer_comp.alpha_composite(roof_details)
|
|
|
|
mstr_msg("layergen", "Layer image generated")
|
|
|
|
# Building shadow
|
|
if mstr_shadow_enabled == True:
|
|
|
|
# Some funnies with shadows
|
|
if self._tag == "building" and (self._value == "detached" or self._value == "semidetached_house" or self._value == "apartments" or self._value == "civic" or self._value == "house" or self._value == "terrace"):
|
|
mask_pix = mask.load()
|
|
roofshadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
roofpix = roofshadow.load()
|
|
# Generate a pseudo shifted roof shadow
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
mp = mask_pix[x,y]
|
|
if mp[3] == 255:
|
|
nx = x+8
|
|
ny = y+4
|
|
if nx < self._imgsize and ny < self._imgsize:
|
|
roofpix[nx,ny] = (0,0,0,255)
|
|
|
|
# Now apply the shift where necessary
|
|
roofpix = roofshadow.load()
|
|
mask_pix = mask.load()
|
|
layer_comp_pix = layer_comp.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
rp = roofpix[x,y]
|
|
mp = mask_pix[x,y]
|
|
if rp[3] == 255 and mp[3] == 255:
|
|
c = layer_comp_pix[x,y]
|
|
dim = randrange(30,61)
|
|
nr = c[0] - dim
|
|
ng = c[1] - dim
|
|
nb = c[2] - dim
|
|
if nr < 0: nr = 0
|
|
if ng < 0: ng = 0
|
|
if nb < 0: nb = 0
|
|
layer_comp_pix[x,y] = (nr, ng, nb, c[3])
|
|
#layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))
|
|
|
|
|
|
# Let's add some details to the roofs
|
|
if self._tag == "building":
|
|
vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]
|
|
if self._value in vls:
|
|
roof_additional_detail = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
rad_pix = roof_additional_detail.load()
|
|
for r in range(30001):
|
|
lx = randrange(self._imgsize)
|
|
ly = randrange(self._imgsize)
|
|
mp = mask_pix[lx,ly]
|
|
if mp[3] == 255:
|
|
# Brighter or darker pixel
|
|
bod = randrange(1,3)
|
|
c = 0
|
|
if bod == 2:
|
|
c = 40
|
|
else:
|
|
c = 200
|
|
dt = (c, c, c, 130)
|
|
rad_pix[lx,ly] = dt
|
|
if lx+1 < self._imgsize:
|
|
rad_pix[lx+1, ly] = dt
|
|
if lx+1 < self._imgsize and ly+1 < self._imgsize:
|
|
rad_pix[lx+1, ly+1] = dt
|
|
if ly+1 < self._imgsize:
|
|
rad_pix[lx, ly+1] = dt
|
|
layer_comp.alpha_composite(roof_additional_detail)
|
|
|
|
# Let's put some other details on commercial buildings
|
|
if self._tag == "building":
|
|
vls = [ "office", "retail", "industrial" ]
|
|
if self._value in vls:
|
|
|
|
# Find a suitable location to render something
|
|
for r in range(15001):
|
|
lx = randrange(self._imgsize)
|
|
ly = randrange(self._imgsize)
|
|
mp = mask_pix[lx,ly]
|
|
|
|
# Think of some random shape
|
|
if mp[3] == 255:
|
|
rw = randrange(3,8)
|
|
rh = randrange(3,8)
|
|
sh = Image.new("RGBA", (rw, rh), (30,30,30,130))
|
|
shp = sh.load()
|
|
for sy in range(rh):
|
|
for sx in range(rw):
|
|
if sx > 0 and sx < rw and sy > 0 and sy < rh: shp[sx, sy] = (180,180,180,160)
|
|
rt = randrange(1, 3)
|
|
if rt == 2:
|
|
sh = sh.rotate(45, expand=True)
|
|
|
|
layer_comp.alpha_composite(sh, (lx, ly))
|
|
|
|
|
|
# Highways and runways of any kind get some special treatment
|
|
if (self._tag == "highway" and self._value == "motorway") or (self._tag == "highway" and self._value == "primary") or (self._tag == "highway" and self._value == "secondary") or (self._tag == "highway" and self._value == "tertiary") or (self._tag == "aeroway" and self._value == "runway"):
|
|
# We will now add some white lines for coolness
|
|
osm_edge = mask.filter(ImageFilter.FIND_EDGES)
|
|
mask_pix = osm_edge.load()
|
|
layer_comp_pix = layer_comp.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mask_pix[x, y][3] > 0:
|
|
# Find a suitable color
|
|
w = randrange(125, 156)
|
|
a=mask_pix[x,y]
|
|
layer_comp_pix[x, y] = ( w,w,w,a[3] )
|
|
|
|
if self._tag == "highway" and self._value == "residential":
|
|
osm_edge = mask.filter(ImageFilter.FIND_EDGES)
|
|
mask_pix = osm_edge.load()
|
|
layer_comp_pix = layer_comp.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mask_pix[x, y][3] > 0:
|
|
# Find a suitable color
|
|
w = randrange(150,181)
|
|
a=mask_pix[x,y]
|
|
layer_comp_pix[x, y] = ( w,w,w,a[3] )
|
|
mstr_msg("layergen", "Street lines added")
|
|
|
|
|
|
# Same as above, except that streams are lines and are not drawn as polygons.
|
|
# Therefore this part needs to be in here as well.
|
|
if self._tag == "waterway" and self._value == "stream":
|
|
mstr_msg("layergen", "Generating inland water mask")
|
|
inl_mask = Image.new("RGBA", (self._imgsize, self._imgsize), (0,0,0,0))
|
|
lyr_pix = layer_comp.load()
|
|
inl_pix = inl_mask.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
l = lyr_pix[x,y]
|
|
if l[3] > 65:
|
|
b = 255 - l[3]
|
|
inl_pix[x,y] = (255,0,255,255)
|
|
#inl_mask.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_mask.png")
|
|
mstr_msg("layergen", "Inland water mask generated and saved")
|
|
|
|
|
|
# Blur roads a bit
|
|
if self._tag == "highway":
|
|
layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))
|
|
|
|
|
|
# Store layer
|
|
#layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
|
mstr_msg("layergen", "Layer image finalized and saved.")
|
|
|
|
|
|
# Depending on if scenery for XP should be made, AND if normal maps should be made, we would
|
|
# need to make them at this exact point
|
|
"""
|
|
if mstr_xp_genscenery == True:
|
|
if mstr_xp_scn_normalmaps == True and self._is_completion == False:
|
|
nm = False
|
|
for n in mstr_xp_normal_maps:
|
|
if n[0] == self._tag and (n[1] == self._value or n[1] == "*"):
|
|
nm = True
|
|
break
|
|
if nm == True:
|
|
nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)
|
|
nrm.build_normalmap(layer_comp)
|
|
"""
|
|
|
|
|
|
# Return image
|
|
return layer_comp
|
|
|
|
|
|
# Should we find more than one source, the first one found will take precedence.
|
|
# For the others, we will need to generate fading images, so that the final layer
|
|
# image works with other tiles
|
|
def generate_adjacent_fades(self, mask):
|
|
adj_sources = self.find_all_adjacent_sources()
|
|
precedence = -1
|
|
|
|
# Be prepared for every border
|
|
brd_t = Image.open(mstr_datafolder + "textures/multi_source/brd_t.png")
|
|
brd_r = Image.open(mstr_datafolder + "textures/multi_source/brd_r.png")
|
|
brd_b = Image.open(mstr_datafolder + "textures/multi_source/brd_b.png")
|
|
brd_l = Image.open(mstr_datafolder + "textures/multi_source/brd_l.png")
|
|
|
|
brd_t_pix = brd_t.load()
|
|
brd_r_pix = brd_r.load()
|
|
brd_b_pix = brd_b.load()
|
|
brd_l_pix = brd_l.load()
|
|
|
|
for s in range(0, 4):
|
|
if adj_sources[s] != -1:
|
|
precedence = adj_sources[s]
|
|
break
|
|
|
|
# Generate required images
|
|
# Basically a shortened version of the main layergen call
|
|
adj_image = Image.new("RGBA", (self._imgsize, self._imgsize))
|
|
for s in range(0, 4):
|
|
if adj_sources[s] != precedence and adj_sources[s] != -1:
|
|
src = adj_sources[s]
|
|
|
|
adj_pix = adj_image.load()
|
|
|
|
# Root folder
|
|
root_folder = mstr_datafolder + "textures/" + self._tag + "/" + self._value
|
|
|
|
# Load in the sources to work with
|
|
ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")
|
|
brd_src = Image.open(root_folder + "/brd/b" + str(src) + ".png")
|
|
ptc_src = []
|
|
for p in ptc:
|
|
ptc_src.append(Image.open(p))
|
|
|
|
#mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )
|
|
#lyr_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
|
|
|
for i in mstr_mask_blur:
|
|
if i[0] == self._tag and i[1] == self._value:
|
|
if self._tag != "place" and (self._value != "sea" or self._value != "ocean"):
|
|
mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))
|
|
break
|
|
mask_pix = mask.load()
|
|
|
|
# Begin producing a largely random image
|
|
samples = 250 # <- We need this in a moment
|
|
for i in range(samples):
|
|
imgid = 0
|
|
if len(ptc_src) == 1: imgid = 0
|
|
if len(ptc_src) >= 2:
|
|
imgid = randrange(1, len(ptc_src)+1) - 1
|
|
l = 0 - int(ptc_src[imgid].width / 2)
|
|
r = adj_image.width - int(ptc_src[imgid].width / 2)
|
|
t = 0 - int(ptc_src[imgid].height / 2)
|
|
b = adj_image.height - int(ptc_src[imgid].height / 2)
|
|
adj_image.alpha_composite( ptc_src[imgid], ( randrange(l, r), randrange(t, b) ) )
|
|
|
|
adj_image.alpha_composite( brd_src )
|
|
|
|
#lyr_pix = lyr_mask.load()
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
if mask_pix[x, y][3] > 0:
|
|
rgb=adj_pix[x,y]
|
|
a=mask_pix[x,y]
|
|
adj_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])
|
|
|
|
# Up until here we mimiced the exact same behavior as layergen. However, now
|
|
# we need to adjust the alpha to make this layer fade.
|
|
# Then, we save the image
|
|
if s == 0:
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
fade_a = brd_t_pix[0, y]
|
|
if mask_pix[x, y][3] > 0:
|
|
c = adj_pix[x,y]
|
|
adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])
|
|
else:
|
|
adj_pix[x,y] = (0,0,0,0)
|
|
#adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_top.png")
|
|
|
|
if s == 1:
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
fade_a = brd_r_pix[x, 0]
|
|
if mask_pix[x, y][3] > 0:
|
|
c = adj_pix[x,y]
|
|
adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])
|
|
else:
|
|
adj_pix[x,y] = (0,0,0,0)
|
|
#adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_right.png")
|
|
|
|
if s == 2:
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
fade_a = brd_b_pix[0, y]
|
|
if mask_pix[x, y][3] > 0:
|
|
c = adj_pix[x,y]
|
|
adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])
|
|
else:
|
|
adj_pix[x,y] = (0,0,0,0)
|
|
#adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_bottom.png")
|
|
|
|
if s == 3:
|
|
for y in range(self._imgsize):
|
|
for x in range(self._imgsize):
|
|
fade_a = brd_l_pix[x, 0]
|
|
if mask_pix[x, y][3] > 0:
|
|
c = adj_pix[x,y]
|
|
adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])
|
|
else:
|
|
adj_pix[x,y] = (0,0,0,0)
|
|
#adj_image.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_fade_left.png")
|
|
|
|
# Return the image
|
|
return adj_image
|
|
|
|
|
|
|
|
def find_all_adjacent_sources(self):
|
|
# Sources for this tag and value - top, right, bottom, left
|
|
sources = [-1,-1,-1,-1]
|
|
|
|
# Perform query for each neighboring tile
|
|
src_top = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number+1, self._lng_number, self._tag, self._value)
|
|
src_rgt = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number, self._lng_number+1, self._tag, self._value)
|
|
src_btm = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number-1, self._lng_number, self._tag, self._value)
|
|
src_lft = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number, self._lng_number-1, self._tag, self._value)
|
|
|
|
if len(src_top) == 2:
|
|
if "b" in src_top[1]: sources[0] = src_top[0]
|
|
if len(src_rgt) == 2:
|
|
if "l" in src_rgt[1]: sources[1] = src_rgt[0]
|
|
if len(src_btm) == 2:
|
|
if "t" in src_btm[1]: sources[2] = src_btm[0]
|
|
if len(src_lft) == 2:
|
|
if "r" in src_lft[1]: sources[3] = src_lft[0]
|
|
|
|
# Report our findings
|
|
return sources
|
|
|
|
# Find the next "by-ten" numbers for the current latitude and longitude
|
|
def find_earthnavdata_number(self):
|
|
earthnavdata = []
|
|
lat = abs(int(self._latitude / 10) * 10)
|
|
lng = abs(int(self._longitude / 10) * 10)
|
|
earthnavdata.append(lat)
|
|
earthnavdata.append(lng)
|
|
return earthnavdata
|
|
|
|
# Construct an X-Plane compatible folder name for latitude and longitude
|
|
def xplane_latlng_folder(self, numbers):
|
|
fstr = ""
|
|
if numbers[0] >= 0: fstr = "+"
|
|
if numbers[0] < 0: fstr = "-"
|
|
if abs(numbers[0]) < 10: fstr = fstr + "0" + str(numbers[0])
|
|
if abs(numbers[0]) >= 10 and numbers[0] <= 90: fstr = fstr + str(numbers[0])
|
|
|
|
if numbers[1] >= 0: fstr = fstr + "+"
|
|
if numbers[1] < 0: fstr = fstr + "-"
|
|
if abs(numbers[1]) < 10: fstr = fstr + "00" + str(numbers[1])
|
|
if abs(numbers[1]) >= 10 and numbers[0] <= 99: fstr = fstr + "0" + str(numbers[1])
|
|
if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])
|
|
|
|
return fstr
|