("natural", "wetland", "natural", "wetland"),
("natural", "scrub", "natural", "scrub"),
("natural", "heath", "natural", "heath"),
+ ("natural", "sand", "natural", "sand"),
+ ("natural", "desert", "natural", "desert"),
# Z-Order 3
("natural", "water", "natural", "water"),
("natural", "bay", "natural", "beach"),
("building", "terrace", "building", "industrial"),
("building", "hangar", "building", "industrial"),
("building", "school", "building", "common"),
- ("building", "yes", "building", "common")
+ ("building", "yes", "building", "common"),
+ ("place", "sea", "natural", "sea"),
+ ("place", "ocean", "natural", "sea")
]
("building", "terrace", 1),
("building", "hangar", 1),
("building", "school", 1),
- ("building", "yes", 1)
+ ("building", "yes", 1),
+ ("place", "sea", 1),
+ ("place", "ocean", 1)
]
self._longitude = lng
self._lng_number = lngnum
self._layerborder = -1
- self._tiledb = mstr_tiledb(lat, lng)
- self._tiledb.create_tables()
self._is_completion = is_completion
# Define layer size depending on what is wanted
self._imgsize = 0
def set_latlng_folder(self, latlngfld):
self._latlngfld = latlngfld
+ # Open DB
+ def open_db(self):
+ self._tiledb = mstr_tiledb(self._latitude, self._longitude, self._latlngfld)
+ self._tiledb.create_tables()
+
# This generates a "border" image, for example farmland usually has a small space of grass
# before the actual crop of farm field itself. This generates this "border" layer,
# and returns it.
# on what they are.
for i in mstr_mask_blur:
if i[0] == self._tag and i[1] == self._value:
- osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))
- break
+ if self._tag != "place" and (self._value != "sea" or self._value != "ocean"):
+ osm_mask = osm_mask.filter(ImageFilter.BoxBlur(radius=i[2]))
+ break
# Begin producing a largely random image
samples = 250 # <- We need this in a moment
layer_border = self.genborder(osm_edge, "landuse", "meadow")
layer_comp.alpha_composite(layer_border)
- # Edges for waters
- if self._tag == "natural" and self._value == "water":
- osm_edge = osm_mask.filter(ImageFilter.FIND_EDGES)
- osm_edge = osm_edge.filter(ImageFilter.MaxFilter)
- osm_edge = osm_edge.filter(ImageFilter.GaussianBlur(radius=2))
- layer_comp.alpha_composite(osm_edge)
-
# Store layer
if self._is_completion == False:
layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
mstr_msg("layergen", "Layer image finalized and saved.")
+ # Depending on if scenery for XP should be made, AND if normal maps should be made, we would
+ # need to make them at this exact point
+ if mstr_xp_genscenery == True:
+ if mstr_xp_generate_normal_maps == True:
+ nm = False
+ for n in mstr_xp_normal_maps:
+ if n[0] == self._tag and n[1] == self._value:
+ nm = True
+ break
+ if nm == True:
+ nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)
+ nrm.build_normalmap()
+
+
# Let's try our hand at pseudo shadows
if mstr_shadow_enabled == True:
if mstr_shadow_shift >= 2:
# need to make them at this exact point
if mstr_xp_genscenery == True:
if mstr_xp_generate_normal_maps == True:
- nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)
- nrm.build_normalmap()
+ nm = False
+ for n in mstr_xp_normal_maps:
+ if n[0] == self._tag and n[1] == self._value:
+ nm = True
+ break
+ if nm == True:
+ nrm = mstr_xp_normalmap(self._latitude, self._longitude, self._tag, self._value, self._lat_number, self._lng_number, self._latlngfld)
+ nrm.build_normalmap()
from photogen import *
from osmxml import *
from tilegen import *
+from xp_dsfgen import *
# The main class which handles the rest
mstr_msg("orthographic", "Created Tiles sub folder: " + self._latlngfld)
# Generate the orthos folder
- if not os.path.exists(self._output + "/Tiles/z_orthograpic_" + self._latlngfld + "/orthos"):
- os.makedirs(self._output + "/Tiles/z_orthograpic_" + self._latlngfld +"/orthos")
+ if not os.path.exists(self._output + "/Tiles/z_orthographic_" + self._latlngfld + "/orthos"):
+ os.makedirs(self._output + "/Tiles/z_orthographic_" + self._latlngfld +"/orthos")
mstr_msg("orthographic", "Created tile orthos folder")
if mstr_xp_genscenery == True:
- if not os.path.exists(self._output + "/Tiles/z_orthograpic_" + self._latlngfld + "/terrain"):
- os.makedirs(self._output + "/Tiles/z_orthograpic_" + self._latlngfld + "/terrain")
+ if not os.path.exists(self._output + "/Tiles/z_orthographic_" + self._latlngfld + "/terrain"):
+ os.makedirs(self._output + "/Tiles/z_orthographic_" + self._latlngfld + "/terrain")
mstr_msg("orthographic", "Created X-Plane tile terrain folder")
if mstr_xp_generate_normal_maps == True:
- if not os.path.exists(self._output + "/Tiles/z_orthograpic_" + self._latlngfld + "/normals"):
- os.makedirs(self._output + "/Tiles/z_orthograpic_" + self._latlngfld + "/normals")
+ if not os.path.exists(self._output + "/Tiles/z_orthographic_" + self._latlngfld + "/normals"):
+ os.makedirs(self._output + "/Tiles/z_orthographic_" + self._latlngfld + "/normals")
mstr_msg("orthographic", "Created X-Plane tile normals folder")
# The tile is constructed of many smaller parts. We walk through the
mstr_msg("orthographic", "Adjusted bounding box for XML object")
# Determine what to do... maybe work was interrupted
- if os.path.isfile(mstr_datafolder + "Tiles/" + self._latlngfld + "/orthos/" + str(cur_tile_y) + "_" + str(cur_tile_x) + ".jpg") == False:
+ if os.path.isfile(mstr_datafolder + "Tiles/" + self._latlngfld + "/orthos/" + str(cur_tile_y) + "_" + str(cur_tile_x) + ".dds") == False:
# Let the user know
mstr_msg("orthographic", "Generating missing orthophoto " + str(cur_tile_y) + "-" + str(cur_tile_x))
lg = mstr_layergen(layer[0], layer[1], self._lat, cur_tile_y, self._long, cur_tile_x, layer[2])
lg.set_max_latlng_tile(maxlatlng)
lg.set_latlng_folder(self._latlngfld)
+ lg.open_db()
lg.genlayer()
curlyr = curlyr+1
mstr_msg("orthographic", "All layers created")
# We should have all layers now.
# Snap a photo with our satellite :)
mstr_msg("orthographic", "Generating ortho photo")
- pg = mstr_photogen(self._lat, self._long, cur_tile_y, cur_tile_x, maxlatlng[0], maxlatlng[1])
+ pg = mstr_photogen(self._lat, self._long, cur_tile_y, cur_tile_x, maxlatlng[0], maxlatlng[1])
pg.genphoto()
mstr_msg("orthographic", " -- Ortho photo generated -- ")
- if mstr_xp_genscenery == True:
- xp_datagroup = xp_datagroup + 1
print("")
print("")
mstr_msg("orthographic", "Generation of all tiles completed!")
+
+ # Complete scenery
+ if mstr_xp_genscenery == True:
+ dsf = mstr_xp_dsfgen(self._lat, self._long, mlat, mlng, self._vstep)
+ dsf.build_dsf_for_tile()
+ mstr_msg("orthographic", "X-Plane scenery completed")
+
+ mstr_msg("orthographic", "Final step completed.")
+ mstr_msg("orthographic", "Tile data in: " + self._output + "/Tiles/z_orthographic_" + self._latlngfld)
+ print("")
+ mstr_msg("orthographic", "Thanks for using Orthographic! -- Best, Marcus")
+ print("")
+
+ # Let's leave this out for the moment
+ """
mstr_msg("orthographic", "Generating ZL16 tiles and keeping airport tiles")
tg = mstr_tilegen(self._lat, self._lng, self._vstep, top_lat, top_lng)
tg.genTiles()
print("")
mstr_msg("orthographic", "Thanks for using Orthographic! -- Best, Marcus")
print("")
+ """
# Generate the layer as if it were part of the OSM data
lg = mstr_layergen(tag, value, self._lat, self._ty, self._lng, self._tx, False, is_completion=True)
lg.set_max_latlng_tile(self._maxlatlng)
+ lg.set_latlng_folder(self._latlngfld)
+ lg.open_db()
lg.genlayer()
# Load the image
self._tile = completion
+ # There may be some tiles that have a larger sea or even an ocean in them - these need to be
+ # removed from the final tile
+ ocean_pix = self._tile.load()
+ for y in range(self._tile.width):
+ for x in range(self._tile.height):
+ p = ocean_pix[x,y]
+ if p[0] == 255 and p[1] == 0 and p[2] == 255:
+ t = (0,0,0,0)
+ ocean_pix[x,y] = t
+
# We are now in posession of the final image.
# Scale to correct size.
# This we can save accordingly.
self._tile.convert('RGB').save(mstr_datafolder + "Tiles/z_orthographic_" + self._latlngfld + "/orthos/" + str(self._ty) + "_" + str(self._tx) + ".png")
+
# Now we convert this into a DDS
with image.Image(filename=mstr_datafolder + "Tiles/z_orthographic_" + self._latlngfld + "/orthos/" + str(self._ty) + "_" + str(self._tx) + ".png") as img:
img.compression = "dxt1"
- img.save(mstr_datafolder + "Tiles/z_orthographic_" + self._latlngfld + "/orthos/" + str(self._ty) + "_" + str(self._tx) + ".dds")
+ img.save(filename=mstr_datafolder + "Tiles/z_orthographic_" + self._latlngfld + "/orthos/" + str(self._ty) + "_" + str(self._tx) + ".dds")
# TODO: CUT OUT OCEANS AND SEAS IN DDS
os.remove(mstr_datafolder + "Tiles/z_orthographic_" + self._latlngfld + "/orthos/" + str(self._ty) + "_" + str(self._tx) + ".png")
+
+
# This checks the final image for empty patches. Should one be
# found, we will generate something to fill the gap. If this is
# the case, we will also note this in the database for the tile,
from log import *
class mstr_tiledb:
- def __init__(self, lat, lng):
+ def __init__(self, lat, lng, latlngfld):
# Note coords
self._latitude = lat
self._longitude = lng
+ self._latlngfld = latlngfld
# The db file will be created, should it not exist
- self._conn = sqlite3.connect(mstr_datafolder + "Tiles/" + str(self._latitude) + "_" + str(self._longitude) + "/data.db")
+ self._conn = sqlite3.connect(mstr_datafolder + "Tiles/z_orthographic_" + latlngfld + "/data.db")
self._crs = self._conn.cursor()
#mstr_msg("tiledb", "Database object initiated")
self.convert_dsf_text()
mstr_msg("xp_dsfgen", "[X-Plane] DSF for tile completed")
-
-
-# Testing
-dsf = mstr_xp_dsfgen(51, 7, 101, 63, 0.01010)
-dsf.build_dsf_for_tile()
\ No newline at end of file
# then provide it
def load_layer(self):
qtr = int(mstr_photores / 4)
- image = Image.open(mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._lng) + "_" + self._tag + "_" + self._value + "_layer.png")
+ image = Image.open(mstr_datafolder + "_cache/" + str(self._lat) + "-" + str(self._tv) + "_" + str(self._lng) + "-" + str(self._th) + "_" + self._tag + "-" + self._value + "_layer.png")
image = image.resize((qtr,qtr), Image.Resampling.LANCZOS)
mstr_msg("xp_normalmap", "[X-Plane] Layer image loaded")
return image
# A few mathematical calls we need
# --------------------------------------------------------
- def intensity(pixel):
+ def intensity(self, pixel):
avg = (pixel[0] + pixel[1] + pixel[2]) / 3
- pavg = 255.0 / avg
+ if avg > 0:
+ pavg = 255.0 / avg
+ else:
+ pavg = 0
return pavg
- def clamp(px, mpx):
+ def clamp(self, px, mpx):
if px > mpx-1:
return mpx-1
else:
return px
- def map_component(px):
+ def map_component(self, px):
return (px + 1.0) * (255.0 / 2.0)
- def normalize_vector(v):
+ def normalize_vector(self, v):
vc = np.array([v[0], v[1], v[2]])
norm = np.linalg.norm(vc)
nv = vc / norm
# The Big Mac. Generate the normal map
def generate_normal_map_for_layer(self, image):
mstr_msg("xp_normalmap", "[X-Plane] Beginning normal map generation")
- nmp = Image.new("RGBA", (image.width, image.height), (128,128,255,255))
+ #nmp = Image.new("RGBA", (image.width, image.height), (128,128,255,255))
+ nmp = Image.new("RGBA", (image.width, image.height), (0,0,0,0))
org = image.load()
nmp_pix = nmp.load()
a = v * 255.0
alpha = int(a)
+
# Let's try some shenanigans
- for y in range(image.width):
- for x in range(image.height):
- # Neighboring pixels
- px_t = org[ self.clamp(x, image.width), self.clamp(y+1, image.height) ]
- px_tr = org[ self.clamp(x+1, image.width), self.clamp(y+1, image.height) ]
- px_r = org[ self.clamp(x+1, image.width), self.clamp(y, image.height) ]
- px_br = org[ self.clamp(x+1, image.width), self.clamp(y+1, image.height) ]
- px_b = org[ self.clamp(x, image.width), self.clamp(y-1, image.height) ]
- px_bl = org[ self.clamp(x-1, image.width), self.clamp(y-1, image.height) ]
- px_l = org[ self.clamp(x-1, image.width), self.clamp(y, image.height) ]
- px_tl = org[ self.clamp(x-1, image.width), self.clamp(y+1, image.height) ]
-
- # Intensities of pixels
- it_t = self.intensity(px_t)
- it_tr = self.intensity(px_tr)
- it_r = self.intensity(px_r)
- it_br = self.intensity(px_br)
- it_b = self.intensity(px_b)
- it_bl = self.intensity(px_bl)
- it_l = self.intensity(px_l)
- it_tl = self.intensity(px_tl)
-
- # Sobel filter
- dx = (it_tr + 2.0 * it_r + it_br) - (it_tl + 2.0 * it_l + it_bl)
- dy = (it_bl + 2.0 * it_b + it_br) - (it_tl + 2.0 * it_t + it_tr)
- dz = 10 # This is usually a good value for strength
- v = (dx, dy, dz)
- nrm = self.normalize_vector(v)
-
- # Invert height for our Orthos
- if nrm[1] > 0:
- nrm[1] = 0 - (abs(nrm[1]))
- else:
- nrm[1] = abs(nrm[1])
-
- # Set pixel
- nmp_pix[x,y] = (int(self.map_component(nrm[0])), int(self.map_component(nrm[1])), int(self.map_component(nrm[2])), alpha)
+ w = image.width
+ h = image.height
+ for y in range(h):
+ for x in range(w):
+ p = org[x,y]
+ if p[3] > 0: # Only do something if there is something to do in layer
+ # Neighboring pixels
+ px_t = org[ self.clamp(x, w), self.clamp(y+1, h) ]
+ px_tr = org[ self.clamp(x+1, w), self.clamp(y+1, h) ]
+ px_r = org[ self.clamp(x+1, w), self.clamp(y, h) ]
+ px_br = org[ self.clamp(x+1, w), self.clamp(y+1, h) ]
+ px_b = org[ self.clamp(x, w), self.clamp(y-1, h) ]
+ px_bl = org[ self.clamp(x-1, w), self.clamp(y-1, h) ]
+ px_l = org[ self.clamp(x-1, w), self.clamp(y, h) ]
+ px_tl = org[ self.clamp(x-1, w), self.clamp(y+1, h) ]
+
+ # Intensities of pixels
+ it_t = self.intensity(px_t)
+ it_tr = self.intensity(px_tr)
+ it_r = self.intensity(px_r)
+ it_br = self.intensity(px_br)
+ it_b = self.intensity(px_b)
+ it_bl = self.intensity(px_bl)
+ it_l = self.intensity(px_l)
+ it_tl = self.intensity(px_tl)
+
+ # Sobel filter
+ dx = (it_tr + 2.0 * it_r + it_br) - (it_tl + 2.0 * it_l + it_bl)
+ dy = (it_bl + 2.0 * it_b + it_br) - (it_tl + 2.0 * it_t + it_tr)
+ dz = 10 # This is usually a good value for strength
+ v = (dx, dy, dz)
+ nrm = self.normalize_vector(v)
+
+ # Invert height for our Orthos
+ if nrm[1] > 0:
+ nrm[1] = 0 - (abs(nrm[1]))
+ else:
+ nrm[1] = abs(nrm[1])
+
+ # Set pixel
+ nmp_pix[x,y] = (int(self.map_component(nrm[0])), int(self.map_component(nrm[1])), int(self.map_component(nrm[2])), alpha)
mstr_msg("xp_normalmap", "[X-Plane] Normal map generated")
return nmp