Massive commit. Raytracer for tile preparation. Resource generator. Everything moved into RAM for processing.
This commit is contained in:
parent
aae81c58e9
commit
2278fe3b0a
12
defines.py
12
defines.py
@ -132,6 +132,7 @@ mstr_ortho_layers = [
|
|||||||
("natural", "bare_rock", "natural", "bare_rock"),
|
("natural", "bare_rock", "natural", "bare_rock"),
|
||||||
("highway", "track", 3),
|
("highway", "track", 3),
|
||||||
("highway", "path", 3),
|
("highway", "path", 3),
|
||||||
|
("highway", "footway", 4),
|
||||||
("leisure", "park", "leisure", "green"),
|
("leisure", "park", "leisure", "green"),
|
||||||
("leisure", "dog_park", "leisure", "green"),
|
("leisure", "dog_park", "leisure", "green"),
|
||||||
("leisure", "garden", "leisure", "green"),
|
("leisure", "garden", "leisure", "green"),
|
||||||
@ -144,7 +145,6 @@ mstr_ortho_layers = [
|
|||||||
# Z-Order 2
|
# Z-Order 2
|
||||||
("highway", "service", 6),
|
("highway", "service", 6),
|
||||||
("highway", "residential", 12),
|
("highway", "residential", 12),
|
||||||
("highway", "footway", 4),
|
|
||||||
("highway", "primary", 25),
|
("highway", "primary", 25),
|
||||||
("highway", "secondary", 13),
|
("highway", "secondary", 13),
|
||||||
("highway", "tertiary", 20),
|
("highway", "tertiary", 20),
|
||||||
@ -191,6 +191,7 @@ mstr_ortho_layers = [
|
|||||||
("building", "kindergarten", "building", "kindergarten"),
|
("building", "kindergarten", "building", "kindergarten"),
|
||||||
("building", "public", "building", "public"),
|
("building", "public", "building", "public"),
|
||||||
("building", "commercial", "building", "commercial"),
|
("building", "commercial", "building", "commercial"),
|
||||||
|
("building", "warehouse", "building", "warehouse"),
|
||||||
("building", "yes", "building", "common"),
|
("building", "yes", "building", "common"),
|
||||||
("water", "lake", "natural", "water"),
|
("water", "lake", "natural", "water"),
|
||||||
("water", "pond", "natural", "water"),
|
("water", "pond", "natural", "water"),
|
||||||
@ -284,6 +285,7 @@ mstr_mask_blur = [
|
|||||||
("building", "kindergarten", 1),
|
("building", "kindergarten", 1),
|
||||||
("building", "public", 1),
|
("building", "public", 1),
|
||||||
("building", "commercial", 1),
|
("building", "commercial", 1),
|
||||||
|
("building", "warehouse", 1),
|
||||||
("building", "yes", 0),
|
("building", "yes", 0),
|
||||||
("place", "sea", 1),
|
("place", "sea", 1),
|
||||||
("place", "ocean", 1)
|
("place", "ocean", 1)
|
||||||
@ -396,7 +398,13 @@ mstr_building_base_colors = [
|
|||||||
"#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",
|
"#373942", "#40424a", "#363b4f", "#2c2d32", "#444651",
|
||||||
"#454545", "#39393b", "#4b4b4c", "#363638", "#525252"
|
"#454545", "#39393b", "#4b4b4c", "#363638", "#525252"
|
||||||
]
|
]
|
||||||
)
|
),
|
||||||
|
("warehouse", [
|
||||||
|
"#403a33", "#4f4b46", "#413629", "#574c3f", "#3a2e21",
|
||||||
|
"#aaaeb6", "#939cac", "#8a919d", "#a0b9bf", "#8d999b",
|
||||||
|
"#49575a", "#273d43", "#313a3c", "#484f50", "#212d30"
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,3 +108,4 @@ def xplane_latlng_folder(numbers):
|
|||||||
if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])
|
if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])
|
||||||
|
|
||||||
return fstr
|
return fstr
|
||||||
|
|
||||||
|
923
layergen.py
923
layergen.py
File diff suppressed because it is too large
Load Diff
8
log.py
8
log.py
@ -11,9 +11,15 @@
|
|||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
from colorama import init as colorama_init
|
||||||
|
from colorama import Fore
|
||||||
|
from colorama import Style
|
||||||
from defines import *
|
from defines import *
|
||||||
|
|
||||||
def mstr_msg(fnc, msg):
|
def mstr_msg(fnc, msg):
|
||||||
if mstr_show_log == True:
|
if mstr_show_log == True:
|
||||||
|
colorama_init()
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
print(now.strftime(" %H:%M:%S" + " | ["+fnc+"] | " + msg))
|
|
||||||
|
print(f' {Fore.GREEN}'+now.strftime("%H:%M:%S")+f'{Style.RESET_ALL} | {Fore.YELLOW}[' + fnc + f']{Style.RESET_ALL} | {Fore.CYAN}'+ msg + f'{Style.RESET_ALL}')
|
||||||
|
#print(f"{Fore.GREEN}" + now.strftime(" %H:%M:%S" + " | ["+fnc+"] | " + msg))
|
@ -252,6 +252,14 @@ class mstr_maskgen:
|
|||||||
if sp[3] != 0:
|
if sp[3] != 0:
|
||||||
bld_shadow_pix[x,y] = (0,0,0,120)
|
bld_shadow_pix[x,y] = (0,0,0,120)
|
||||||
|
|
||||||
|
|
||||||
|
# Mark buildings in red
|
||||||
|
for y in range(mstr_photores):
|
||||||
|
for x in range(mstr_photores):
|
||||||
|
mp = mask_pix[x,y]
|
||||||
|
if mp[3] != 0:
|
||||||
|
bld_shadow_pix[x,y] = (255,0,0,255)
|
||||||
|
|
||||||
# Store
|
# Store
|
||||||
if os.path.isfile(fn) == True:
|
if os.path.isfile(fn) == True:
|
||||||
lyr = Image.open(fn)
|
lyr = Image.open(fn)
|
||||||
|
24
og.py
24
og.py
@ -35,13 +35,9 @@ prep = False
|
|||||||
|
|
||||||
if len(sys.argv) == 4:
|
if len(sys.argv) == 4:
|
||||||
cli = True
|
cli = True
|
||||||
if sys.argv[3] == "true": prep = True
|
|
||||||
|
|
||||||
#if len(sys.argv) == 4:
|
|
||||||
# pbf = True
|
|
||||||
|
|
||||||
# Only if we find enough arguments, proceed.
|
# Only if we find enough arguments, proceed.
|
||||||
if cli == True:
|
if cli:
|
||||||
lat = int(sys.argv[1])
|
lat = int(sys.argv[1])
|
||||||
lng = int(sys.argv[2])
|
lng = int(sys.argv[2])
|
||||||
|
|
||||||
@ -50,11 +46,12 @@ if cli == True:
|
|||||||
# Create the class and init values
|
# Create the class and init values
|
||||||
og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd(), prep)
|
og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd(), prep)
|
||||||
|
|
||||||
if prep == True:
|
# Prepare a tile
|
||||||
|
if sys.argv[3] == "prepare":
|
||||||
og._prepareTile()
|
og._prepareTile()
|
||||||
|
|
||||||
if prep == False:
|
# Generate orthos
|
||||||
if sys.argv[3] != "xpscenery":
|
if sys.argv[3] != "prepare" and sys.argv[3] != "xpscenery":
|
||||||
og._generateOrthos_mt(int(sys.argv[3]))
|
og._generateOrthos_mt(int(sys.argv[3]))
|
||||||
|
|
||||||
# Build the terrain mesh and assign ground textures
|
# Build the terrain mesh and assign ground textures
|
||||||
@ -62,17 +59,6 @@ if cli == True:
|
|||||||
og.generate_xp_scenery()
|
og.generate_xp_scenery()
|
||||||
|
|
||||||
|
|
||||||
# Only if we find enough arguments, proceed.
|
|
||||||
if pbf == True:
|
|
||||||
lat = int(sys.argv[1])
|
|
||||||
lng = int(sys.argv[2])
|
|
||||||
pbf = sys.argv[3]
|
|
||||||
|
|
||||||
if pbf == "pbf":
|
|
||||||
# Create the class and init values
|
|
||||||
og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd())
|
|
||||||
og._generateData()
|
|
||||||
|
|
||||||
|
|
||||||
if cli == False and pbf == False:
|
if cli == False and pbf == False:
|
||||||
mstr_msg("_main", "Please provide Latitude and Longitude. Exiting.")
|
mstr_msg("_main", "Please provide Latitude and Longitude. Exiting.")
|
||||||
|
@ -170,9 +170,13 @@ class mstr_orthographic:
|
|||||||
mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))
|
mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))
|
||||||
maxlatlng = [ mlat, mlng ]
|
maxlatlng = [ mlat, mlng ]
|
||||||
|
|
||||||
|
# For completion layers
|
||||||
|
numbers = list(range(1, 16))
|
||||||
|
res = random.sample(numbers, 5)
|
||||||
|
|
||||||
procs = []
|
procs = []
|
||||||
for p in range(1, amtsmt+1):
|
for p in range(1, amtsmt+1):
|
||||||
proc = Process(target=self._buildOrtho, args=[1, p, amtsmt])
|
proc = Process(target=self._buildOrtho, args=[1, p, amtsmt, res])
|
||||||
procs.append(proc)
|
procs.append(proc)
|
||||||
proc.start()
|
proc.start()
|
||||||
mstr_msg("orthographic", "Ortho threads started")
|
mstr_msg("orthographic", "Ortho threads started")
|
||||||
@ -181,7 +185,7 @@ class mstr_orthographic:
|
|||||||
# Starts a threading loop to build orthos, with the defined starting point in
|
# Starts a threading loop to build orthos, with the defined starting point in
|
||||||
# the lat-lng grid. You will also need to provide the horizontal stepping so
|
# the lat-lng grid. You will also need to provide the horizontal stepping so
|
||||||
# that the thread keeps running.
|
# that the thread keeps running.
|
||||||
def _buildOrtho(self, v, h, step):
|
def _buildOrtho(self, v, h, step, cpl):
|
||||||
|
|
||||||
# Starting point
|
# Starting point
|
||||||
grid_lat = v
|
grid_lat = v
|
||||||
@ -256,7 +260,6 @@ class mstr_orthographic:
|
|||||||
lg = mstr_layergen(layer[0], layer[1], self._lat, grid_lat, self._long, grid_lng, layer[2])
|
lg = mstr_layergen(layer[0], layer[1], self._lat, grid_lat, self._long, grid_lng, layer[2])
|
||||||
lg.set_max_latlng_tile(maxlatlng)
|
lg.set_max_latlng_tile(maxlatlng)
|
||||||
lg.set_latlng_folder(self._latlngfld)
|
lg.set_latlng_folder(self._latlngfld)
|
||||||
#lg.open_db()
|
|
||||||
lg.open_tile_info()
|
lg.open_tile_info()
|
||||||
lyr = lg.genlayer(mask, osmxml)
|
lyr = lg.genlayer(mask, osmxml)
|
||||||
photolayers.append(lyr)
|
photolayers.append(lyr)
|
||||||
@ -274,7 +277,8 @@ class mstr_orthographic:
|
|||||||
# Snap a photo with our satellite :)
|
# Snap a photo with our satellite :)
|
||||||
mstr_msg("orthographic", "Generating ortho photo")
|
mstr_msg("orthographic", "Generating ortho photo")
|
||||||
pg = mstr_photogen(self._lat, self._long, grid_lat, grid_lng, maxlatlng[0], maxlatlng[1])
|
pg = mstr_photogen(self._lat, self._long, grid_lat, grid_lng, maxlatlng[0], maxlatlng[1])
|
||||||
pg.genphoto(photolayers, waterlayers)
|
pg.setLayerNames(layers)
|
||||||
|
pg.genphoto(photolayers, waterlayers, cpl)
|
||||||
mstr_msg("orthographic", " -- Ortho photo generated -- ")
|
mstr_msg("orthographic", " -- Ortho photo generated -- ")
|
||||||
print("")
|
print("")
|
||||||
print("")
|
print("")
|
||||||
@ -375,12 +379,12 @@ class mstr_orthographic:
|
|||||||
bb_lat = self._lat
|
bb_lat = self._lat
|
||||||
bb_lng = self._long
|
bb_lng = self._long
|
||||||
|
|
||||||
|
|
||||||
# We will now prepare the graphic tile generation. We do this by only generating
|
# We will now prepare the graphic tile generation. We do this by only generating
|
||||||
# the masks and determine which sources to use in the actual images.
|
# the masks and determine which sources to use in the actual images.
|
||||||
# Previously, I downloaded all XML files in one go - but to ease the
|
# Previously, I downloaded all XML files in one go - but to ease the
|
||||||
# stress on OSM servers and my server, we will do acquire the data
|
# stress on OSM servers and my server, we will do acquire the data
|
||||||
# only for the current processed part of the tile.
|
# only for the current processed part of the tile.
|
||||||
|
"""
|
||||||
for lat_grid in range(1, maxlatlng[0]+1):
|
for lat_grid in range(1, maxlatlng[0]+1):
|
||||||
for lng_grid in range(1, maxlatlng[1]+1):
|
for lng_grid in range(1, maxlatlng[1]+1):
|
||||||
# Adjust bounding box
|
# Adjust bounding box
|
||||||
@ -403,7 +407,7 @@ class mstr_orthographic:
|
|||||||
mask = mg._build_mask(osmxml, is_prep=True) # We need an object here
|
mask = mg._build_mask(osmxml, is_prep=True) # We need an object here
|
||||||
|
|
||||||
tp = mstr_tileprep(self._lat, self._long, lat_grid, lng_grid, layer[0], layer[1], mask, False)
|
tp = mstr_tileprep(self._lat, self._long, lat_grid, lng_grid, layer[0], layer[1], mask, False)
|
||||||
tp._prepareTile()
|
tp._determineEdges()
|
||||||
|
|
||||||
curlyr = curlyr+1
|
curlyr = curlyr+1
|
||||||
|
|
||||||
@ -428,6 +432,24 @@ class mstr_orthographic:
|
|||||||
if cur_tile_y > top_lat:
|
if cur_tile_y > top_lat:
|
||||||
top_lat = cur_tile_y
|
top_lat = cur_tile_y
|
||||||
|
|
||||||
|
exit(1)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# We now need to "raytrace" the resources for correct placement
|
||||||
|
mstr_msg("orthographic", "Performing resource plamement tracing for tile")
|
||||||
|
for lat_grid in range(1, maxlatlng[0]+1):
|
||||||
|
for lng_grid in range(1, maxlatlng[1]+1):
|
||||||
|
mstr_msg("orthographic", "Placement tracing for " + str(lat_grid) + ":" + str(lng_grid))
|
||||||
|
df = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + str(lat_grid) + "_" + str(lng_grid)
|
||||||
|
fnlines = []
|
||||||
|
with open(df) as textfile:
|
||||||
|
fnlines = textfile.readlines()
|
||||||
|
|
||||||
|
for l in range(0, len(fnlines)):
|
||||||
|
lyr = fnlines[l].split(" ")
|
||||||
|
tp = mstr_tileprep(self._lat, self._long, lat_grid, lng_grid, lyr[0], lyr[1], None, False)
|
||||||
|
tp._setLatLngFold(self._latlngfld)
|
||||||
|
tp._placeTileSources(lat_grid, lng_grid)
|
||||||
|
|
||||||
|
|
||||||
# Generates X-Plane 11/12 scenery with
|
# Generates X-Plane 11/12 scenery with
|
||||||
|
305
photogen.py
305
photogen.py
@ -1,12 +1,14 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from PIL import Image, ImageFilter, ImageEnhance
|
from PIL import Image, ImageFilter, ImageEnhance, ImageFile
|
||||||
from defines import *
|
from defines import *
|
||||||
from layergen import *
|
from layergen import *
|
||||||
from log import *
|
from log import *
|
||||||
from functions import *
|
from functions import *
|
||||||
from xp_normalmap import *
|
from xp_normalmap import *
|
||||||
|
|
||||||
|
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# ORTHOGRAPHIC
|
# ORTHOGRAPHIC
|
||||||
# Your personal aerial satellite. Always on. At any altitude.*
|
# Your personal aerial satellite. Always on. At any altitude.*
|
||||||
@ -37,16 +39,29 @@ class mstr_photogen:
|
|||||||
mstr_msg("photogen", "Photogen initialized")
|
mstr_msg("photogen", "Photogen initialized")
|
||||||
|
|
||||||
|
|
||||||
|
# Defines the order of layer names that were processed
|
||||||
|
# Called by orthographic prior to starting the photo gen process
|
||||||
|
def setLayerNames(self, names):
|
||||||
|
self._lyrnames = names
|
||||||
|
|
||||||
|
|
||||||
# This puts it all together. Bonus: AND saves it.
|
# This puts it all together. Bonus: AND saves it.
|
||||||
def genphoto(self, layers, waterlayers):
|
def genphoto(self, layers, waterlayers, cpl):
|
||||||
# Template for the file name which is always the same
|
# Template for the file name which is always the same
|
||||||
#root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"
|
#root_filename = mstr_datafolder + "/_cache/" + str(self._lat) + "-" + str(self._ty) + "_" + str(self._lng) + "-" + str(self._tx) + "_"
|
||||||
|
|
||||||
|
# Correct layers
|
||||||
|
#mstr_msg("photogen", "Correcting layer order issues")
|
||||||
|
#layers = self.correctLayerIssues(layers)
|
||||||
|
|
||||||
# First, we walk through all layers and blend them on top of each other, in order
|
# First, we walk through all layers and blend them on top of each other, in order
|
||||||
mstr_msg("photogen", "Merging layers")
|
mstr_msg("photogen", "Merging layers")
|
||||||
|
|
||||||
|
lyr=0
|
||||||
for l in layers:
|
for l in layers:
|
||||||
|
if self._lyrnames[lyr] != "building":
|
||||||
self._tile.alpha_composite(l)
|
self._tile.alpha_composite(l)
|
||||||
|
lyr=lyr+1
|
||||||
|
|
||||||
|
|
||||||
# When we have run through this loop, we will end up with a sandwiched
|
# When we have run through this loop, we will end up with a sandwiched
|
||||||
@ -65,65 +80,80 @@ class mstr_photogen:
|
|||||||
if emptyspace == True:
|
if emptyspace == True:
|
||||||
|
|
||||||
mstr_msg("photogen", "Patching empty space")
|
mstr_msg("photogen", "Patching empty space")
|
||||||
mask = self.buildCompletionMask()
|
|
||||||
|
|
||||||
# Load the mask
|
|
||||||
mask_px = mask.load()
|
|
||||||
|
|
||||||
cmpl = Image.new("RGBA", (self._imgsize, self._imgsize))
|
cmpl = Image.new("RGBA", (self._imgsize, self._imgsize))
|
||||||
cmp_px = cmpl.load()
|
|
||||||
|
|
||||||
edn = self.find_earthnavdata_number()
|
edn = self.find_earthnavdata_number()
|
||||||
edns = self.latlng_folder(edn)
|
edns = self.latlng_folder(edn)
|
||||||
idx = 0
|
|
||||||
for r in mstr_completion_colors:
|
|
||||||
if r[0] == edns:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
idx = idx+1
|
|
||||||
|
|
||||||
for y in range(self._imgsize):
|
cplstr = ""
|
||||||
for x in range(self._imgsize):
|
for c in range(0, len(cpl)):
|
||||||
p = mask_px[x,y]
|
cplstr = cplstr + str(cpl[c])
|
||||||
if p[3] > 0:
|
if c < len(cpl)-1:
|
||||||
cidx = randrange(0, len(mstr_completion_colors[idx][1])-1)
|
cplstr = cplstr + "_"
|
||||||
clr = mstr_completion_colors[idx][1][cidx]
|
|
||||||
cmp_px[x,y] = (clr[0], clr[1], clr[2], 255)
|
|
||||||
|
|
||||||
# Some features
|
# Should this not exist yet, we need to create it
|
||||||
patches = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")
|
rg = mstr_resourcegen("landuse", "meadow", cpl)
|
||||||
|
rg.setLayerContrast(randrange(1,4))
|
||||||
|
ptcimg = rg.gensource()
|
||||||
|
|
||||||
# Pick an amount of features to add
|
ptc_src = [ptcimg[0]]
|
||||||
patch_amt = randrange(1, 7)
|
samples = 250 # <- We need this in a moment
|
||||||
|
for i in range(samples):
|
||||||
|
imgid = 0
|
||||||
|
if len(ptc_src) == 1: imgid = 0
|
||||||
|
l = 0 - int(ptc_src[imgid].width / 2)
|
||||||
|
r = cmpl.width - int(ptc_src[imgid].width / 2)
|
||||||
|
t = 0 - int(ptc_src[imgid].height / 2)
|
||||||
|
b = cmpl.height - int(ptc_src[imgid].height / 2)
|
||||||
|
cmpl.alpha_composite(ptc_src[imgid], (randrange(l, r), randrange(t, b)))
|
||||||
|
|
||||||
# Add those somewhere
|
brd_img = ptcimg[1]
|
||||||
for p in range(1, patch_amt+1):
|
cmpl.alpha_composite(brd_img)
|
||||||
# Load some patch
|
|
||||||
ptc = Image.open(mstr_datafolder + "textures/tile/completion/p" + str(randrange(1, len(patches)+1)) + ".png")
|
|
||||||
# Rotate it
|
|
||||||
ptc = ptc.rotate(randrange(0, 360), expand=True)
|
|
||||||
|
|
||||||
# Make sure ortho generation does not crash
|
# Patches to add from other sources. If they don't exist, we also need to make them
|
||||||
if ptc.width >= mstr_photores:
|
masks = glob.glob(mstr_datafolder + "textures/tile/completion/*.png")
|
||||||
ptc = ptc.resize((1536, 1536), Image.Resampling.BILINEAR)
|
amt = randrange(5, 16)
|
||||||
|
for i in range(1, amt + 1):
|
||||||
|
pick = randrange(0, len(masks))
|
||||||
|
patchmask = Image.open(masks[pick])
|
||||||
|
patchpix = patchmask.load()
|
||||||
|
# Pick from possible tags and values for the patches
|
||||||
|
patchtags = [
|
||||||
|
["landuse", "meadow"],
|
||||||
|
["landuse", "grass"],
|
||||||
|
["natural", "heath"],
|
||||||
|
["natural", "scrub"]
|
||||||
|
]
|
||||||
|
|
||||||
# Adjust alpha on this image
|
numbers = list(range(1, 16))
|
||||||
ptc_p = ptc.load()
|
src = random.sample(numbers, 5)
|
||||||
for y in range(ptc.height):
|
|
||||||
for x in range(ptc.width):
|
|
||||||
c = ptc_p[x,y]
|
|
||||||
if c[3] > 0:
|
|
||||||
na = c[3] - 160
|
|
||||||
if na < 0: na = 0
|
|
||||||
nc = (c[0], c[1], c[2], na)
|
|
||||||
ptc_p[x,y] = nc
|
|
||||||
|
|
||||||
# Find a location INSIDE the image!
|
patchpick = randrange(0, len(patchtags))
|
||||||
px = randrange(1, randrange(self._imgsize - ptc.width - 1))
|
|
||||||
py = randrange(1, randrange(self._imgsize - ptc.height - 1))
|
|
||||||
|
|
||||||
# Add it to the completion image
|
rg = mstr_resourcegen(patchtags[patchpick][0], patchtags[patchpick][1], src)
|
||||||
cmpl.alpha_composite(ptc, dest=(px,py))
|
rg.setLayerContrast(randrange(1, 4))
|
||||||
|
ptch = rg.gensource()
|
||||||
|
|
||||||
|
rg_img = ptch[0]
|
||||||
|
rg_pix = rg_img.load()
|
||||||
|
|
||||||
|
# The patch to be used in the layer
|
||||||
|
layerpatch = Image.new("RGBA", (patchmask.width, patchmask.height))
|
||||||
|
lp_pix = layerpatch.load()
|
||||||
|
for y in range(0, patchmask.height):
|
||||||
|
for x in range(0, patchmask.width):
|
||||||
|
ptc_msk = patchpix[x, y]
|
||||||
|
if ptc_msk[3] > 0:
|
||||||
|
oc = rg_pix[x, y]
|
||||||
|
nc = (oc[0], oc[1], oc[2], ptc_msk[3])
|
||||||
|
lp_pix[x, y] = nc
|
||||||
|
|
||||||
|
layerpatch = layerpatch.rotate(randrange(0, 360), expand=True)
|
||||||
|
|
||||||
|
lx = randrange(self._imgsize - layerpatch.width)
|
||||||
|
ly = randrange(self._imgsize - layerpatch.height)
|
||||||
|
cmpl.alpha_composite(layerpatch, (lx, ly))
|
||||||
|
|
||||||
# Merge the images
|
# Merge the images
|
||||||
cmpl.alpha_composite(self._tile)
|
cmpl.alpha_composite(self._tile)
|
||||||
@ -153,10 +183,21 @@ class mstr_photogen:
|
|||||||
if c[3] == 0:
|
if c[3] == 0:
|
||||||
corrpix[x,y] = (0,0,0,0)
|
corrpix[x,y] = (0,0,0,0)
|
||||||
|
|
||||||
|
# One more thing...
|
||||||
|
mstr_msg("photogen", "Adding features to layers")
|
||||||
|
self.addTreesToFeatures(layers)
|
||||||
|
|
||||||
|
# Throw missing buildings on top
|
||||||
|
lyr = 0
|
||||||
|
for l in layers:
|
||||||
|
if self._lyrnames[lyr] == "building":
|
||||||
|
self._tile.alpha_composite(l)
|
||||||
|
lyr = lyr + 1
|
||||||
|
|
||||||
# We are now in posession of the final image.
|
# We are now in posession of the final image.
|
||||||
|
|
||||||
# Contrast
|
# Contrast
|
||||||
self._tile = ImageEnhance.Contrast(self._tile).enhance(1)
|
#self._tile = ImageEnhance.Contrast(self._tile).enhance(0.1)
|
||||||
|
|
||||||
# This we can save accordingly.
|
# This we can save accordingly.
|
||||||
self._tile.save(mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._ty) + "_" + str(self._tx) + ".png")
|
self._tile.save(mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._ty) + "_" + str(self._tx) + ".png")
|
||||||
@ -191,6 +232,172 @@ class mstr_photogen:
|
|||||||
nrmimg.save(nrmfln)
|
nrmimg.save(nrmfln)
|
||||||
|
|
||||||
|
|
||||||
|
# Generates some random tree.
|
||||||
|
# We will now move away from using pre-made trees...
|
||||||
|
# they didn't look so great
|
||||||
|
def generate_tree(self):
|
||||||
|
sx = randrange(18, 31)
|
||||||
|
sy = randrange(18, 31)
|
||||||
|
|
||||||
|
treepoly = Image.new("RGBA", (sx, sy))
|
||||||
|
draw = ImageDraw.Draw(treepoly)
|
||||||
|
|
||||||
|
draw.ellipse((4, 4, sx - 4, sy - 4), fill="black")
|
||||||
|
|
||||||
|
tree = Image.new("RGBA", (sx, sy))
|
||||||
|
treepx = tree.load()
|
||||||
|
maskpx = treepoly.load()
|
||||||
|
|
||||||
|
# How many tree points do we want?
|
||||||
|
treepts = 75
|
||||||
|
# How many of those have been drawn?
|
||||||
|
ptsdrawn = 0
|
||||||
|
|
||||||
|
bc = [
|
||||||
|
(36, 50, 52),
|
||||||
|
(30, 41, 39),
|
||||||
|
(32, 45, 37),
|
||||||
|
(32, 39, 49),
|
||||||
|
(33, 34, 40),
|
||||||
|
(44, 50, 53),
|
||||||
|
(40, 46, 48),
|
||||||
|
(14, 31, 38),
|
||||||
|
(17, 41, 33),
|
||||||
|
(39, 56, 35),
|
||||||
|
(51, 51, 42),
|
||||||
|
(12, 27, 31),
|
||||||
|
(45, 59, 48),
|
||||||
|
(37, 54, 29),
|
||||||
|
(59, 50, 34),
|
||||||
|
(59, 59, 35),
|
||||||
|
(59, 51, 35),
|
||||||
|
(70, 72, 45),
|
||||||
|
(48, 59, 44),
|
||||||
|
(29, 47, 23),
|
||||||
|
(47, 61, 43),
|
||||||
|
(29, 68, 15),
|
||||||
|
(53, 77, 63),
|
||||||
|
(20, 68, 40)
|
||||||
|
]
|
||||||
|
|
||||||
|
bcp = randrange(0, len(bc))
|
||||||
|
|
||||||
|
treedraw = ImageDraw.Draw(tree)
|
||||||
|
while ptsdrawn < treepts + 1:
|
||||||
|
rx = randrange(0, sx)
|
||||||
|
ry = randrange(0, sy)
|
||||||
|
mp = maskpx[rx, ry]
|
||||||
|
if mp[3] > 0:
|
||||||
|
d = randrange(0, 51)
|
||||||
|
r = bc[bcp][0]
|
||||||
|
g = bc[bcp][1] + d
|
||||||
|
b = bc[bcp][2] + (d // 2)
|
||||||
|
a = randrange(170, 256)
|
||||||
|
c = (r, g, b, a)
|
||||||
|
ex = randrange(2, 5)
|
||||||
|
ey = randrange(2, 5)
|
||||||
|
treedraw.ellipse((rx - (ex // 2), ry - (ey // 2), rx + (ey // 2), ry + (ey // 2)), fill=c)
|
||||||
|
ptsdrawn = ptsdrawn + 1
|
||||||
|
|
||||||
|
for y in range(0, tree.height):
|
||||||
|
for x in range(0, tree.width):
|
||||||
|
tp = treepx[x, y]
|
||||||
|
diff = randrange(0, 31)
|
||||||
|
nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])
|
||||||
|
treepx[x, y] = nc
|
||||||
|
|
||||||
|
tree = tree.filter(ImageFilter.GaussianBlur(radius=0.5))
|
||||||
|
|
||||||
|
for y in range(0, tree.height):
|
||||||
|
for x in range(0, tree.width):
|
||||||
|
tp = treepx[x, y]
|
||||||
|
diff = randrange(0, 51)
|
||||||
|
nc = (tp[0] - diff, tp[1] - diff, tp[2] - diff, tp[3])
|
||||||
|
treepx[x, y] = nc
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
|
# This used to be in layergen and solves the problem of roads being rendered above trees.
|
||||||
|
# It is the only solution that worked, after some research.
|
||||||
|
def addTreesToFeatures(self, layers):
|
||||||
|
|
||||||
|
# Walk through list of layers to decide where to add the trees
|
||||||
|
curlyr = 0
|
||||||
|
for lyr in self._lyrnames:
|
||||||
|
# Add trees only in some features
|
||||||
|
if (lyr[0] == "landuse" and lyr[1] == "cemetery") or (
|
||||||
|
lyr[0] == "landuse" and lyr[1] == "residential") or (
|
||||||
|
lyr[0] == "leisure" and lyr[1] == "park"):
|
||||||
|
trees = Image.new("RGBA", (self._imgsize, self._imgsize))
|
||||||
|
amt = 4000
|
||||||
|
lyrmask = layers[curlyr].load() # We can use the layer image as alpha mask
|
||||||
|
for i in range(1, amt + 1):
|
||||||
|
lx = randrange(0, self._imgsize)
|
||||||
|
ly = randrange(0, self._imgsize)
|
||||||
|
lp = lyrmask[lx,ly]
|
||||||
|
if lp[3] > 0:
|
||||||
|
tree = self.generate_tree()
|
||||||
|
trees.alpha_composite(tree, (lx, ly))
|
||||||
|
|
||||||
|
tree_shadow = Image.new("RGBA", (self._imgsize, self._imgsize))
|
||||||
|
tree_pix = trees.load()
|
||||||
|
shadow_pix = tree_shadow.load()
|
||||||
|
for y in range(self._imgsize):
|
||||||
|
for x in range(self._imgsize):
|
||||||
|
tp = tree_pix[x, y]
|
||||||
|
if tp[3] > 0:
|
||||||
|
rndshd = randrange(5, 210)
|
||||||
|
sc = (0, 0, 0, rndshd)
|
||||||
|
if x + 8 < self._imgsize and y + 5 < self._imgsize:
|
||||||
|
shadow_pix[x + 8, y + 5] = sc
|
||||||
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
||||||
|
tree_shadow.alpha_composite(trees)
|
||||||
|
self._tile.alpha_composite(tree_shadow)
|
||||||
|
curlyr = curlyr + 1
|
||||||
|
|
||||||
|
# Reset
|
||||||
|
curlyr = 0
|
||||||
|
bldg = []
|
||||||
|
tilepix = self._tile.load()
|
||||||
|
for lyr in self._lyrnames:
|
||||||
|
if lyr[0] == "building":
|
||||||
|
bldg.append(curlyr)
|
||||||
|
curlyr = curlyr + 1
|
||||||
|
|
||||||
|
for b in range(0, len(bldg)):
|
||||||
|
bldg_lyr = layers[bldg[b]].load()
|
||||||
|
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")
|
||||||
|
shdw_pix = shdw.load()
|
||||||
|
for y in range(0, self._imgsize):
|
||||||
|
for x in range(0, self._imgsize):
|
||||||
|
bpix = bldg_lyr[x,y]
|
||||||
|
spix = shdw_pix[x,y]
|
||||||
|
if bpix[3] > 0 and spix[0] == 255:
|
||||||
|
tilepix[x,y] = ( bpix[0], bpix[1], bpix[2], bpix[3] )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Correct some layer issues
|
||||||
|
def correctLayerIssues(self, layers):
|
||||||
|
|
||||||
|
# First the residential/forest dilemma
|
||||||
|
residential = 0
|
||||||
|
forest = 0
|
||||||
|
|
||||||
|
curlyr = 0
|
||||||
|
for lyr in self._lyrnames:
|
||||||
|
if lyr[0] == "landuse" and lyr[1] == "residential":
|
||||||
|
residential=curlyr
|
||||||
|
if lyr[0] == "landuse" and lyr[1] == "forest":
|
||||||
|
forest = curlyr
|
||||||
|
curlyr = curlyr+1
|
||||||
|
|
||||||
|
layers[forest].alpha_composite(layers[residential])
|
||||||
|
|
||||||
|
return layers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# This checks the final image for empty patches. Should one be
|
# This checks the final image for empty patches. Should one be
|
||||||
|
33
tileinfo.py
33
tileinfo.py
@ -29,7 +29,6 @@ class mstr_tileinfo:
|
|||||||
#self._adjfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/adjinfo"
|
#self._adjfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/adjinfo"
|
||||||
self._cplfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/cplinfo"
|
self._cplfile = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/cplinfo"
|
||||||
self.createDataFile()
|
self.createDataFile()
|
||||||
self.createCompletionFile()
|
|
||||||
|
|
||||||
|
|
||||||
def createDataFile(self):
|
def createDataFile(self):
|
||||||
@ -37,15 +36,8 @@ class mstr_tileinfo:
|
|||||||
open(self._adjfile, 'a').close()
|
open(self._adjfile, 'a').close()
|
||||||
|
|
||||||
|
|
||||||
def createCompletionFile(self):
|
def add_adjacency_data(self, tag, value, source, adj):
|
||||||
if os.path.isfile(self._cplfile) == False:
|
|
||||||
open(self._cplfile, 'a').close()
|
|
||||||
|
|
||||||
|
|
||||||
def add_adjacency_data(self, tv, th, tag, value, source, adj):
|
|
||||||
line = ""
|
line = ""
|
||||||
line = line + str(tv) + " "
|
|
||||||
line = line + str(th) + " "
|
|
||||||
line = line + tag + " "
|
line = line + tag + " "
|
||||||
line = line + value + " "
|
line = line + value + " "
|
||||||
line = line + str(source) + " "
|
line = line + str(source) + " "
|
||||||
@ -55,19 +47,6 @@ class mstr_tileinfo:
|
|||||||
textfile.write(line)
|
textfile.write(line)
|
||||||
|
|
||||||
|
|
||||||
def add_completion_data(self, tv, th, tag, value, source, adj):
|
|
||||||
line = ""
|
|
||||||
line = line + str(tv) + " "
|
|
||||||
line = line + str(th) + " "
|
|
||||||
line = line + tag + " "
|
|
||||||
line = line + value + " "
|
|
||||||
line = line + str(source) + " "
|
|
||||||
line = line + str(adj) + "\n"
|
|
||||||
|
|
||||||
with open(self._cplfile, 'a') as textfile:
|
|
||||||
textfile.write(line)
|
|
||||||
|
|
||||||
|
|
||||||
def get_adjacency_for_tag_and_value(self, tv, th, tag, value):
|
def get_adjacency_for_tag_and_value(self, tv, th, tag, value):
|
||||||
adj = []
|
adj = []
|
||||||
fnlines = []
|
fnlines = []
|
||||||
@ -78,11 +57,10 @@ class mstr_tileinfo:
|
|||||||
|
|
||||||
for ln in fnlines:
|
for ln in fnlines:
|
||||||
l = ln.split(" ")
|
l = ln.split(" ")
|
||||||
if int(l[0]) == tv and int(l[1]) == th:
|
if l[0] == tag and l[1] == value:
|
||||||
if l[2] == tag and l[3] == value:
|
l[3] = l[3].replace("\n", "")
|
||||||
l[5] = l[5].replace("\n", "")
|
adj.append(l[2])
|
||||||
adj.append(int(l[4]))
|
adj.append(l[3])
|
||||||
adj.append(l[5])
|
|
||||||
break
|
break
|
||||||
|
|
||||||
return adj
|
return adj
|
||||||
@ -243,3 +221,4 @@ class mstr_tileinfo:
|
|||||||
if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])
|
if abs(numbers[1]) >= 100 : fstr = fstr + str(numbers[1])
|
||||||
|
|
||||||
return fstr
|
return fstr
|
||||||
|
|
||||||
|
240
tileprep.py
240
tileprep.py
@ -14,6 +14,7 @@
|
|||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
|
from os import MFD_ALLOW_SEALING
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from osmxml import *
|
from osmxml import *
|
||||||
@ -34,7 +35,7 @@ class mstr_tileprep:
|
|||||||
self._tag = tag
|
self._tag = tag
|
||||||
self._value = value
|
self._value = value
|
||||||
self._edges = "" # To be filled by _edgeDetect call
|
self._edges = "" # To be filled by _edgeDetect call
|
||||||
self._source = -1
|
self._source = ""
|
||||||
self._mask = mask
|
self._mask = mask
|
||||||
latlngfld = xplane_latlng_folder([lat, lng])
|
latlngfld = xplane_latlng_folder([lat, lng])
|
||||||
self._tileinfo = mstr_tileinfo(lat, lng, v, h, latlngfld)
|
self._tileinfo = mstr_tileinfo(lat, lng, v, h, latlngfld)
|
||||||
@ -53,8 +54,8 @@ class mstr_tileprep:
|
|||||||
return srcfld
|
return srcfld
|
||||||
|
|
||||||
|
|
||||||
# Prepare the tile accordingly
|
# Use the mask to determine the edges
|
||||||
def _prepareTile(self):
|
def _determineEdges(self):
|
||||||
# Load the mask pixels
|
# Load the mask pixels
|
||||||
mp = self._mask.load()
|
mp = self._mask.load()
|
||||||
imgsize = self._mask.width
|
imgsize = self._mask.width
|
||||||
@ -69,29 +70,29 @@ class mstr_tileprep:
|
|||||||
al=False
|
al=False
|
||||||
|
|
||||||
# Top scan
|
# Top scan
|
||||||
for i in range(0, imgsize-1):
|
for i in range(0, imgsize):
|
||||||
p = mp[i,0]
|
p = mp[i,0]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
at=True
|
at=True
|
||||||
break
|
break
|
||||||
|
|
||||||
# Right scan
|
# Right scan
|
||||||
for i in range(0, imgsize-1):
|
for i in range(0, imgsize):
|
||||||
p = mp[imgsize-1,i]
|
p = mp[imgsize-1,i]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
ar=True
|
ar=True
|
||||||
break
|
break
|
||||||
|
|
||||||
# Bottom scan
|
# Bottom scan
|
||||||
for i in range(0, imgsize-1):
|
for i in range(0, imgsize):
|
||||||
p = mp[i,imgsize-1]
|
p = mp[i,imgsize-1]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
ab=True
|
ab=True
|
||||||
break
|
break
|
||||||
|
|
||||||
# Left scan
|
# Left scan
|
||||||
for i in range(0, imgsize-1):
|
for i in range(0, imgsize):
|
||||||
p = mp[1,i]
|
p = mp[0,i]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
al=True
|
al=True
|
||||||
break
|
break
|
||||||
@ -103,48 +104,187 @@ class mstr_tileprep:
|
|||||||
if ab==True: adjstr = adjstr + "b"
|
if ab==True: adjstr = adjstr + "b"
|
||||||
if al==True: adjstr = adjstr + "l"
|
if al==True: adjstr = adjstr + "l"
|
||||||
|
|
||||||
# Now find out of there is a source from any adjacent tile
|
# We will now write this down first, without a source being selected
|
||||||
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
|
|
||||||
if adjstr != "":
|
if adjstr != "":
|
||||||
if self._is_completion == False:
|
self._tileinfo.add_adjacency_data(self._tag, self._value, "0", adjstr)
|
||||||
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")
|
|
||||||
|
|
||||||
|
# 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
|
@ -1,3 +1,4 @@
|
|||||||
|
from random import randrange
|
||||||
|
|
||||||
# -------------------------------------------------------------------
|
# -------------------------------------------------------------------
|
||||||
# ORTHOGRAPHIC
|
# ORTHOGRAPHIC
|
||||||
@ -73,7 +74,7 @@ class mstr_xp_normalmap:
|
|||||||
# Resize original
|
# Resize original
|
||||||
image = image.resize((int(mstr_photores/4), int(mstr_photores/4)), Image.Resampling.BILINEAR)
|
image = image.resize((int(mstr_photores/4), int(mstr_photores/4)), Image.Resampling.BILINEAR)
|
||||||
|
|
||||||
nmp = Image.new("RGBA", (image.width, image.height), (128,128,1,1))
|
nmp = Image.new("RGBA", (image.width, image.height), (128,128,0,0))
|
||||||
|
|
||||||
if water: nmp = Image.new("RGBA", (image.width, image.height), (128, 128, 255, 0))
|
if water: nmp = Image.new("RGBA", (image.width, image.height), (128, 128, 255, 0))
|
||||||
|
|
||||||
@ -83,6 +84,7 @@ class mstr_xp_normalmap:
|
|||||||
# Let's try some shenanigans
|
# Let's try some shenanigans
|
||||||
w = image.width
|
w = image.width
|
||||||
h = image.height
|
h = image.height
|
||||||
|
if not water:
|
||||||
for y in range(h):
|
for y in range(h):
|
||||||
for x in range(w):
|
for x in range(w):
|
||||||
p = org[x,y]
|
p = org[x,y]
|
||||||
@ -120,11 +122,24 @@ class mstr_xp_normalmap:
|
|||||||
nrm[1] = abs(nrm[1])
|
nrm[1] = abs(nrm[1])
|
||||||
|
|
||||||
# Set pixel
|
# Set pixel
|
||||||
if water:
|
|
||||||
nmp_pix[x,y] = (int(self.map_component(nrm[0])), int(self.map_component(nrm[1])), int(self.map_component(nrm[2])), int(self.map_component(nrm[2])))
|
|
||||||
if not water:
|
|
||||||
nmp_pix[x,y] = (int(self.map_component(nrm[0])), int(self.map_component(nrm[1])), 255 - int(self.map_component(nrm[2])), 1)
|
nmp_pix[x,y] = (int(self.map_component(nrm[0])), int(self.map_component(nrm[1])), 255 - int(self.map_component(nrm[2])), 1)
|
||||||
|
|
||||||
|
# Previous code produced bad and eerie looking lines at the border of the image. Let's have a go with this.
|
||||||
|
if water:
|
||||||
|
for y in range(h):
|
||||||
|
for x in range(w):
|
||||||
|
p = org[x,y]
|
||||||
|
if p[3] > 0:
|
||||||
|
wr = randrange(116, 141)
|
||||||
|
wg = randrange(111, 139)
|
||||||
|
wb = 255
|
||||||
|
if x == 0 or x == w-1: wb = 0
|
||||||
|
if y == 0 or y == h-1: wb = 0
|
||||||
|
wa = p[3]
|
||||||
|
c = (wr, wg, wb, wa)
|
||||||
|
nmp_pix[x,y] = c
|
||||||
|
|
||||||
|
|
||||||
mstr_msg("xp_normalmap", "[X-Plane] Normal map generated")
|
mstr_msg("xp_normalmap", "[X-Plane] Normal map generated")
|
||||||
return nmp
|
return nmp
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user