# We will simply things to achieve good-looking results.\r
# You can, however, disable the shadow rendering layer here.\r
mstr_shadow_enabled = True\r
-mstr_shadow_strength = 0.85\r
-mstr_shadow_shift = 24\r
+mstr_shadow_strength = 0.65\r
+mstr_shadow_shift = 15\r
# The tags that cast shadows\r
mstr_shadow_casters = [\r
("landuse", "forest"),\r
("leisure", "nature_reserve"),\r
+ ("natural", "wood"),\r
+ ("natural", "tree_row"),\r
("building", "semidetached_house"),\r
("building", "apartments"),\r
("building", "garage"),\r
("leisure", "garden", "leisure", "green"),\r
("leisure", "sports_centre", "leisure", "green"),\r
("leisure", "pitch", "leisure", "green"),\r
+ ("leisure", "playground", "leisure", "green"),\r
("landuse", "farmland", "landuse", "farmland"),\r
("landuse", "farmyard", "landuse", "farmland"),\r
("landuse", "military", "landuse", "residential-boundary"),\r
("waterway", "stream", 10),\r
("leisure", "nature_reserve", "landuse", "forest"),\r
("landuse", "forest", "landuse", "forest"),\r
+ ("natural", "wood", "natural", "wood"),\r
+ ("natural", "tree_row", 22),\r
("natural", "wetland", "natural", "wetland"),\r
("natural", "scrub", "natural", "scrub"),\r
("natural", "heath", "natural", "heath"),\r
("water", "lake", "natural", "water"),\r
("water", "pond", "natural", "water"),\r
("water", "river", "natural", "water"),\r
- ("amenity", "parking", "amenities", "parking"),\r
+ ("leisure", "swimming_pool", "natural", "water"),\r
+ ("amenity", "parking", "amenity", "parking"),\r
+ ("amenity", "school", "amenity", "school"),\r
("highway", "pedestrian", 4),\r
# Z-Order 4\r
("highway", "motorway", 32),\r
("building", "terrace", "building", "industrial"),\r
("building", "hangar", "building", "industrial"),\r
("building", "school", "building", "common"),\r
+ ("building", "kindergarten", "building", "kindergarten"),\r
+ ("building", "public", "building", "public"),\r
+ ("building", "commercial", "building", "commercial"),\r
("building", "yes", "building", "common"),\r
("place", "sea", "natural", "sea"),\r
("place", "ocean", "natural", "sea")\r
# Blur values for the single masks of the ortho layers\r
mstr_mask_blur = [\r
# Z-Order 0\r
- ("landuse", "residential", 30),\r
- ("boundary", "administrative", 30),\r
+ ("landuse", "residential", 20),\r
+ ("boundary", "administrative", 20),\r
# Z-Order 1\r
- ("landuse", "grass", 30),\r
- ("landuse", "cemetery", 30),\r
- ("landuse", "greenfield", 30),\r
- ("landuse", "orchard", 30),\r
- ("landuse", "meadow", 30),\r
- ("barrier", "hedge", 5),\r
+ ("landuse", "grass", 12),\r
+ ("landuse", "cemetery", 12),\r
+ ("landuse", "greenfield", 12),\r
+ ("landuse", "orchard", 12),\r
+ ("landuse", "meadow", 12),\r
+ ("barrier", "hedge", 1),\r
("landuse", "recreation_ground", 20),\r
- ("landuse", "vineyard", 30),\r
- ("natural", "grassland", 30),\r
+ ("landuse", "vineyard", 12),\r
+ ("natural", "grassland", 12),\r
("natural", "wetland", 30),\r
- ("natural", "scrub", 20),\r
- ("natural", "heath", 20),\r
- ("leisure", "park", 30),\r
+ ("natural", "scrub", 15),\r
+ ("natural", "heath", 15),\r
+ ("leisure", "park", 15),\r
("leisure", "golf_course", 25),\r
- ("leisure", "dog_park", 35),\r
+ ("leisure", "dog_park", 15),\r
("leisure", "garden", 20),\r
("leisure", "sports_centre", 5),\r
("leisure", "pitch", 2),\r
+ ("leisure", "playground", 2),\r
("landuse", "farmland", 10),\r
("landuse", "farmyard", 10),\r
# Z-Order 2\r
- ("landuse", "forest", 20),\r
- ("leisure", "nature_reserve", 20),\r
- ("landuse", "military", 30),\r
+ ("landuse", "forest", 8),\r
+ ("leisure", "nature_reserve", 8),\r
+ ("natural", "wood", 8),\r
+ ("natural", "tree_row", 8),\r
+ ("landuse", "military", 15),\r
# Z-Order 3\r
("natural", "bare_rock", 25),\r
("natural", "water", 4),\r
("water", "lake", 10),\r
("water", "pond", 10),\r
("water", "river", 10),\r
+ ("leisure", "swimming_pool", 10),\r
("waterway", "river", 10),\r
("waterway", "stream", 10),\r
- ("amenity", "parking", 3),\r
+ ("amenity", "parking", 1),\r
+ ("amenity", "school", 1),\r
("highway", "pedestrian", 12),\r
# Z-Order 4\r
- ("highway", "motorway", 5),\r
- ("highway", "primary", 5),\r
- ("highway", "secondary", 5),\r
- ("highway", "tertiary", 5),\r
- ("highway", "unclassified", 5),\r
- ("highway", "living_street", 5),\r
- ("highway", "residential", 5),\r
- ("highway", "service", 3),\r
- ("highway", "footway", 3),\r
- ("highway", "track", 3),\r
- ("highway", "path", 3),\r
- ("railway", "rail", 4),\r
+ ("highway", "motorway", 2),\r
+ ("highway", "primary", 2),\r
+ ("highway", "secondary", 2),\r
+ ("highway", "tertiary", 2),\r
+ ("highway", "unclassified", 2),\r
+ ("highway", "living_street", 2),\r
+ ("highway", "residential", 2),\r
+ ("highway", "service", 2),\r
+ ("highway", "footway", 2),\r
+ ("highway", "track", 2),\r
+ ("highway", "path", 2),\r
+ ("railway", "rail", 2),\r
# Z-Order 5\r
- ("aeroway", "taxiway", 12),\r
- ("aeroway", "runway", 12),\r
+ ("aeroway", "taxiway", 2),\r
+ ("aeroway", "runway", 2),\r
("building", "detached", 1),\r
("building", "church", 1),\r
("building", "hotel", 1),\r
("building", "terrace", 1),\r
("building", "hangar", 1),\r
("building", "school", 1),\r
- ("building", "yes", 1),\r
+ ("building", "kindergarten", 1),\r
+ ("building", "public", 1),\r
+ ("building", "commercial", 1),\r
+ ("building", "yes", 0),\r
("place", "sea", 1),\r
("place", "ocean", 1)\r
]\r
+\r
+\r
+# Base colors for different building types\r
+mstr_building_base_colors = [\r
+ ("detached", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#534136", "#4d3424", "#534b45", "#553724", "#574c45",\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("church", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("hotel", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("farm", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#534136", "#4d3424", "#534b45", "#553724", "#574c45"\r
+ ]\r
+ ),\r
+ ("semidetached_house", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#534136", "#4d3424", "#534b45", "#553724", "#574c45",\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("apartments", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("civic", [\r
+ "#7b848b", "#5d6d7b", "#5e646a", "#454d53", "#585b5e",\r
+ "#877a78", "#797372", "#797372", "#6f5550", "#7c7574"\r
+ ]\r
+ ),\r
+ ("garage", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#523731", "#46484e", "#33353a", "#3a3733", "#5d5a57"\r
+ ]\r
+ ),\r
+ ("office", [\r
+ "#403a33", "#4f4b46", "#413629", "#574c3f", "#3a2e21",\r
+ "#aaaeb6", "#939cac", "#8a919d", "#a0b9bf", "#8d999b",\r
+ "#49575a", "#273d43", "#313a3c", "#484f50", "#212d30"\r
+ ]\r
+ ),\r
+ ("retail", [\r
+ "#403a33", "#4f4b46", "#413629", "#574c3f", "#3a2e21",\r
+ "#aaaeb6", "#939cac", "#8a919d", "#a0b9bf", "#8d999b",\r
+ "#49575a", "#273d43", "#313a3c", "#484f50", "#212d30"\r
+ ]\r
+ ),\r
+ ("industrial", [\r
+ "#939fa2", "#728080", "#9eafaf", "#4f6061", "#96b2b6",\r
+ "#b2b398", "#878868", "#989888", "#bdb79c", "#959386"\r
+ ]\r
+ ),\r
+ ("house", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#534136", "#4d3424", "#534b45", "#553724", "#574c45",\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("terrace", [\r
+ "#86898c", "#5e656c", "#6d6868", "#6d6c68", "#46443d",\r
+ "#3d4546", "#6b7071", "#716b70", "#738684", "#868073"\r
+ ]\r
+ ),\r
+ ("hangar", [\r
+ "#403a33", "#4f4b46", "#413629", "#574c3f", "#3a2e21",\r
+ "#aaaeb6", "#939cac", "#8a919d", "#a0b9bf", "#8d999b",\r
+ "#49575a", "#273d43", "#313a3c", "#484f50", "#212d30"\r
+ ]\r
+ ),\r
+ ("school", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("kindergarten", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("public", [\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ ),\r
+ ("commercial", [\r
+ "#403a33", "#4f4b46", "#413629", "#574c3f", "#3a2e21",\r
+ "#aaaeb6", "#939cac", "#8a919d", "#a0b9bf", "#8d999b",\r
+ "#49575a", "#273d43", "#313a3c", "#484f50", "#212d30"\r
+ ]\r
+ ),\r
+ ("yes", [\r
+ "#693333", "#592b2b", "#513434", "#4a1e1e", "#362626",\r
+ "#534136", "#4d3424", "#534b45", "#553724", "#574c45",\r
+ "#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",\r
+ "#454545", "#39393b", "#4b4b4c", "#363638", "#525252"\r
+ ]\r
+ )\r
+]\r
+\r
+\r
+mstr_completion_colors = [\r
+ ("+50+000", [\r
+ (48,63,34),\r
+ (81,95,64),\r
+ (105,100,64),\r
+ (91,105,72),\r
+ (78,69,41),\r
+ (116,113,78),\r
+ (90,94,69),\r
+ (58,68,40),\r
+ (57,72,41),\r
+ (93,103,76),\r
+ (139,142,111),\r
+ (92,102,73),\r
+ (71,86,55),\r
+ (103,105,91),\r
+ (96,78,56),\r
+ (143,141,113),\r
+ (107,108,74),\r
+ (41,56,34),\r
+ (51,63,41),\r
+ (137,137,107)\r
+ ]\r
+ )\r
+]
\ No newline at end of file
import os\r
from random import randrange\r
import random\r
-from PIL import Image, ImageFilter, ImageDraw, ImagePath\r
+from PIL import Image, ImageFilter, ImageDraw, ImagePath, ImageEnhance\r
from defines import *\r
from log import *\r
from tileinfo import *\r
layer.alpha_composite( ptc_src[imgid], ( randrange(l, r), randrange(t, b) ) )\r
mstr_msg("layergen", "Layer image generated")\r
\r
+ # We now need to add the seamless border\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"):\r
- amt = randrange(1,16)\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(1,251)\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 = osm_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.25))\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
+ amt = 3500\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
- lx = randrange( int(layer.width/20), layer.width - (int(layer.width/20)) - img.width ) \r
- ly = randrange( int(layer.width/20), layer.width - (int(layer.width/20)) - img.height )\r
- layer.alpha_composite( img, (lx, ly) )\r
-\r
+ p = randrange(1, 11)\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
+ layer.alpha_composite(tree, (lx, ly))\r
\r
- # We now need to add the seamless border\r
- layer.alpha_composite( brd_src )\r
mstr_msg("layergen", "Layer image completed")\r
\r
\r
if mask_pix[x, y][3] > 0:\r
rgb=layer_pix[x,y]\r
a=mask_pix[x,y]\r
- if self._value == "residential":\r
- layer_comp_pix[x, y] = ( rgb[0], rgb[1], rgb[2], int(a[3]/2))\r
- if self._value != "residential":\r
- layer_comp_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])\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
fade = Image.open(fade_fn + "_fade_left.png")\r
layer_comp.alpha_composite(fade)\r
mstr_msg("layergen", "Adjacent fading completed")\r
- \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
# Store layer\r
if self._is_completion == False:\r
for x in range(self._imgsize-1):\r
m = mask_pix[x,y]\r
shf_x = 0\r
- # Buildings get slightly closer shadows\r
- if self._tag == "building":\r
- shf_x = x + int(mstr_shadow_shift/2)\r
- if self._tag != "building":\r
- shf_x = x + mstr_shadow_shift\r
+ shf_x = x + mstr_shadow_shift\r
if shf_x <= self._imgsize-1:\r
a = mask_pix[x,y][3]\r
st = 0\r
- if self._tag == "building":\r
- st = random.uniform(0.25, mstr_shadow_strength/2)\r
- if self._tag != "building":\r
- st = random.uniform(0.45, mstr_shadow_strength)\r
+ st = random.uniform(0.45, mstr_shadow_strength)\r
ca = a * st\r
aa = int(ca)\r
shadow_pix[shf_x, y] = (0,0,0,aa)\r
#self._tiledb.close_db()\r
\r
# Create a water mask we need to remove from the DDS later\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"):\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
inl_mask = Image.new("RGBA", (self._imgsize, self._imgsize), (0,0,0,0))\r
lyr_pix = layer_comp.load()\r
mstr_msg("layergen", "Edge mask generated")\r
\r
# As above, we will apply the blur as noted in the defines\r
- for i in mstr_mask_blur:\r
- if i[0] == self._tag and i[1] == self._value:\r
- osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
- break\r
+ # Except for buildings\r
+ if self._tag != "building":\r
+ for i in mstr_mask_blur:\r
+ if i[0] == self._tag and i[1] == self._value:\r
+ osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))\r
+ break\r
osm_edge = osm_edge.filter(ImageFilter.BoxBlur(radius=1))\r
\r
\r
edge_pix = osm_edge.load()\r
layer_comp_pix = layer_comp.load()\r
\r
- # Let's define some base color ranges for different types of buildings\r
- bld_clr = [\r
- ("detached", 190, 192, 195), \r
- ("church", 134, 134, 136), \r
- ("hotel", 153, 147, 138), \r
- ("farm", 145, 124, 121), \r
- ("semidetached_house", 167, 163, 152), \r
- ("apartments", 129, 134, 127), \r
- ("civic", 134, 134, 136), \r
- ("garage", 101, 109, 111),\r
- ("office", 139, 152, 156),\r
- ("retail", 121, 122, 108),\r
- ("industrial", 191, 192, 187),\r
- ("house", 145, 124, 121),\r
- ("terrace", 191, 192, 187),\r
- ("hangar", 137, 162, 195),\r
- ("school", 111, 117, 115),\r
- ("yes", 152, 144, 141)\r
- ]\r
-\r
- # Find the color index to work with\r
- cidx = 0\r
- if self._tag == "building":\r
- for c in bld_clr:\r
- if c[0] == self._value:\r
- break\r
- cidx = cidx+1\r
-\r
for y in range(self._imgsize):\r
for x in range(self._imgsize):\r
if mask_pix[x, y][3] > 0:\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
- d = randrange(140,160)\r
+ d = randrange(85, 101)\r
layer_comp_pix[x, y] = ( d,d,d,a[3] )\r
if self._tag == "highway" and self._value == "motorway":\r
d = randrange(1,20)\r
# Rock, grass, water\r
mats = [ (48-d, 45-d, 42-d), (58-d, 81-d, 41-d), (129-d, 148-d, 159-d) ]\r
# Pick one of those\r
- pick = randrange(1,4)\r
+ #pick = randrange(1,4)\r
+ pick = 2\r
t = a[3]-d\r
if t < 0: t = 0\r
- layer_comp_pix[x, y] = ( mats[pick-1][0], mats[pick-1][1], mats[pick-1][2], t )\r
+ if e[3] > 0:\r
+ layer_comp_pix[x, y] = ( mats[pick-1][0], mats[pick-1][1], mats[pick-1][2], t )\r
\r
# A bit special here\r
if self._tag == "building":\r
- \r
- # Find a color range\r
+ # Find a color range for the pixel\r
d = randrange(1,21)\r
- # Bring in some variety by making the one or other pixel darker\r
- dp = randrange(1, 3)\r
- if dp == 2:\r
- d = d + 20\r
- # Adjust this pixel\r
- c = (bld_clr[cidx][1]-d, bld_clr[cidx][2]-d, bld_clr[cidx][3]-d, 255)\r
- # Set pixel\r
- layer_comp_pix[x, y] = c \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
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
+ for t in range(20001):\r
+ lx = randrange(self._imgsize)\r
+ ly = randrange(self._imgsize)\r
+ a = mask_pix[lx,ly]\r
+ if a[3] > 0:\r
+ if lx < self._imgsize and ly < self._imgsize:\r
+ p = randrange(1,11)\r
+ tree = Image.open(mstr_datafolder + "textures/building/area/p" + str(p) + ".png")\r
+ layer_comp.alpha_composite(tree, (lx, ly))\r
+\r
# We will do some super magic here to let houses look more realistic\r
- if self._tag == "building" or self._value == "cemetery":\r
- vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "office", "retail", "industrial", "house", "school", "yes" ]\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
# Generate a new image\r
details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
for x in range(self._imgsize-1):\r
p = layer_pix[x,y]\r
if p[3] > 0:\r
- shf_x = x+randrange(1, 21)\r
- shf_y = y+randrange(1, 21)\r
- shf_x2 = x-randrange(1, 21)\r
- shf_y2 = y-randrange(1, 21)\r
- if shf_x <= self._imgsize-1 and shf_x >= 0 and shf_y <= self._imgsize-1 and shf_y >= 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
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
- # Merge the details BELOW the houses\r
- details.alpha_composite(layer_comp)\r
- layer_comp = details\r
- # New edge\r
- osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)\r
- osm_edge = osm_edge.filter(ImageFilter.MaxFilter)\r
- osm_edge = osm_edge.filter(ImageFilter.GaussianBlur(radius=2))\r
- # Blur the image\r
- layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))\r
- osm_edge.alpha_composite(layer_comp)\r
- layer_comp = osm_edge\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
\r
# Add some random trees\r
div = int(self._imgsize/200)\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 > 0 and shf_x < self._imgsize and shf_y > 0 and shf_y < self._imgsize:\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
for y in range(self._imgsize-1):\r
for x in range(self._imgsize-1):\r
m = mask_pix[x,y]\r
- shf_x = x + randrange(1, mstr_shadow_shift + 1)\r
- shf_x2 = x + randrange(1, mstr_shadow_shift + 1)\r
- if shf_x <= self._imgsize-1 and shf_x >= 0 and shf_x2 <= self._imgsize-1 and shf_x2 >= 0:\r
+ shf_x = x + mstr_shadow_shift\r
+ shf_y = y + (mstr_shadow_shift/2)\r
+ if shf_x < self._imgsize and shf_y < self._imgsize:\r
a = mask_pix[x,y][3]\r
- st = random.uniform(0.6, mstr_shadow_strength)\r
+ st = random.uniform(0.3, mstr_shadow_strength)\r
ca = a * st\r
aa = int(ca)\r
- shadow_pix[shf_x, y] = (0,0,0,aa)\r
- shadow_pix[shf_x2, y] = (0,0,0,aa)\r
+ shadow_pix[shf_x, shf_y] = (0,0,0,aa)\r
+ shadow = shadow.filter(ImageFilter.GaussianBlur(radius=2))\r
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")\r
mstr_msg("layergen", "Shadow layer completed")\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 = osm_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 = osm_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
# 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
for x in range(self._imgsize):\r
if mask_pix[x, y][3] > 0:\r
# Find a suitable color\r
- w = randrange(185, 215)\r
+ w = randrange(125, 156)\r
a=mask_pix[x,y]\r
layer_comp_pix[x, y] = ( w,w,w,a[3] )\r
\r
+ if self._tag == "highway" and self._value == "residential":\r
+ mask_pix = osm_edge.load()\r
+ layer_comp_pix = layer_comp.load()\r
+ for y in range(self._imgsize):\r
+ for x in range(self._imgsize):\r
+ if mask_pix[x, y][3] > 0:\r
+ # Find a suitable color\r
+ w = randrange(60, 96)\r
+ a=mask_pix[x,y]\r
+ layer_comp_pix[x, y] = ( w,w,w,a[3] )\r
+\r
+\r
mstr_msg("layergen", "Street lines added")\r
\r
if self._tag == "waterway" and (self._value == "river" or self._value == "stream"):\r
layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=4))\r
\r
-\r
# Store layer\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
mstr_msg("layergen", "Layer image finalized and saved.")\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
+ earthnavdata = []\r
+ lat = abs(int(self._latitude / 10) * 10)\r
+ lng = abs(int(self._longitude / 10) * 10)\r
+ earthnavdata.append(lat)\r
+ earthnavdata.append(lng)\r
+ return earthnavdata\r
+\r
+ # Construct an X-Plane compatible folder name for latitude and longitude\r
+ def xplane_latlng_folder(self, numbers):\r
+ fstr = ""\r
+ if numbers[0] >= 0: fstr = "+"\r
+ if numbers[0] < 0: fstr = "-"\r
+ if abs(numbers[0]) < 10: fstr = fstr + "0" + str(numbers[0])\r
+ if abs(numbers[0]) >= 10 and numbers[0] <= 90: fstr = fstr + str(numbers[0])\r
+\r
+ if numbers[1] >= 0: fstr = fstr + "+"\r
+ if numbers[1] < 0: fstr = fstr + "-"\r
+ if abs(numbers[1]) < 10: fstr = fstr + "00" + str(numbers[1])\r
+ if abs(numbers[1]) >= 10 and numbers[0] <= 99: fstr = fstr + "0" + str(numbers[1])\r
+ if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])\r
+\r
+ return fstr\r
# Corel Draw!\r
imgd = ImageDraw.Draw(mask_img)\r
\r
- # Draw polygons for everything except those three tags\r
+ # Draw polygons\r
if self._isline == False:\r
if len(pts) >= 3:\r
- imgd.polygon(pts, fill="#000000")\r
+ if self._tag != "building":\r
+ imgd.polygon(pts, fill="#000000")\r
+ if self._tag == "building":\r
+ # Find ID of color index to use\r
+ idx = 0\r
+ for i in mstr_building_base_colors:\r
+ if i[0] == self._value:\r
+ break\r
+ else:\r
+ idx = idx + 1\r
+ # Now we have the index.\r
+ # Pick some color from it\r
+ c = randrange(len( mstr_building_base_colors[idx][1]))\r
+ clr = mstr_building_base_colors[idx][1][c]\r
+ # And draw the polygon with that -\r
+ # this will be the base color for that building in the layer\r
+ imgd.polygon(pts, fill=clr)\r
\r
# For road specific items, draw lines instead\r
if self._isline == True:\r
\r
import os\r
-from PIL import Image, ImageFilter\r
+from PIL import Image, ImageFilter, ImageEnhance\r
from defines import *\r
from layergen import *\r
from log import *\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
+ # Shadow merging\r
+ bldg_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ if mstr_shadow_enabled == True:\r
+ for l in mstr_ortho_layers:\r
+ if l[0] == "building":\r
+ if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"):\r
+ shd = Image.open(root_filename + l[0] + "-" + l[1] + "_layer_shadow.png")\r
+ bldg_shadow.alpha_composite(shd)\r
+ # Details merging\r
+ bldg_details = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ for l in mstr_ortho_layers:\r
+ if l[0] == "building":\r
+ if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer_details.png"):\r
+ dtl = Image.open(root_filename + l[0] + "-" + l[1] + "_layer_details.png")\r
+ dtl = dtl.filter(ImageFilter.GaussianBlur(radius=1))\r
+ bldg_details.alpha_composite(dtl)\r
+ # Building merging\r
+ bldg_main = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ for l in mstr_ortho_layers:\r
+ if l[0] == "building":\r
+ if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):\r
+ bld = Image.open(root_filename + l[0] + "-" + l[1] + "_layer.png")\r
+ bld = bld.filter(ImageFilter.GaussianBlur(radius=0.35))\r
+ bldg_main.alpha_composite(bld)\r
+ # Merge the building layers\r
+ bldg_final = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+ bldg_final.alpha_composite(bldg_details)\r
+ bldg_final.alpha_composite(bldg_shadow)\r
+ bldg_final.alpha_composite(bldg_main)\r
+\r
for l in mstr_ortho_layers:\r
if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):\r
# Need to divert in case we have shadows\r
if mstr_shadow_enabled == True:\r
if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"):\r
- sn = root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"\r
- s_layer = Image.open(sn)\r
- self._tile.alpha_composite(s_layer)\r
- # Complete the file name based on the template\r
- fn = root_filename + l[0] + "-" + l[1] + "_layer.png"\r
- # Open the layer\r
- layer = Image.open(fn)\r
- # Converge the layer with this image\r
- self._tile.alpha_composite(layer)\r
+ if l[0] != "building":\r
+ sn = root_filename + l[0] + "-" + l[1] + "_layer_shadow.png"\r
+ s_layer = Image.open(sn)\r
+ self._tile.alpha_composite(s_layer)\r
+ if l[0] != "building":\r
+ # Complete the file name based on the template\r
+ fn = root_filename + l[0] + "-" + l[1] + "_layer.png"\r
+ # Open the layer\r
+ layer = Image.open(fn)\r
+ if l[0] == "leisure" and l[1] == "pitch":\r
+ layer = layer.filter(ImageFilter.GaussianBlur(radius=0.2))\r
+ # Converge the layer with this image\r
+ self._tile.alpha_composite(layer)\r
+\r
+ # Drop the buildings on top\r
+ self._tile.alpha_composite(bldg_final)\r
+\r
\r
# When we have run through this loop, we will end up with a sandwiched\r
# image of all the other images, in their correct order.\r
["natural", "water"],\r
["water", "lake"],\r
["water", "pond"],\r
- ["water", "river"]\r
+ ["water", "river"],\r
+ ["leisure", "swimming_pool"]\r
)\r
for l in water_layers:\r
fn = mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_" + l[0] + "-" + l[1] + "_layer_mask.png"\r
# Scale to correct size.\r
#self._tile = self._tile.resize((mstr_photores, mstr_photores), Image.Resampling.BILINEAR)\r
\r
+ # Contrast\r
+ self._tile = ImageEnhance.Contrast(self._tile).enhance(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
\r
cur_lng = self._lng
for lat in range(1, self._mlat+1):
for lng in range(1, self._mlng+1):
- # The '1' after 'ORTHOPHOTO' defines we want water underneath transparent parts of the DDS texture/ortho.
- # This ensures that even if the mesh does not include information for there being a water body,
- # we will get 100% correct representation of the water bodies.
- scrtxt = "ORTHOPHOTO 1 " + str(cur_lng) + " " + str(cur_lat) + " " + str(round(cur_lng+mstr_zl_18, 6)) + " " + str(cur_lat) + " " + str(round(cur_lng+mstr_zl_18, 6)) + " " + str(round(cur_lat+self._vstep, 6)) + " " + str(cur_lng) + " " + str(round(cur_lat+self._vstep, 6)) + " terrain/" + self._latlngfld + "/" + str(lat) + "_" + str(lng) + ".ter\n"
-
- with open(scr, 'a') as textfile:
- textfile.write(scrtxt)
+ # Write the line only if an ortho exists of course.
+ if os.path.isfile(mstr_datafolder + "z_orthographic/" + self._latlngfld + "/orthos/" + str(lat) + "_" + str(lng) + ".dds" ) == True:
+ # The '1' after 'ORTHOPHOTO' defines we want water underneath transparent parts of the DDS texture/ortho.
+ # This ensures that even if the mesh does not include information for there being a water body,
+ # we will get 100% correct representation of the water bodies.
+ scrtxt = "ORTHOPHOTO 1 " + str(cur_lng) + " " + str(cur_lat) + " " + str(round(cur_lng+mstr_zl_18, 6)) + " " + str(cur_lat) + " " + str(round(cur_lng+mstr_zl_18, 6)) + " " + str(round(cur_lat+self._vstep, 6)) + " " + str(cur_lng) + " " + str(round(cur_lat+self._vstep, 6)) + " terrain/" + self._latlngfld + "/" + str(lat) + "_" + str(lng) + ".ter\n"
+
+ with open(scr, 'a') as textfile:
+ textfile.write(scrtxt)
cur_lng = round(cur_lng + mstr_zl_18, 6)