Last minor adjustments and a needed feature for PBF generation (needed for a later stage)
This commit is contained in:
parent
817d65639d
commit
bd2594221d
@ -75,6 +75,7 @@ mstr_xp_scn_normalmaps = True
|
||||
mstr_xp_meshtool = "/home/marcus/Developer/Projects/orthographic/bin/MeshTool"
|
||||
mstr_xp_ddstool = "/home/marcus/Developer/Projects/orthographic/bin/DDSTool"
|
||||
mstr_xp_xessrc = "https://dev.x-plane.com/update/misc/MeshTool/"
|
||||
mstr_xp_floor_height = 2.8 # 2.5m ceiling height + 30cm concrete per floor
|
||||
|
||||
# If you set the above to true, you can define for which features you
|
||||
# want to generate normal maps for. The below is my recommendation for
|
||||
|
@ -1123,7 +1123,7 @@ class mstr_layergen:
|
||||
ptc_src.append(Image.open(p))
|
||||
|
||||
osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )
|
||||
lyr_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
||||
#lyr_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
|
||||
|
||||
for i in mstr_mask_blur:
|
||||
if i[0] == self._tag and i[1] == self._value:
|
||||
@ -1147,12 +1147,12 @@ class mstr_layergen:
|
||||
|
||||
adj_image.alpha_composite( brd_src )
|
||||
|
||||
lyr_pix = lyr_mask.load()
|
||||
#lyr_pix = lyr_mask.load()
|
||||
for y in range(self._imgsize):
|
||||
for x in range(self._imgsize):
|
||||
if lyr_pix[x, y][3] > 0:
|
||||
if mask_pix[x, y][3] > 0:
|
||||
rgb=adj_pix[x,y]
|
||||
a=lyr_pix[x,y]
|
||||
a=mask_pix[x,y]
|
||||
adj_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])
|
||||
|
||||
# Up until here we mimiced the exact same behavior as layergen. However, now
|
||||
|
16
maskgen.py
16
maskgen.py
@ -13,12 +13,6 @@
|
||||
# that this part of the code is the most crucial one, as the other
|
||||
# classes involved rely on what this code is doing, and by extension,
|
||||
# generating.
|
||||
#
|
||||
# The PNG generated will be used in this progression:
|
||||
# - Generate mask from OSM (here)
|
||||
# - Generate colored photo layer from this mask, for example for
|
||||
# landuse: forest
|
||||
# - Compile actual satellite aerial
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
import math
|
||||
@ -83,9 +77,7 @@ class mstr_maskgen:
|
||||
# Builds the required mask
|
||||
def _build_mask(self):
|
||||
# Generate empty image
|
||||
imgsize = 0
|
||||
if mstr_photores == 2048: imgsize=2048
|
||||
if mstr_photores == 4096: imgsize=6000
|
||||
imgsize = 2048
|
||||
mask_img = Image.new("RGBA", (imgsize, imgsize))
|
||||
|
||||
tilexml = mstr_datafolder + "_cache/tile.xml"
|
||||
@ -119,7 +111,7 @@ class mstr_maskgen:
|
||||
for d in way:
|
||||
if d[0] == w[0]:
|
||||
if self._tag == "building" and bld_levels == 0:
|
||||
bld_levels = xml.find_building_levels(tilexml, w[0])
|
||||
bld_levels = xml.find_building_levels(w[0])
|
||||
nd.append(d[1])
|
||||
frs.append(nd)
|
||||
# Scout through relations as these also make up map data
|
||||
@ -160,9 +152,7 @@ class mstr_maskgen:
|
||||
p_lng = self.project_pixel(latlng[1], bbox[3])
|
||||
pixlat = 0
|
||||
pixlng = 0
|
||||
pr = 0
|
||||
if mstr_photores == 2048: pr = 2048
|
||||
if mstr_photores == 4096: pr = 6000
|
||||
pr = 2048
|
||||
|
||||
# Draw pixels in direction according to latitude and longitude positions -
|
||||
|
||||
|
22
og.py
22
og.py
@ -22,7 +22,7 @@ from defines import *
|
||||
print(" ")
|
||||
print(" ---------------------------------------------------------------- ")
|
||||
print(" ORTHOGRAPHIC: An ortho-photo generator, using real world data.")
|
||||
print(" Developed by MarStrMind - Code available on marstr.online")
|
||||
print(" Developed by MarStr - Code available on marstr.online")
|
||||
print(" ---------------------------------------------------------------- ")
|
||||
print(" ")
|
||||
|
||||
@ -30,9 +30,14 @@ print(" ")
|
||||
# Evaluate CLI arguments and process tile.
|
||||
|
||||
cli = False
|
||||
pbf = False
|
||||
|
||||
if len(sys.argv) == 3:
|
||||
cli = True
|
||||
|
||||
if len(sys.argv) == 4:
|
||||
pbf = True
|
||||
|
||||
# Only if we find enough arguments, proceed.
|
||||
if cli == True:
|
||||
lat = int(sys.argv[1])
|
||||
@ -44,7 +49,20 @@ if cli == True:
|
||||
og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd())
|
||||
og._buildTile()
|
||||
|
||||
else:
|
||||
|
||||
# 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:
|
||||
mstr_msg("_main", "Please provide Latitude and Longitude. Exiting.")
|
||||
print ("")
|
||||
|
||||
|
@ -77,6 +77,74 @@ class mstr_orthographic:
|
||||
return round(dm * 1000, 3)
|
||||
|
||||
|
||||
# In this case we only want to acquire PBF for a latitude and longitude. Normally
|
||||
# not needed for standard ortho generation.
|
||||
def _generateData(self):
|
||||
# The tile is constructed of many smaller parts. We walk through the
|
||||
# smallest possible, from which the bigger ones are later built.
|
||||
bb_lat = self._lat
|
||||
bb_lng = self._long
|
||||
bb_lat_edge = self._lat+self._vstep
|
||||
bb_lng_edge = self._long+mstr_zl_18
|
||||
cur_tile_x = 1
|
||||
cur_tile_y = 1
|
||||
osmxml = mstr_osmxml(0,0)
|
||||
mstr_msg("orthographic", "Set initial coordinates and bounding box for OSM acquisition")
|
||||
|
||||
# The highest encountered tile numbers
|
||||
# This is needed to produce the zoom level 16 images
|
||||
top_lat = 1
|
||||
top_lng = 1
|
||||
|
||||
# We need to know the highest possible latitude and longitude tile numbers,
|
||||
# in case we render at the edge
|
||||
mlat = 1
|
||||
mlng = 1
|
||||
while bb_lat < self._lat + 1:
|
||||
bb_lat = bb_lat + self._vstep
|
||||
mlat = mlat+1
|
||||
while bb_lng < self._long + 1:
|
||||
bb_lng = bb_lng + mstr_zl_18
|
||||
mlng = mlng+1
|
||||
mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))
|
||||
maxlatlng = [ mlat, mlng ]
|
||||
|
||||
# Reset these two
|
||||
bb_lat = self._lat
|
||||
bb_lng = self._long
|
||||
|
||||
# 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
|
||||
# only for the current processed part of the tile.
|
||||
for lat_grid in range(1, maxlatlng[0]+1):
|
||||
for lng_grid in range(1, maxlatlng[1]+1):
|
||||
# Adjust bounding box
|
||||
osmxml.adjust_bbox(bb_lat, bb_lng, bb_lat_edge, bb_lng_edge)
|
||||
|
||||
osmxml.generate_osm(cur_tile_y, cur_tile_x) # <- This acquires current OSM info
|
||||
|
||||
# Adjust longitude coordinates
|
||||
cur_tile_x = cur_tile_x+1
|
||||
bb_lng = bb_lng + mstr_zl_18
|
||||
bb_lng_edge = bb_lng_edge + mstr_zl_18
|
||||
mstr_msg("orthographic", "Adjustment of longitude performed")
|
||||
# Adjust peak longitude tile number
|
||||
if cur_tile_x > top_lng:
|
||||
top_lng = cur_tile_x
|
||||
|
||||
# Adjust latitude and all other values when we get here
|
||||
cur_tile_y = cur_tile_y+1
|
||||
cur_tile_x = 1
|
||||
bb_lng = self._long
|
||||
bb_lng_edge = self._long + mstr_zl_18
|
||||
bb_lat = bb_lat + self._vstep
|
||||
bb_lat_edge = bb_lat_edge + self._vstep
|
||||
mstr_msg("orthographic", "Adjustment of latitude performed")
|
||||
# Adjust peak latitude number
|
||||
if cur_tile_y > top_lat:
|
||||
top_lat = cur_tile_y
|
||||
|
||||
|
||||
# Builds and processes the tile with everything required, in one call.
|
||||
def _buildTile(self):
|
||||
mstr_msg("orthographic", "Beginning construction of tile")
|
||||
@ -163,9 +231,6 @@ class mstr_orthographic:
|
||||
bb_lat = self._lat
|
||||
bb_lng = self._long
|
||||
|
||||
# For X-Plane scenery generation
|
||||
xp_datagroup = 1
|
||||
|
||||
# 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
|
||||
# only for the current processed part of the tile.
|
||||
|
74
osmxml.py
74
osmxml.py
@ -36,6 +36,26 @@ class mstr_osmxml:
|
||||
self._curB_lng = round(lng_e, 4)
|
||||
|
||||
|
||||
def generate_osm(self, v, h, asobject=False):
|
||||
mstr_msg("osmxml", "Acquiring OSM data for " + str(self._lat)+","+str(self._lng)+" - "+str(self._curB_lat)+","+str(self._curB_lng))
|
||||
|
||||
# We will use our self-hosted API for this.
|
||||
data = {
|
||||
"bbox": {
|
||||
"lat": str(self._lat),
|
||||
"lng": str(self._lng),
|
||||
"lat_b": str(self._curB_lat),
|
||||
"lng_b": str(self._curB_lng)
|
||||
},
|
||||
"tile_lat": str(self._lat),
|
||||
"tile_lng": str(self._lng),
|
||||
"square_lat": str(v),
|
||||
"square_lng": str(h),
|
||||
"as_pbf": "true"
|
||||
}
|
||||
r = requests.post(mstr_osm_endpoint, json=data)
|
||||
|
||||
|
||||
# Acquire XMLs in chunks, then store them
|
||||
def acquire_osm(self, v, h, asobject=False):
|
||||
mstr_msg("osmxml", "Acquiring OSM data for " + str(self._lat)+","+str(self._lng)+" - "+str(self._curB_lat)+","+str(self._curB_lng))
|
||||
@ -152,9 +172,9 @@ class mstr_osmxml:
|
||||
|
||||
|
||||
# Find the levels of a building (for shadow rendering)
|
||||
def find_building_levels(self, xmlfile, way_id):
|
||||
lvl = 3 # Standard if we don't find anything else
|
||||
xml_doc = xml.dom.minidom.parse(xmlfile)
|
||||
def find_building_levels(self, way_id):
|
||||
lvl = 2 # Standard if we don't find anything else
|
||||
xml_doc = xml.dom.minidom.parse(mstr_datafolder + "_cache/tile.xml")
|
||||
wpdata = xml_doc.getElementsByTagName("way")
|
||||
for wp in wpdata:
|
||||
if wp.getAttribute("id") == way_id:
|
||||
@ -167,6 +187,54 @@ class mstr_osmxml:
|
||||
break
|
||||
return lvl
|
||||
|
||||
# Find minimum level of a building
|
||||
def find_building_minlevel(self, way_id):
|
||||
lvl = 0 # Standard if we don't find anything else
|
||||
xml_doc = xml.dom.minidom.parse(mstr_datafolder + "_cache/tile.xml")
|
||||
wpdata = xml_doc.getElementsByTagName("way")
|
||||
for wp in wpdata:
|
||||
if wp.getAttribute("id") == way_id:
|
||||
tags = wp.getElementsByTagName("tag")
|
||||
for tag in tags:
|
||||
a = tag.getAttribute("k")
|
||||
v = tag.getAttribute("v")
|
||||
if a == "building:min_level":
|
||||
lvl = int(v)
|
||||
break
|
||||
return lvl
|
||||
|
||||
# Find the roof shape
|
||||
def find_building_roof_shape(self, way_id):
|
||||
rs = "flat" # Standard if we don't find anything else
|
||||
xml_doc = xml.dom.minidom.parse(mstr_datafolder + "_cache/tile.xml")
|
||||
wpdata = xml_doc.getElementsByTagName("way")
|
||||
for wp in wpdata:
|
||||
if wp.getAttribute("id") == way_id:
|
||||
tags = wp.getElementsByTagName("tag")
|
||||
for tag in tags:
|
||||
a = tag.getAttribute("k")
|
||||
v = tag.getAttribute("v")
|
||||
if a == "roof:shape":
|
||||
rs = v
|
||||
break
|
||||
return rs
|
||||
|
||||
# Find the roof levels
|
||||
def find_building_roof_levels(self, way_id):
|
||||
lvl = 0 # Standard if we don't find anything else
|
||||
xml_doc = xml.dom.minidom.parse(mstr_datafolder + "_cache/tile.xml")
|
||||
wpdata = xml_doc.getElementsByTagName("way")
|
||||
for wp in wpdata:
|
||||
if wp.getAttribute("id") == way_id:
|
||||
tags = wp.getElementsByTagName("tag")
|
||||
for tag in tags:
|
||||
a = tag.getAttribute("k")
|
||||
v = tag.getAttribute("v")
|
||||
if a == "roof:levels":
|
||||
lvl = int(v)
|
||||
break
|
||||
return lvl
|
||||
|
||||
|
||||
# It turns out that some features hide themselves in the relations section.
|
||||
# I figured this out during testing, and almost going insane over the
|
||||
|
Loading…
x
Reference in New Issue
Block a user