\r
import glob\r
import os\r
+import time\r
from random import randrange\r
import random\r
-from PIL import Image, ImageFilter, ImageDraw\r
+\r
+import PIL.ImageOps\r
+from PIL import Image, ImageFilter, ImageDraw, ImageOps, ImageFile\r
from defines import *\r
from log import *\r
from tileinfo import *\r
from osmxml import *\r
from functions import *\r
+from resourcegen import *\r
+\r
+ImageFile.LOAD_TRUNCATED_IMAGES = True\r
\r
class mstr_layergen:\r
\r
# Find the source to use pre-determined in phase one\r
def findLayerSource(self):\r
# The source number\r
- src = -1\r
+ src = []\r
\r
# The already existing source data\r
srcfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(self._lng_number)\r
with open(srcfile) as file:\r
for line in file:\r
linedata = line.split(" ")\r
- if linedata[2] == self._tag and linedata[3] == self._value:\r
- src = int(linedata[4])\r
+ if linedata[0] == self._tag and linedata[1] == self._value:\r
+ src = linedata[2].split(",")\r
break\r
\r
- # Should we encounter a -1 at this point, we can choose something\r
+ # Should we encounter a 0 length at this point, we can choose something\r
# It means it touches no border as it was not found in the file\r
- if src == -1:\r
- root_folder = mstr_datafolder + "textures/"\r
- for s in mstr_ortho_layers:\r
- if s[0] == self._tag and s[1] == self._value:\r
- fld_main = len(s)-2\r
- fld_sub = len(s)-1\r
- root_folder = root_folder + s[fld_main] + "/" + s[fld_sub]\r
- \r
- brd = glob.glob(root_folder + "/brd/b*.png")\r
- src = randrange(1, len(brd)+1)\r
+ if len(src) == 0:\r
+ while len(src) < 6:\r
+ pick = randrange(1, 16)\r
+ if pick not in src: src.append(pick)\r
\r
return src\r
\r
\r
+ # Find layer contrast to apply, if any\r
+ def findLayerContrast(self):\r
+\r
+ contrast = 0\r
+\r
+ # The already existing source data\r
+ srcfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(\r
+ self._lng_number)\r
+\r
+ # Let's open the file and find our entry\r
+ with open(srcfile) as file:\r
+ for line in file:\r
+ linedata = line.split(" ")\r
+ if linedata[0] == self._tag and linedata[1] == self._value:\r
+ src = linedata[2].split(",")\r
+ contrast = src[4]\r
+\r
+ return contrast\r
+\r
+\r
+ # Generates some random tree.\r
+ # We will now move away from using pre-made trees...\r
+ # they didn't look so great\r
+ def generate_tree(self):\r
+ sx = randrange(18, 31)\r
+ sy = randrange(18, 31)\r
+\r
+ treepoly = Image.new("RGBA", (sx, sy))\r
+ draw = ImageDraw.Draw(treepoly)\r
+\r
+ draw.ellipse((4, 4, sx - 4, sy - 4), fill="black")\r
+\r
+ tree = Image.new("RGBA", (sx, sy))\r
+ treepx = tree.load()\r
+ maskpx = treepoly.load()\r
+\r
+ # How many tree points do we want?\r
+ treepts = 75\r
+ # How many of those have been drawn?\r
+ ptsdrawn = 0\r
+\r
+ bc = [\r
+ (36, 50, 52),\r
+ (30, 41, 39),\r
+ (32, 45, 37),\r
+ (32, 39, 49),\r
+ (33, 34, 40),\r
+ (44, 50, 53),\r
+ (40, 46, 48),\r
+ (14, 31, 38),\r
+ (17, 41, 33),\r
+ (39, 56, 35),\r
+ (51, 51, 42),\r
+ (12, 27, 31),\r
+ (45, 59, 48),\r
+ (37, 54, 29),\r
+ (59, 50, 34),\r
+ (59, 59, 35),\r
+ (59, 51, 35),\r
+ (70, 72, 45),\r
+ (48, 59, 44),\r
+ (29, 47, 23),\r
+ (47, 61, 43),\r
+ (29, 68, 15),\r
+ (53, 77, 63),\r
+ (20, 68, 40)\r
+ ]\r
+\r
+ bcp = randrange(0, len(bc))\r
+\r
+ treedraw = ImageDraw.Draw(tree)\r
+ while ptsdrawn < treepts + 1:\r
+ rx = randrange(0, sx)\r
+ ry = randrange(0, sy)\r
+ mp = maskpx[rx, ry]\r
+ if mp[3] > 0:\r
+ d = randrange(0, 51)\r
+ r = bc[bcp][0]\r
+ g = bc[bcp][1] + d\r
+ b = bc[bcp][2] + (d // 2)\r
+ a = randrange(170, 256)\r
+ c = (r, g, b, a)\r
+ ex = randrange(2, 5)\r
+ ey = randrange(2, 5)\r
+ treedraw.ellipse((rx - (ex // 2), ry - (ey // 2), rx + (ey // 2), ry + (ey // 2)), fill=c)\r
+ ptsdrawn = ptsdrawn + 1\r
+\r
+ for y in range(0, tree.height):\r
+ for x in range(0, tree.width):\r
+ tp = treepx[x, y]\r
+ diff = randrange(0, 31)\r
+ nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])\r
+ treepx[x, y] = nc\r
+\r
+ tree = tree.filter(ImageFilter.GaussianBlur(radius=0.5))\r
+\r
+ for y in range(0, tree.height):\r
+ for x in range(0, tree.width):\r
+ tp = treepx[x, y]\r
+ diff = randrange(0, 51)\r
+ nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])\r
+ treepx[x, y] = nc\r
+\r
+ return tree\r
+\r
\r
# This generates the layer from the defined mask\r
def genlayer(self, mask, xml):\r
# If we find an airport, make a note ...\r
if icao != None:\r
if len(icao) >= 1 and self._is_completion == False:\r
- #for i in icao:\r
- # ... but only, if this airport is not already noted\r
- #iccheck = self._tiledb.perform_query("SELECT * FROM airports WHERE icao='" + i +"';")\r
- #if len(iccheck) == 0:\r
- #self._tiledb.insert_icao(i, self._lat_number, self._lng_number, self._latitude, self._longitude)\r
- # mstr_msg("layergen", "Airport/s noted in data file")\r
rw_surface = xml.find_runway_surface()\r
\r
# The image for the layer itself\r
# We need to differentiate that.\r
\r
if (self._isline == False and self._tag != "building") or (self._is_completion == True):\r
- # Determine where we get the our source material from\r
+ # Determine where we get the source material from\r
root_folder = mstr_datafolder + "textures/"\r
for s in mstr_ortho_layers:\r
if s[0] == self._tag and s[1] == self._value:\r
\r
# Determine which sources to use.\r
src = self.findLayerSource()\r
- \r
- ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")\r
- \r
- # Load in the sources to work with\r
- brd_src = Image.open(root_folder + "/brd/b" + str(src) + ".png")\r
+\r
+ # Patch and border sources. There can only be one for each.\r
+ brd_src = None\r
ptc_src = []\r
- for p in ptc:\r
- ptc_src.append(Image.open(p))\r
+ \r
+ # Find out if the generated image already exists.\r
+ # If not, both border and patch need to be generated first.\r
+ gensrc_ptc = mstr_datafolder + "_cache/_pool/ptc_" + self._tag + "_" + self._value + "_"\r
+ for s in range(len(src)):\r
+ gensrc_ptc = gensrc_ptc + str(src[s])\r
+ if s < len(src) - 1:\r
+ gensrc_ptc = gensrc_ptc + "_"\r
+ gensrc_ptc = gensrc_ptc + ".png"\r
+\r
+ # Find this layer's predetermined contrast\r
+ lyr_contrast = self.findLayerContrast()\r
+\r
+ # Should this not exist yet, we need to create it\r
+ #if os.path.isfile(gensrc_ptc) == False:\r
+ rg = mstr_resourcegen(self._tag, self._value, src)\r
+ rg.setLayerContrast(int(lyr_contrast))\r
+ lyr_res = rg.gensource()\r
+\r
+ # Open the images\r
+ ptc_src.append(lyr_res[0]) # Used to be an array, so let's keep it\r
+ brd_src = lyr_res[1]\r
+\r
mstr_msg("layergen", "Layer sources selected")\r
\r
# Generate an edge mask from the original\r
layer.alpha_composite( brd_src )\r
\r
# Here we need to do some magic to make some features look more natural\r
- 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"):\r
- if self._is_completion == False:\r
- amt = randrange(2, 9)\r
- for i in range(1, amt+1):\r
- ptc = randrange(1, 14)\r
- img = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(ptc)+".png")\r
- img = img.rotate(randrange(0, 360), expand=True)\r
- a = img.getchannel("A")\r
- bbox = a.getbbox()\r
- img = img.crop(bbox)\r
- lx = randrange( self._imgsize - img.width ) \r
- ly = randrange( self._imgsize - img.height )\r
- layer.alpha_composite( img, (lx, ly) )\r
- if self._is_completion == True:\r
- mp = mask.load()\r
- edn = self.xplane_latlng_folder(self.find_earthnavdata_number())\r
- idx = 0\r
- for r in mstr_completion_colors:\r
- if r[0] == edn:\r
- break\r
- else:\r
- idx = idx+1\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- if mp[x,y][3] > 0:\r
- # Pick a color\r
- a = mp[x,y]\r
- cidx = randrange(len(mstr_completion_colors[idx][1]))\r
- clr = mstr_completion_colors[idx][1][cidx]\r
- layer_pix[x,y] = (clr[0], clr[1], clr[2], a[3])\r
- amt = randrange(1,51)\r
- for i in range(1, amt+1):\r
- ptc = randrange(1, 14)\r
- img = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(ptc)+".png")\r
- img = img.rotate(randrange(0, 360), expand=True)\r
- a = img.getchannel("A")\r
- bbox = a.getbbox()\r
- img = img.crop(bbox)\r
- imgp = img.load()\r
- for y in range(img.height):\r
- for x in range(img.width):\r
- c = imgp[x,y]\r
- nc = (c[0], c[1], c[2], int(imgp[x,y][3]*0.4))\r
- imgp[x,y] = nc\r
- lx = randrange( self._imgsize - img.width ) \r
- ly = randrange( self._imgsize - img.height )\r
- layer.alpha_composite( img, (lx, ly))\r
- layer = layer.filter(ImageFilter.GaussianBlur(radius=1))\r
- \r
-\r
- # Add trees only in some features\r
- if (self._tag == "landuse" and self._value == "cemetery") or (self._tag == "landuse" and self._value == "residential") or (self._tag == "leisure" and self._value == "park"):\r
- trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- amt = 3500\r
- for i in range(1, amt+1):\r
- p = randrange(1, 16)\r
- tree = Image.open(mstr_datafolder + "textures/building/area/p" + str(p) + ".png")\r
- lx = randrange( self._imgsize - tree.width ) \r
- ly = randrange( self._imgsize - tree.height )\r
- trees.alpha_composite(tree, (lx, ly))\r
- \r
- tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- tree_pix = trees.load()\r
- shadow_pix = tree_shadow.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- tp = tree_pix[x,y]\r
- if tp[3] > 0:\r
- rndshd = randrange(5, 210)\r
- sc = (0,0,0,rndshd)\r
- if x+8 < self._imgsize and y+5 < self._imgsize:\r
- shadow_pix[x+8,y+5] = sc\r
- tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))\r
- tree_shadow.alpha_composite(trees)\r
- layer.alpha_composite(tree_shadow)\r
-\r
- mstr_msg("layergen", "Layer image completed")\r
+ if (self._tag == "landuse" and self._value == "meadow") or (\r
+ self._tag == "natural" and self._value == "grassland") or (\r
+ self._tag == "natural" and self._value == "heath") or (\r
+ self._tag == "landuse" and self._value == "cemetery") or (\r
+ self._tag == "landuse" and self._value == "residential"):\r
+ amt = randrange(2, 9)\r
+ masks = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")\r
+ for i in range(1, amt + 1):\r
+ pick = randrange(0, len(masks))\r
+ patchmask = Image.open(masks[pick])\r
+ patchpix = patchmask.load()\r
+ # Pick from possible tags and values for the patches\r
+ patchtags = [\r
+ ["landuse", "meadow"],\r
+ ["landuse", "grass"],\r
+ ["natural", "heath"],\r
+ ["natural", "scrub"]\r
+ ]\r
+\r
+ numbers = list(range(1, 16))\r
+ src = random.sample(numbers, 5)\r
+\r
+ patchpick = randrange(0, len(patchtags))\r
+ ctr = randrange(1, 4)\r
+ rg = mstr_resourcegen(patchtags[patchpick][0], patchtags[patchpick][1], src)\r
+ rg.setLayerContrast(ctr)\r
+ ptch = rg.gensource()\r
+\r
+ rg_img = ptch[0]\r
+ rg_pix = rg_img.load()\r
+\r
+ # The patch to be used in the layer\r
+ layerpatch = Image.new("RGBA", (patchmask.width, patchmask.height))\r
+ lp_pix = layerpatch.load()\r
+ for y in range(0, patchmask.height):\r
+ for x in range(0, patchmask.width):\r
+ ptc_msk = patchpix[x,y]\r
+ if ptc_msk[3] > 0:\r
+ oc = rg_pix[x,y]\r
+ nc = ( oc[0], oc[1], oc[2], ptc_msk[3] )\r
+ lp_pix[x,y] = nc\r
+\r
+ layerpatch = layerpatch.rotate(randrange(0, 360), expand=True)\r
+\r
+ lx = randrange(self._imgsize - layerpatch.width)\r
+ ly = randrange(self._imgsize - layerpatch.height)\r
+ layer.alpha_composite(layerpatch, (lx, ly))\r
\r
\r
# And now for the Big Mac.\r
a=mask_pix[x,y]\r
layer_comp_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])\r
\r
- # For some things, we will need to add a border and then add this to the layer.\r
- layer_border = None\r
- if self._tag == "landuse":\r
- if self._value == "forest" or self._value == "farmland":\r
- osm_edge = osm_edge.filter(ImageFilter.ModeFilter(size=15))\r
- osm_edge = osm_edge.filter(ImageFilter.BoxBlur(radius=2))\r
- layer_border = self.genborder(osm_edge, "landuse", "meadow")\r
- layer_comp.alpha_composite(layer_border)\r
-\r
-\r
- # Here we want to make sure that the generated image fits well with others, so\r
- # let's do that.\r
- mstr_msg("layergen", "Generating adjacent fades")\r
- adjfade = self.generate_adjacent_fades(mask)\r
-\r
- layer_comp.alpha_composite(adjfade)\r
- mstr_msg("layergen", "Adjacent fading completed")\r
-\r
\r
# Add a white-ish border around pitches\r
if self._tag == "leisure" and self._value == "pitch":\r
- epx = osm_edge.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- ep = epx[x,y]\r
- if ep[3] > 0:\r
- d = randrange(10,101)\r
- nw = (200-d,200-d,200-d,255)\r
- layer_comp_pix[x,y] = nw\r
-\r
- # I need to put this special sub-call here to solve an otherwise unsolvable\r
- # conflict with layer order\r
- if self._tag == "landuse" and self._value == "forest":\r
- # The residential layer MUST exist before we reach the forest part.\r
- fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_landuse-residential_layer.png"\r
- if os.path.isfile(fn):\r
- rsd = Image.open(fn)\r
- rsd_pix = rsd.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- rpix = rsd_pix[x,y]\r
- lpix = layer_comp_pix[x,y]\r
- if rpix[3] > 0 and lpix[3] > 0:\r
- layer_comp_pix[x,y] = (lpix[0], lpix[1], lpix[2], 255-rpix[3])\r
+ pitch_edge = osm_edge\r
+ pitch_edge = pitch_edge.filter(ImageFilter.GaussianBlur(radius=0.5))\r
+ pitch_mask = pitch_edge.load()\r
\r
- # Store layer\r
- #if self._is_completion == False:\r
- # 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" )\r
- #if self._is_completion == True:\r
- # layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_tile-completion_layer.png" )\r
- #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" )\r
- mstr_msg("layergen", "Layer image finalized and saved.")\r
+ # ImageOps.invert does not like RGBA images for inversion. So I need to do it.\r
+ for y in range(0, self._imgsize):\r
+ for x in range(0, self._imgsize):\r
+ pm = pitch_mask[x,y]\r
+ if pm[3] > 0:\r
+ d = randrange(0, 21)\r
+ layer_comp_pix[x,y] = ( 110-pm[0]-d, 110-pm[1]-d, 110-pm[2]-d, pm[3]-(d*2) )\r
\r
\r
- # Depending on if scenery for XP should be made, AND if normal maps should be made, we would\r
- # need to make them at this exact point\r
- """\r
- if mstr_xp_genscenery == True:\r
- if mstr_xp_scn_normalmaps == True and self._is_completion == False:\r
- nm = False\r
- for n in mstr_xp_normal_maps:\r
- if n[0] == self._tag and (n[1] == self._value or n[1] == "*"):\r
- nm = True\r
- break\r
- if nm == True:\r
- nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)\r
- nrm.build_normalmap(layer_comp)\r
- """\r
+ # Layer complete\r
+ mstr_msg("layergen", "Layer image completed.")\r
\r
\r
# Let's try our hand at pseudo shadows\r
layer_comp = shadow\r
mstr_msg("layergen", "Shadow layer completed")\r
\r
-\r
- # Create a water mask we need to remove from the DDS later\r
- """\r
- 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"):\r
- mstr_msg("layergen", "Generating inland water mask")\r
- water_file = mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._lat_number) + "_" + str(self._lng_number) + "_water.png"\r
- inl_mask = None\r
- if os.path.isfile(water_file):\r
- inl_mask = Image.open(water_file)\r
- else:\r
- inl_mask = Image.new("L", (self._imgsize, self._imgsize), (255))\r
- lyr_pix = layer_comp.load()\r
- inl_pix = inl_mask.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- l = lyr_pix[x,y]\r
- if l[3] > 50:\r
- clr = 255-l[3]\r
- c = (clr)\r
- inl_pix[x,y] = c\r
- inl_mask.save(water_file)\r
- #if l[3] > 65:\r
- # b = 255 - l[3]\r
- # inl_pix[x,y] = (255,0,255,255)\r
- #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")\r
- #layer_comp = inl_mask\r
- mstr_msg("layergen", "Inland water mask generated and saved")\r
- """\r
-\r
# Return the completed image\r
return layer_comp\r
\r
\r
# If we encounter one of these road-specific tags, we need to proceed differently.\r
\r
- if self._isline == True or self._tag == "building":\r
+ if self._isline == True or self._tag != "building":\r
\r
# We will need the mask in question\r
#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" )\r
d = randrange(41, 61)\r
layer_comp_pix[x, y] = ( d,d,d,a[3] )\r
if self._tag == "highway" and self._value != "motorway":\r
- dr = randrange(110,121)\r
- dg = randrange(110,121)\r
- db = randrange(115,130)\r
- layer_comp_pix[x, y] = ( dr,dg,db,a[3] )\r
+ d = randrange(0, 36)\r
+ dr = 90+d\r
+ dg = 90+d\r
+ db = 95+d\r
+ da = a[3]\r
+ layer_comp_pix[x, y] = ( dr,dg,db,da )\r
if self._tag == "highway" and self._value == "motorway":\r
- dr = randrange(77,89)\r
- dg = randrange(88,96)\r
- db = randrange(90,101)\r
+ d = randrange(0, 36)\r
+ dr = 57+d\r
+ dg = 68+d\r
+ db = 70+d\r
layer_comp_pix[x, y] = ( dr,dg,db,a[3] )\r
+ if self._tag == "highway" and (self._value == "footway" or self._value == "track" or self._value == "path"):\r
+ dr = randrange(158, 183)\r
+ dg = randrange(143, 178)\r
+ db = randrange(90, 161)\r
+ da = a[3]-20\r
+ layer_comp_pix[x, y] = (dr, dg, db, da)\r
if self._tag == "waterway" and (self._value == "stream" or self._value == "river"):\r
d = randrange(1, 15)\r
# Rock, grass, water\r
if t < 0: t = 0\r
if e[3] > 0:\r
layer_comp_pix[x, y] = ( mats[pick-1][0], mats[pick-1][1], mats[pick-1][2], 35 )\r
- \r
- # A bit special here\r
- if self._tag == "building":\r
- # Find a color range for the pixel\r
- d = randrange(1,21)\r
- nr = a[0]+40 - d\r
- ng = a[1]+40 - d\r
- nb = a[2]+40 - d\r
- if nr < 0: nr = 0\r
- if ng < 0: ng = 0\r
- if nb < 0: nb = 0\r
- if nr > 255: nr = 255\r
- if ng > 255: ng = 255\r
- if nb > 255: nb = 255\r
- nc = (nr, ng, nb, 255)\r
- layer_comp_pix[x,y] = (nr,ng,nb,255)\r
- \r
- if self._value == "track" or self._value == "path":\r
- d = randrange(1,20)\r
- r = 164 - d\r
- g = 159 - d\r
- b = 138 - d\r
- layer_comp_pix[x, y] = ( r,g,b,a[3] )\r
\r
# A bit different for tree rows\r
if self._tag == "natural" and self._value == "tree_row":\r
a = mask_pix[lx,ly]\r
if a[3] > 0:\r
if lx < self._imgsize and ly < self._imgsize:\r
- p = randrange(1,16)\r
- tree = Image.open(mstr_datafolder + "textures/building/area/p" + str(p) + ".png")\r
+ tree = self.generate_tree()\r
trees.alpha_composite(tree, (lx, ly))\r
if mstr_shadow_enabled == True:\r
tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
tree_shadow.alpha_composite(trees)\r
layer_comp.alpha_composite(tree_shadow)\r
\r
- # We will do some super magic here to let houses look more realistic\r
- if self._tag == "building":\r
- \r
- details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- roof_details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
-\r
- if mstr_shadow_enabled == True:\r
- fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_building-" + self._value + "_layer_shadow.png"\r
- if os.path.isfile(fn):\r
- shadow = Image.open(fn)\r
-\r
- vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]\r
- if self._value in vls:\r
- # Generate a new image\r
- details_pix = details.load()\r
- layer_pix = layer_comp.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- p = layer_pix[x,y]\r
- if p[3] > 0:\r
- shf_x = x+randrange(1, 16)\r
- shf_y = y+randrange(1, 16)\r
- shf_x2 = x-randrange(1, 16)\r
- shf_y2 = y-randrange(1, 16)\r
- if shf_x < self._imgsize and shf_y < self._imgsize and shf_x2 < self._imgsize and shf_y2 < self._imgsize:\r
- st = random.uniform(0.65, 0.85)\r
- ca = 255 * st\r
- aa = int(ca)\r
- d = randrange(1,26)\r
- d2 = randrange(1,26)\r
- details_pix[shf_x, shf_y] = (187-d, 179-d, 176-d, aa)\r
- details_pix[shf_x2, shf_y2] = (187-d2, 179-d2, 176-d2, aa)\r
-\r
- # Image for roof details\r
- roof_det_pix = roof_details.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- mp = mask_pix[x,y]\r
- if mp[3] == 255:\r
- # Determine if we render some pixel\r
- rnd = randrange(1, 3)\r
- if rnd == 2:\r
- # Find a range for the base color of the pixel\r
- d = randrange(21)\r
- # Find a random alpha value\r
- a = randrange(1, 151)\r
- nc = (mstr_building_detail_colors[0][0]-d, mstr_building_detail_colors[0][1]-d, mstr_building_detail_colors[0][2]-d, a)\r
- roof_det_pix[x,y] = nc\r
-\r
-\r
- # Let's see how it works with this method\r
- #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")\r
- #layer_comp.alpha_composite(details)\r
-\r
- # Add some random trees\r
- div = int(self._imgsize/200)\r
- for y in range(0, self._imgsize, div):\r
- for x in range(0, self._imgsize, div):\r
- if x > 0 and x < self._imgsize and y > 0 and y < self._imgsize:\r
- p = mask_pix[x, y]\r
- if p[3] != 0:\r
- # We found something...\r
- # Determine if we put something somewhere\r
- placement = randrange(0, 5)\r
- if placement == 1:\r
- # Do some random shift away from this location\r
- shf_x = randrange(x-11, x+11)\r
- shf_y = randrange(y-11, y+11)\r
- if shf_x < self._imgsize and shf_y < self._imgsize:\r
- # Pick a number of trees to place\r
- numtrees = randrange(1, 16)\r
- for i in range(1, numtrees+1):\r
- # Pick some file\r
- pick = str(randrange(1, 16))\r
- tree = Image.open(mstr_datafolder + "textures/building/area/p" + pick + ".png")\r
- # Do a correction for the location if needed\r
- if shf_x < 1: shf_x = 1\r
- if shf_y < 1: shf_y = 1\r
- if shf_x > self._imgsize - tree.width: shf_x = self._imgsize - tree.width - 1\r
- if shf_y > self._imgsize - tree.height: shf_y = self._imgsize - tree.height - 1\r
- trees.alpha_composite(tree, (shf_x, shf_y))\r
- \r
- \r
- if mstr_shadow_enabled == True:\r
- tree_pix = trees.load()\r
- shadow_pix = tree_shadow.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- tp = tree_pix[x,y]\r
- if tp[3] > 0:\r
- rndshd = randrange(5, 210)\r
- sc = (0,0,0,rndshd)\r
- if x+8 < self._imgsize and y+5 < self._imgsize:\r
- shadow_pix[x+8,y+5] = sc\r
- tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))\r
- tree_shadow.alpha_composite(trees)\r
-\r
- # Let's try this one on for size\r
- bld_comp = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- details = details.filter(ImageFilter.GaussianBlur(radius=1))\r
- bld_comp.alpha_composite(details)\r
- bld_comp.alpha_composite(tree_shadow)\r
- bld_comp.alpha_composite(trees)\r
- shd_p = shadow.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- c = shd_p[x,y]\r
- if c[3] > 0:\r
- s = (0,0,0,120-(randrange(0,21)))\r
- shd_p[x,y] = s\r
- shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1))\r
- bld_comp.alpha_composite(shadow)\r
- layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1.1))\r
- bld_comp.alpha_composite(layer_comp)\r
- layer_comp = bld_comp\r
- layer_comp.alpha_composite(roof_details)\r
-\r
mstr_msg("layergen", "Layer image generated")\r
\r
- # Building shadow\r
- if mstr_shadow_enabled == True:\r
- \r
- # Some funnies with shadows\r
- 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"):\r
- mask_pix = mask.load()\r
- roofshadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- roofpix = roofshadow.load()\r
- # Generate a pseudo shifted roof shadow\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- mp = mask_pix[x,y]\r
- if mp[3] == 255:\r
- nx = x+8\r
- ny = y+4\r
- if nx < self._imgsize and ny < self._imgsize:\r
- roofpix[nx,ny] = (0,0,0,255)\r
-\r
- # Now apply the shift where necessary\r
- roofpix = roofshadow.load()\r
- mask_pix = mask.load()\r
- layer_comp_pix = layer_comp.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- rp = roofpix[x,y]\r
- mp = mask_pix[x,y]\r
- if rp[3] == 255 and mp[3] == 255:\r
- c = layer_comp_pix[x,y]\r
- dim = randrange(30,61)\r
- nr = c[0] - dim\r
- ng = c[1] - dim\r
- nb = c[2] - dim\r
- if nr < 0: nr = 0\r
- if ng < 0: ng = 0\r
- if nb < 0: nb = 0\r
- layer_comp_pix[x,y] = (nr, ng, nb, c[3])\r
- #layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))\r
-\r
-\r
- # Let's add some details to the roofs\r
- if self._tag == "building":\r
- vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]\r
- if self._value in vls:\r
- roof_additional_detail = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- rad_pix = roof_additional_detail.load()\r
- for r in range(30001):\r
- lx = randrange(self._imgsize)\r
- ly = randrange(self._imgsize)\r
- mp = mask_pix[lx,ly]\r
- if mp[3] == 255:\r
- # Brighter or darker pixel\r
- bod = randrange(1,3)\r
- c = 0\r
- if bod == 2:\r
- c = 40\r
- else:\r
- c = 200\r
- dt = (c, c, c, 130)\r
- rad_pix[lx,ly] = dt\r
- if lx+1 < self._imgsize:\r
- rad_pix[lx+1, ly] = dt\r
- if lx+1 < self._imgsize and ly+1 < self._imgsize:\r
- rad_pix[lx+1, ly+1] = dt\r
- if ly+1 < self._imgsize:\r
- rad_pix[lx, ly+1] = dt\r
- layer_comp.alpha_composite(roof_additional_detail)\r
- \r
- # Let's put some other details on commercial buildings\r
- if self._tag == "building":\r
- vls = [ "office", "retail", "industrial" ]\r
- if self._value in vls:\r
-\r
- # Find a suitable location to render something\r
- for r in range(15001):\r
- lx = randrange(self._imgsize)\r
- ly = randrange(self._imgsize)\r
- mp = mask_pix[lx,ly]\r
-\r
- # Think of some random shape\r
- if mp[3] == 255:\r
- rw = randrange(3,8)\r
- rh = randrange(3,8)\r
- sh = Image.new("RGBA", (rw, rh), (30,30,30,130))\r
- shp = sh.load()\r
- for sy in range(rh):\r
- for sx in range(rw):\r
- if sx > 0 and sx < rw and sy > 0 and sy < rh: shp[sx, sy] = (180,180,180,160)\r
- rt = randrange(1, 3)\r
- if rt == 2:\r
- sh = sh.rotate(45, expand=True)\r
-\r
- layer_comp.alpha_composite(sh, (lx, ly))\r
-\r
\r
# Highways and runways of any kind get some special treatment\r
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"):\r
mstr_msg("layergen", "Layer image finalized and saved.")\r
\r
\r
- # Depending on if scenery for XP should be made, AND if normal maps should be made, we would\r
- # need to make them at this exact point\r
- """\r
- if mstr_xp_genscenery == True:\r
- if mstr_xp_scn_normalmaps == True and self._is_completion == False:\r
- nm = False\r
- for n in mstr_xp_normal_maps:\r
- if n[0] == self._tag and (n[1] == self._value or n[1] == "*"):\r
- nm = True\r
- break\r
- if nm == True:\r
- nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)\r
- nrm.build_normalmap(layer_comp)\r
- """\r
-\r
-\r
# Return image\r
return layer_comp\r
\r
+ # ------------------------------------------------------------------------------------------\r
+ # ------------------------------------------------------------------------------------------\r
+ # ------------------------------------------------------------------------------------------\r
\r
- # Should we find more than one source, the first one found will take precedence.\r
- # For the others, we will need to generate fading images, so that the final layer \r
- # image works with other tiles\r
- def generate_adjacent_fades(self, mask):\r
- adj_sources = self.find_all_adjacent_sources()\r
- precedence = -1\r
+ # As we now have a specific pool for buildings, we will need to enter a third branch\r
+ # to handle all kinds of buildings in the orthos.\r
+ if self._tag == "building":\r
+ # Access to pixels from OSM mask\r
+ mask_pix = mask.load()\r
\r
- # Be prepared for every border\r
- brd_t = Image.open(mstr_datafolder + "textures/multi_source/brd_t.png")\r
- brd_r = Image.open(mstr_datafolder + "textures/multi_source/brd_r.png")\r
- brd_b = Image.open(mstr_datafolder + "textures/multi_source/brd_b.png")\r
- brd_l = Image.open(mstr_datafolder + "textures/multi_source/brd_l.png")\r
+ # Separate images for additional details\r
+ tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ bld_src = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ bld_main = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ osm_edge = mask.filter(ImageFilter.FIND_EDGES)\r
\r
- brd_t_pix = brd_t.load()\r
- brd_r_pix = brd_r.load()\r
- brd_b_pix = brd_b.load()\r
- brd_l_pix = brd_l.load()\r
+ # Determine which sources to use.\r
+ src = self.findLayerSource()\r
\r
- for s in range(0, 4):\r
- if adj_sources[s] != -1:\r
- precedence = adj_sources[s]\r
- break\r
+ # Patch and border sources. There can only be one for each.\r
+ brd_src = None\r
+ ptc_src = []\r
\r
- # Generate required images\r
- # Basically a shortened version of the main layergen call\r
- adj_image = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- for s in range(0, 4):\r
- if adj_sources[s] != precedence and adj_sources[s] != -1:\r
- src = adj_sources[s]\r
+ # Find this layer's predetermined contrast\r
+ lyr_contrast = self.findLayerContrast()\r
\r
- adj_pix = adj_image.load()\r
+ rg = mstr_resourcegen(self._tag, self._value, src)\r
+ rg.setLayerContrast(int(lyr_contrast))\r
+ bldg_src = rg.gensource()\r
\r
- # Root folder\r
- root_folder = mstr_datafolder + "textures/" + self._tag + "/" + self._value\r
+ # Open the images\r
+ ptc_src.append(bldg_src[0]) # Used to be an array, so let's keep it\r
+ brd_src = bldg_src[1]\r
\r
- # Load in the sources to work with\r
- ptc = glob.glob(root_folder + "/ptc/b" + str(src) + "_p*.png")\r
- brd_src = Image.open(root_folder + "/brd/b" + str(src) + ".png")\r
- ptc_src = []\r
- for p in ptc:\r
- ptc_src.append(Image.open(p))\r
+ # Begin producing a largely random image\r
+ samples = 250 # <- We need this in a moment\r
+ for i in range(samples):\r
+ imgid = 0\r
+ if len(ptc_src) == 1: imgid = 0\r
+ if len(ptc_src) >= 2:\r
+ imgid = randrange(1, len(ptc_src) + 1) - 1\r
+ l = 0 - int(ptc_src[imgid].width / 2)\r
+ r = layer.width - int(ptc_src[imgid].width / 2)\r
+ t = 0 - int(ptc_src[imgid].height / 2)\r
+ b = layer.height - int(ptc_src[imgid].height / 2)\r
+ bld_src.alpha_composite(ptc_src[imgid], (randrange(l, r), randrange(t, b)))\r
+ mstr_msg("layergen", "Layer image generated")\r
\r
- #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" )\r
- #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" )\r
+ bld_src_pix = bld_src.load()\r
+ bld_main_pix = bld_main.load()\r
+ for y in range(0, self._imgsize):\r
+ for x in range(0, self._imgsize):\r
+ mp = mask_pix[x,y]\r
+ bp = bld_src_pix[x,y]\r
+ if mp[3] > 0:\r
+ nc = ( bp[0], bp[1], bp[2], mp[3] )\r
+ bld_main_pix[x,y] = nc\r
+\r
+ bld_main = bld_main.filter(ImageFilter.GaussianBlur(radius=0.5))\r
+ osm_edge = osm_edge.filter(ImageFilter.GaussianBlur(radius=1.5))\r
+ bld_edge = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ bld_edge_pix = bld_edge.load()\r
+ edge_pix = osm_edge.load()\r
+ for y in range(osm_edge.height):\r
+ for x in range(osm_edge.width):\r
+ ep = edge_pix[x,y]\r
+ bp = bld_src_pix[x,y]\r
+ if ep[3] == 255 and bp[3] == 255:\r
+ nc = (0,0,0,60)\r
+ bld_edge_pix[x,y] = nc\r
+ bld_main.alpha_composite(bld_edge)\r
\r
- for i in mstr_mask_blur:\r
- if i[0] == self._tag and i[1] == self._value:\r
- if self._tag != "place" and (self._value != "sea" or self._value != "ocean"): \r
- mask = mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
- break\r
- mask_pix = mask.load()\r
- \r
- # Begin producing a largely random image\r
- samples = 250 # <- We need this in a moment\r
- for i in range(samples):\r
- imgid = 0\r
- if len(ptc_src) == 1: imgid = 0\r
- if len(ptc_src) >= 2:\r
- imgid = randrange(1, len(ptc_src)+1) - 1\r
- l = 0 - int(ptc_src[imgid].width / 2)\r
- r = adj_image.width - int(ptc_src[imgid].width / 2)\r
- t = 0 - int(ptc_src[imgid].height / 2)\r
- b = adj_image.height - int(ptc_src[imgid].height / 2)\r
- adj_image.alpha_composite( ptc_src[imgid], ( randrange(l, r), randrange(t, b) ) )\r
-\r
- adj_image.alpha_composite( brd_src )\r
-\r
- #lyr_pix = lyr_mask.load()\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- if mask_pix[x, y][3] > 0:\r
- rgb=adj_pix[x,y]\r
- a=mask_pix[x,y]\r
- adj_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])\r
\r
- # Up until here we mimiced the exact same behavior as layergen. However, now\r
- # we need to adjust the alpha to make this layer fade.\r
- # Then, we save the image\r
- if s == 0:\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- fade_a = brd_t_pix[0, y]\r
- if mask_pix[x, y][3] > 0:\r
- c = adj_pix[x,y]\r
- adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
- else:\r
- adj_pix[x,y] = (0,0,0,0)\r
- #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")\r
- \r
- if s == 1:\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- fade_a = brd_r_pix[x, 0]\r
- if mask_pix[x, y][3] > 0:\r
- c = adj_pix[x,y]\r
- adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
- else:\r
- adj_pix[x,y] = (0,0,0,0)\r
- #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")\r
- \r
- if s == 2:\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- fade_a = brd_b_pix[0, y]\r
- if mask_pix[x, y][3] > 0:\r
- c = adj_pix[x,y]\r
- adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
+ if mstr_shadow_enabled == True:\r
+ fn = mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(\r
+ self._longitude) + "-" + str(self._lng_number) + "_building-" + self._value + "_layer_shadow.png"\r
+ if os.path.isfile(fn):\r
+ shadow = Image.open(fn)\r
+\r
+ # Add some random trees\r
+ for t in range(0, 5000):\r
+ loc_x = randrange(0, self._imgsize)\r
+ loc_y = randrange(0, self._imgsize)\r
+ shf_val = 21\r
+ shf_x = randrange(loc_x - shf_val, loc_x + shf_val)\r
+ shf_y = randrange(loc_y - shf_val, loc_y + shf_val)\r
+ mp = mask_pix[loc_x, loc_y]\r
+ if mp[3] == 255:\r
+ shf_att = 0\r
+ shf_ok = False\r
+ shf_x = randrange(loc_x - shf_val, loc_x + shf_val)\r
+ shf_y = randrange(loc_y - shf_val, loc_y + shf_val)\r
+ while shf_att < 51:\r
+ if shf_x > 0 and shf_x < self._imgsize and shf_y > 0 and shf_y < self._imgsize:\r
+ sp = mask_pix[shf_x, shf_y]\r
+ if sp[3] == 0:\r
+ shf_ok = True\r
+ break\r
else:\r
- adj_pix[x,y] = (0,0,0,0)\r
- #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")\r
+ shf_att = shf_att + 1\r
+ else:\r
+ shf_val = shf_val + 10\r
\r
- if s == 3:\r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- fade_a = brd_l_pix[x, 0]\r
- if mask_pix[x, y][3] > 0:\r
- c = adj_pix[x,y]\r
- adj_pix[x,y] = (c[0], c[1], c[2], fade_a[3])\r
- else:\r
- adj_pix[x,y] = (0,0,0,0)\r
- #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")\r
+ shf_att = shf_att + 1\r
+\r
+ if shf_ok == True:\r
+ tree = self.generate_tree()\r
+ trees.alpha_composite(tree, (shf_x, shf_y))\r
\r
- # Return the image\r
- return adj_image\r
+ # Perform correction for tree rendering\r
+ tree_pix = trees.load()\r
+ for y in range (0, self._imgsize):\r
+ for x in range(0, self._imgsize):\r
+ mp = mask_pix[x,y]\r
+ tp = tree_pix[x,y]\r
+ if mp[3] == 255 and tp[3] == 255:\r
+ tree_pix[x,y] = (0,0,0,0)\r
\r
\r
\r
- def find_all_adjacent_sources(self):\r
- # Sources for this tag and value - top, right, bottom, left\r
- sources = [-1,-1,-1,-1] \r
+ if mstr_shadow_enabled == True:\r
+ tree_pix = trees.load()\r
+ shadow_pix = tree_shadow.load()\r
+ for y in range(self._imgsize):\r
+ for x in range(self._imgsize):\r
+ tp = tree_pix[x, y]\r
+ if tp[3] > 0:\r
+ rndshd = randrange(5, 210)\r
+ sc = (0, 0, 0, rndshd)\r
+ if x + 8 < self._imgsize and y + 5 < self._imgsize:\r
+ shadow_pix[x + 8, y + 5] = sc\r
+ tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))\r
+ tree_shadow.alpha_composite(trees)\r
+\r
+ # Let's try this one on for size\r
+ bld_comp = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ bld_comp.alpha_composite(tree_shadow)\r
+ bld_comp.alpha_composite(trees)\r
+ shd_p = shadow.load()\r
+ for y in range(self._imgsize):\r
+ for x in range(self._imgsize):\r
+ c = shd_p[x, y]\r
+ if c[3] > 0:\r
+ s = (0, 0, 0, 120 - (randrange(0, 21)))\r
+ shd_p[x, y] = s\r
+ shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1))\r
+ bld_comp.alpha_composite(shadow)\r
+ #bld_comp = bld_comp.filter(ImageFilter.GaussianBlur(radius=1.1))\r
+ bld_comp.alpha_composite(bld_main)\r
\r
- # Perform query for each neighboring tile\r
- src_top = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number+1, self._lng_number, self._tag, self._value)\r
- src_rgt = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number, self._lng_number+1, self._tag, self._value)\r
- src_btm = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number-1, self._lng_number, self._tag, self._value)\r
- src_lft = self._tileinfo.get_adjacency_for_tag_and_value(self._lat_number, self._lng_number-1, self._tag, self._value)\r
+ return bld_comp\r
\r
- if len(src_top) == 2:\r
- if "b" in src_top[1]: sources[0] = src_top[0]\r
- if len(src_rgt) == 2:\r
- if "l" in src_rgt[1]: sources[1] = src_rgt[0]\r
- if len(src_btm) == 2:\r
- if "t" in src_btm[1]: sources[2] = src_btm[0]\r
- if len(src_lft) == 2:\r
- if "r" in src_lft[1]: sources[3] = src_lft[0]\r
\r
- # Report our findings\r
- return sources\r
\r
# Find the next "by-ten" numbers for the current latitude and longitude\r
def find_earthnavdata_number(self):\r
\r
import os\r
-from PIL import Image, ImageFilter, ImageEnhance\r
+from PIL import Image, ImageFilter, ImageEnhance, ImageFile\r
from defines import *\r
from layergen import *\r
from log import *\r
from functions import *\r
from xp_normalmap import *\r
\r
+ImageFile.LOAD_TRUNCATED_IMAGES = True\r
+\r
# -------------------------------------------------------------------\r
# ORTHOGRAPHIC\r
# Your personal aerial satellite. Always on. At any altitude.*\r
self._latlngfld = self.latlng_folder([lat,lng])\r
mstr_msg("photogen", "Photogen initialized")\r
\r
+\r
+ # Defines the order of layer names that were processed\r
+ # Called by orthographic prior to starting the photo gen process\r
+ def setLayerNames(self, names):\r
+ self._lyrnames = names\r
+\r
\r
# This puts it all together. Bonus: AND saves it.\r
- def genphoto(self, layers, waterlayers):\r
+ def genphoto(self, layers, waterlayers, cpl):\r
# Template for the file name which is always the same\r
#root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"\r
\r
+ # Correct layers\r
+ #mstr_msg("photogen", "Correcting layer order issues")\r
+ #layers = self.correctLayerIssues(layers)\r
+\r
# First, we walk through all layers and blend them on top of each other, in order\r
mstr_msg("photogen", "Merging layers")\r
\r
+ lyr=0\r
for l in layers:\r
- self._tile.alpha_composite(l)\r
+ if self._lyrnames[lyr] != "building":\r
+ self._tile.alpha_composite(l)\r
+ lyr=lyr+1\r
\r
\r
# When we have run through this loop, we will end up with a sandwiched\r
if emptyspace == True:\r
\r
mstr_msg("photogen", "Patching empty space")\r
- mask = self.buildCompletionMask()\r
-\r
- # Load the mask\r
- mask_px = mask.load()\r
\r
cmpl = Image.new("RGBA", (self._imgsize, self._imgsize))\r
- cmp_px = cmpl.load()\r
\r
edn = self.find_earthnavdata_number()\r
edns = self.latlng_folder(edn)\r
- idx = 0\r
- for r in mstr_completion_colors:\r
- if r[0] == edns:\r
- break\r
- else:\r
- idx = idx+1\r
- \r
- for y in range(self._imgsize):\r
- for x in range(self._imgsize):\r
- p = mask_px[x,y]\r
- if p[3] > 0:\r
- cidx = randrange(0, len(mstr_completion_colors[idx][1])-1)\r
- clr = mstr_completion_colors[idx][1][cidx]\r
- cmp_px[x,y] = (clr[0], clr[1], clr[2], 255)\r
-\r
- # Some features\r
- patches = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")\r
-\r
- # Pick an amount of features to add\r
- patch_amt = randrange(1, 7)\r
-\r
- # Add those somewhere\r
- for p in range(1, patch_amt+1):\r
- # Load some patch\r
- ptc = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(randrange(1, len(patches)+1)) + ".png")\r
- # Rotate it\r
- ptc = ptc.rotate(randrange(0, 360), expand=True)\r
-\r
- # Make sure ortho generation does not crash\r
- if ptc.width >= mstr_photores:\r
- ptc = ptc.resize((1536, 1536), Image.Resampling.BILINEAR)\r
-\r
- # Adjust alpha on this image\r
- ptc_p = ptc.load()\r
- for y in range(ptc.height):\r
- for x in range(ptc.width):\r
- c = ptc_p[x,y]\r
- if c[3] > 0:\r
- na = c[3] - 160\r
- if na < 0: na = 0\r
- nc = (c[0], c[1], c[2], na)\r
- ptc_p[x,y] = nc\r
-\r
- # Find a location INSIDE the image!\r
- px = randrange(1, randrange(self._imgsize - ptc.width - 1))\r
- py = randrange(1, randrange(self._imgsize - ptc.height - 1))\r
-\r
- # Add it to the completion image\r
- cmpl.alpha_composite(ptc, dest=(px,py))\r
+\r
+ cplstr = ""\r
+ for c in range(0, len(cpl)):\r
+ cplstr = cplstr + str(cpl[c])\r
+ if c < len(cpl)-1:\r
+ cplstr = cplstr + "_"\r
+\r
+ # Should this not exist yet, we need to create it\r
+ rg = mstr_resourcegen("landuse", "meadow", cpl)\r
+ rg.setLayerContrast(randrange(1,4))\r
+ ptcimg = rg.gensource()\r
+\r
+ ptc_src = [ptcimg[0]]\r
+ samples = 250 # <- We need this in a moment\r
+ for i in range(samples):\r
+ imgid = 0\r
+ if len(ptc_src) == 1: imgid = 0\r
+ l = 0 - int(ptc_src[imgid].width / 2)\r
+ r = cmpl.width - int(ptc_src[imgid].width / 2)\r
+ t = 0 - int(ptc_src[imgid].height / 2)\r
+ b = cmpl.height - int(ptc_src[imgid].height / 2)\r
+ cmpl.alpha_composite(ptc_src[imgid], (randrange(l, r), randrange(t, b)))\r
+\r
+ brd_img = ptcimg[1]\r
+ cmpl.alpha_composite(brd_img)\r
+\r
+ # Patches to add from other sources. If they don't exist, we also need to make them\r
+ masks = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")\r
+ amt = randrange(5, 16)\r
+ for i in range(1, amt + 1):\r
+ pick = randrange(0, len(masks))\r
+ patchmask = Image.open(masks[pick])\r
+ patchpix = patchmask.load()\r
+ # Pick from possible tags and values for the patches\r
+ patchtags = [\r
+ ["landuse", "meadow"],\r
+ ["landuse", "grass"],\r
+ ["natural", "heath"],\r
+ ["natural", "scrub"]\r
+ ]\r
+\r
+ numbers = list(range(1, 16))\r
+ src = random.sample(numbers, 5)\r
+\r
+ patchpick = randrange(0, len(patchtags))\r
+\r
+ rg = mstr_resourcegen(patchtags[patchpick][0], patchtags[patchpick][1], src)\r
+ rg.setLayerContrast(randrange(1, 4))\r
+ ptch = rg.gensource()\r
+\r
+ rg_img = ptch[0]\r
+ rg_pix = rg_img.load()\r
+\r
+ # The patch to be used in the layer\r
+ layerpatch = Image.new("RGBA", (patchmask.width, patchmask.height))\r
+ lp_pix = layerpatch.load()\r
+ for y in range(0, patchmask.height):\r
+ for x in range(0, patchmask.width):\r
+ ptc_msk = patchpix[x, y]\r
+ if ptc_msk[3] > 0:\r
+ oc = rg_pix[x, y]\r
+ nc = (oc[0], oc[1], oc[2], ptc_msk[3])\r
+ lp_pix[x, y] = nc\r
+\r
+ layerpatch = layerpatch.rotate(randrange(0, 360), expand=True)\r
+\r
+ lx = randrange(self._imgsize - layerpatch.width)\r
+ ly = randrange(self._imgsize - layerpatch.height)\r
+ cmpl.alpha_composite(layerpatch, (lx, ly))\r
\r
# Merge the images\r
cmpl.alpha_composite(self._tile)\r
corrpix[x,y] = nc\r
if c[3] == 0:\r
corrpix[x,y] = (0,0,0,0)\r
+\r
+ # One more thing...\r
+ mstr_msg("photogen", "Adding features to layers")\r
+ self.addTreesToFeatures(layers)\r
+\r
+ # Throw missing buildings on top\r
+ lyr = 0\r
+ for l in layers:\r
+ if self._lyrnames[lyr] == "building":\r
+ self._tile.alpha_composite(l)\r
+ lyr = lyr + 1\r
\r
# We are now in posession of the final image.\r
\r
# Contrast\r
- self._tile = ImageEnhance.Contrast(self._tile).enhance(1)\r
+ #self._tile = ImageEnhance.Contrast(self._tile).enhance(0.1)\r
\r
# This we can save accordingly.\r
self._tile.save(mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._ty) + "_" + str(self._tx) + ".png")\r
nrmimg.save(nrmfln)\r
\r
\r
+ # Generates some random tree.\r
+ # We will now move away from using pre-made trees...\r
+ # they didn't look so great\r
+ def generate_tree(self):\r
+ sx = randrange(18, 31)\r
+ sy = randrange(18, 31)\r
+\r
+ treepoly = Image.new("RGBA", (sx, sy))\r
+ draw = ImageDraw.Draw(treepoly)\r
+\r
+ draw.ellipse((4, 4, sx - 4, sy - 4), fill="black")\r
+\r
+ tree = Image.new("RGBA", (sx, sy))\r
+ treepx = tree.load()\r
+ maskpx = treepoly.load()\r
+\r
+ # How many tree points do we want?\r
+ treepts = 75\r
+ # How many of those have been drawn?\r
+ ptsdrawn = 0\r
+\r
+ bc = [\r
+ (36, 50, 52),\r
+ (30, 41, 39),\r
+ (32, 45, 37),\r
+ (32, 39, 49),\r
+ (33, 34, 40),\r
+ (44, 50, 53),\r
+ (40, 46, 48),\r
+ (14, 31, 38),\r
+ (17, 41, 33),\r
+ (39, 56, 35),\r
+ (51, 51, 42),\r
+ (12, 27, 31),\r
+ (45, 59, 48),\r
+ (37, 54, 29),\r
+ (59, 50, 34),\r
+ (59, 59, 35),\r
+ (59, 51, 35),\r
+ (70, 72, 45),\r
+ (48, 59, 44),\r
+ (29, 47, 23),\r
+ (47, 61, 43),\r
+ (29, 68, 15),\r
+ (53, 77, 63),\r
+ (20, 68, 40)\r
+ ]\r
+\r
+ bcp = randrange(0, len(bc))\r
+\r
+ treedraw = ImageDraw.Draw(tree)\r
+ while ptsdrawn < treepts + 1:\r
+ rx = randrange(0, sx)\r
+ ry = randrange(0, sy)\r
+ mp = maskpx[rx, ry]\r
+ if mp[3] > 0:\r
+ d = randrange(0, 51)\r
+ r = bc[bcp][0]\r
+ g = bc[bcp][1] + d\r
+ b = bc[bcp][2] + (d // 2)\r
+ a = randrange(170, 256)\r
+ c = (r, g, b, a)\r
+ ex = randrange(2, 5)\r
+ ey = randrange(2, 5)\r
+ treedraw.ellipse((rx - (ex // 2), ry - (ey // 2), rx + (ey // 2), ry + (ey // 2)), fill=c)\r
+ ptsdrawn = ptsdrawn + 1\r
+\r
+ for y in range(0, tree.height):\r
+ for x in range(0, tree.width):\r
+ tp = treepx[x, y]\r
+ diff = randrange(0, 31)\r
+ nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])\r
+ treepx[x, y] = nc\r
+\r
+ tree = tree.filter(ImageFilter.GaussianBlur(radius=0.5))\r
+\r
+ for y in range(0, tree.height):\r
+ for x in range(0, tree.width):\r
+ tp = treepx[x, y]\r
+ diff = randrange(0, 51)\r
+ nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])\r
+ treepx[x, y] = nc\r
+\r
+ return tree\r
+\r
+\r
+ # This used to be in layergen and solves the problem of roads being rendered above trees.\r
+ # It is the only solution that worked, after some research.\r
+ def addTreesToFeatures(self, layers):\r
+\r
+ # Walk through list of layers to decide where to add the trees\r
+ curlyr = 0\r
+ for lyr in self._lyrnames:\r
+ # Add trees only in some features\r
+ if (lyr[0] == "landuse" and lyr[1] == "cemetery") or (\r
+ lyr[0] == "landuse" and lyr[1] == "residential") or (\r
+ lyr[0] == "leisure" and lyr[1] == "park"):\r
+ trees = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ amt = 4000\r
+ lyrmask = layers[curlyr].load() # We can use the layer image as alpha mask\r
+ for i in range(1, amt + 1):\r
+ lx = randrange(0, self._imgsize)\r
+ ly = randrange(0, self._imgsize)\r
+ lp = lyrmask[lx,ly]\r
+ if lp[3] > 0:\r
+ tree = self.generate_tree()\r
+ trees.alpha_composite(tree, (lx, ly))\r
+\r
+ tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ tree_pix = trees.load()\r
+ shadow_pix = tree_shadow.load()\r
+ for y in range(self._imgsize):\r
+ for x in range(self._imgsize):\r
+ tp = tree_pix[x, y]\r
+ if tp[3] > 0:\r
+ rndshd = randrange(5, 210)\r
+ sc = (0, 0, 0, rndshd)\r
+ if x + 8 < self._imgsize and y + 5 < self._imgsize:\r
+ shadow_pix[x + 8, y + 5] = sc\r
+ tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))\r
+ tree_shadow.alpha_composite(trees)\r
+ self._tile.alpha_composite(tree_shadow)\r
+ curlyr = curlyr + 1\r
+\r
+ # Reset\r
+ curlyr = 0\r
+ bldg = []\r
+ tilepix = self._tile.load()\r
+ for lyr in self._lyrnames:\r
+ if lyr[0] == "building":\r
+ bldg.append(curlyr)\r
+ curlyr = curlyr + 1\r
+\r
+ for b in range(0, len(bldg)):\r
+ bldg_lyr = layers[bldg[b]].load()\r
+ shdw = Image.open(mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_" + self._lyrnames[bldg[b]][0] + "-" + self._lyrnames[bldg[b]][1] + "_layer_shadow.png")\r
+ shdw_pix = shdw.load()\r
+ for y in range(0, self._imgsize):\r
+ for x in range(0, self._imgsize):\r
+ bpix = bldg_lyr[x,y]\r
+ spix = shdw_pix[x,y]\r
+ if bpix[3] > 0 and spix[0] == 255:\r
+ tilepix[x,y] = ( bpix[0], bpix[1], bpix[2], bpix[3] )\r
+\r
+\r
+\r
+ # Correct some layer issues\r
+ def correctLayerIssues(self, layers):\r
+\r
+ # First the residential/forest dilemma\r
+ residential = 0\r
+ forest = 0\r
+\r
+ curlyr = 0\r
+ for lyr in self._lyrnames:\r
+ if lyr[0] == "landuse" and lyr[1] == "residential":\r
+ residential=curlyr\r
+ if lyr[0] == "landuse" and lyr[1] == "forest":\r
+ forest = curlyr\r
+ curlyr = curlyr+1\r
+\r
+ layers[forest].alpha_composite(layers[residential])\r
+\r
+ return layers\r
+\r
+\r
\r
\r
# This checks the final image for empty patches. Should one be\r
# -------------------------------------------------------------------
import glob
+from os import MFD_ALLOW_SEALING
from random import randrange
from PIL import Image
from osmxml import *
self._tag = tag
self._value = value
self._edges = "" # To be filled by _edgeDetect call
- self._source = -1
+ self._source = ""
self._mask = mask
latlngfld = xplane_latlng_folder([lat, lng])
self._tileinfo = mstr_tileinfo(lat, lng, v, h, latlngfld)
return srcfld
- # Prepare the tile accordingly
- def _prepareTile(self):
+ # Use the mask to determine the edges
+ def _determineEdges(self):
# Load the mask pixels
mp = self._mask.load()
imgsize = self._mask.width
al=False
# Top scan
- for i in range(0, imgsize-1):
+ 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-1):
+ 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-1):
+ 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-1):
- p = mp[1,i]
+ for i in range(0, imgsize):
+ p = mp[0,i]
if p[3] > 0:
al=True
break
if ab==True: adjstr = adjstr + "b"
if al==True: adjstr = adjstr + "l"
- # Now find out of there is a source from any adjacent tile
- adjtiles = findAdjacentTilesTo(self._tile_v, self._tile_h)
- sat = []
- sar = []
- sab = []
- sal = []
- if self._is_completion == False:
- if at == True: sat = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[0][0], adjtiles[0][1], self._tag, self._value) # Top
- if ar == True: sar = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[1][0], adjtiles[1][1], self._tag, self._value) # Right
- if ab == True: sab = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[2][0], adjtiles[2][1], self._tag, self._value) # Bottom
- if al == True: sal = self._tileinfo.get_adjacency_for_tag_and_value(adjtiles[3][0], adjtiles[3][1], self._tag, self._value) # Left
- if self._is_completion == True:
- if at == True: sat = self._tileinfo.get_adjacency_for_completion(adjtiles[0][0], adjtiles[0][1]) # Top
- if ar == True: sar = self._tileinfo.get_adjacency_for_completion(adjtiles[1][0], adjtiles[1][1]) # Right
- if ab == True: sab = self._tileinfo.get_adjacency_for_completion(adjtiles[2][0], adjtiles[2][1]) # Bottom
- if al == True: sal = self._tileinfo.get_adjacency_for_completion(adjtiles[3][0], adjtiles[3][1]) # Left
-
- if self._source == -1 and len(sat) == 2: self._source = sat[0]
- if self._source == -1 and len(sar) == 2: self._source = sar[0]
- if self._source == -1 and len(sab) == 2: self._source = sab[0]
- if self._source == -1 and len(sal) == 2: self._source = sal[0]
-
- # If there was nothing in the info still, we need to select some source
- if self._source == -1:
- srcfld = self._findCorrectTextureFolder()
- tx = mstr_datafolder + "textures/" + srcfld[0] + "/" + srcfld[1] + "/brd/b*.png"
- lst = glob.glob(tx)
- if len(lst) == 1: self._source = 1
- if len(lst) >= 2: self._source = randrange(1, len(lst)+1)
-
-
- # Store into DB - but only if there is something to store
+ # We will now write this down first, without a source being selected
if adjstr != "":
- if self._is_completion == False:
- r = self._tileinfo.get_adjacency_for_tag_and_value(self._tile_v, self._tile_h, self._tag, self._value)
- if len(r) == 0:
- self._tileinfo.add_adjacency_data(self._tile_v, self._tile_h, self._tag, self._value, self._source, adjstr)
- mstr_msg("tileprep", "Adjacency info stored in database")
-
- if self._is_completion == True:
- r = self._tileinfo.get_adjacency_for_completion(self._tile_v, self._tile_h)
- if len(r) == 0:
- self._tileinfo.add_completion_data(self._tile_v, self._tile_h, self._tag, self._value, self._source, adjstr)
- mstr_msg("tileprep", "Adjacency info for completion stored in database")
+ 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:
+ l[3] = l[3].replace("\n", "")
+ 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:
+ l[3] = l[3].replace("\n", "")
+ 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):
+ df = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(tile_v) + "_" + str(tile_h)
+ fnlines = []
+ contrast = 0
+ 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 l[0] == self._tag and l[1] == self._value:
+ l[2] = res
+ contrast = int(l[4])
+
+ # Find contrast values for some tags
+ if (
+ (l[0] == "landuse" and l[1] == "forest") or
+ (l[0] == "landuse" and l[1] == "meadow") or
+ (l[0] == "landuse" and l[1] == "grass") or
+ (l[0] == "leisure" and l[1] == "nature_reserve") or
+ (l[0] == "natural" and l[1] == "grassland") or
+ (l[0] == "landuse" and l[1] == "greenfield") or
+ (l[0] == "natural" and l[1] == "heath") or
+ (l[0] == "natural" and l[1] == "wetland") or
+ (l[0] == "leisure" and l[1] == "park") or
+ (l[0] == "building")
+ ):
+ if int(l[4]) == 0: contrast = randrange(1, 4)
+
+ l[3] = l[3].replace("\n", "")
+ fnlines[curline] = l[0] + " " + l[1] + " " + l[2] + " " + l[3] + " " + str(contrast) + "\n"
+
+ curline = curline+1
+
+ lines = ""
+ for l in range(len(fnlines)):
+ lines = lines + fnlines[l]
+
+ with open(df, 'w') as textfile:
+ textfile.write(lines)
+
+
+ # 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):
+
+ # The first tile gets to choose something for itself
+ if self._tile_v == 1 and self._tile_h == 1:
+ resstr = self._selectResources()
+ self._storeResourceInfo(1, 1, resstr)
+
+ # Start "raytracing"
+
+ # Initial reset
+ tv = self._tile_v
+ th = self._tile_h
+ # Start marching north
+ while tv < mlat+1:
+ restch = self._getResourceTouch(tv, th)
+ if "t" in restch:
+ resstr = self._getResourceInfo(tv, th)
+ if resstr == "0":
+ resstr = self._selectResources()
+ self._storeResourceInfo(tv, th, resstr)
+ resd = self._getResourceInfo(tv+1, th)
+ if resd=="0":
+ self._storeResourceInfo(tv + 1, th, resstr)
+ else:
+ break
+ tv = tv + 1
+
+ # Start marching east
+ tv = self._tile_v
+ th = self._tile_h
+ while th < mlng + 1:
+ restch = self._getResourceTouch(tv, th)
+ if "r" in restch:
+ resstr = self._getResourceInfo(tv, th)
+ if resstr == "0":
+ resstr = self._selectResources()
+ self._storeResourceInfo(tv, th, resstr)
+ resd = self._getResourceInfo(tv, th+1)
+ if resd == "0":
+ self._storeResourceInfo(tv, th + 1, resstr)
+ else:
+ break
+ th = th + 1
+
+ # Start marching south
+ tv = self._tile_v
+ th = self._tile_h
+ while tv > 0:
+ restch = self._getResourceTouch(tv, th)
+ if "b" in restch:
+ resstr = self._getResourceInfo(tv, th)
+ if resstr == "0":
+ resstr = self._selectResources()
+ self._storeResourceInfo(tv, th, resstr)
+ resd = self._getResourceInfo(tv - 1, th)
+ if resd == "0":
+ self._storeResourceInfo(tv - 1, th, resstr)
+ else:
+ break
+ tv = tv - 1
+
+ # Start marching west
+ tv = self._tile_v
+ th = self._tile_h
+ while th > 0:
+ restch = self._getResourceTouch(tv, th)
+ if "l" in restch:
+ resstr = self._getResourceInfo(tv, th)
+ if resstr == "0":
+ resstr = self._selectResources()
+ self._storeResourceInfo(tv, th, resstr)
+ resd = self._getResourceInfo(tv, th-1)
+ if resd == "0":
+ self._storeResourceInfo(tv, th - 1, resstr)
+ else:
+ break
+ th = th - 1
\ No newline at end of file