orthographic/osmxml.py

166 lines
5.9 KiB
Python
Raw Normal View History

# -------------------------------------------------------------------
# ORTHOGRAPHIC
# Your personal aerial satellite. Always on. At any altitude.*
# Developed by MarStrMind
# License: MIT
# Up to date version always on marstr.online
# -------------------------------------------------------------------
# osmxml.py
# Performs calls to Overpass API to acquire XML files which we can
# then store into a much faster SQLite3 database.
# -------------------------------------------------------------------
import xml.dom.minidom
import requests
import os
from defines import *
from log import *
class mstr_osmxml:
def __init__(self, lat, lng):
self._latv = lat
self._lngv = lng
self._lat = lat
self._lng = lng
self._curB_lat = lat + mstr_zl_18
self._curB_lng = lng + mstr_zl_18
# Adjust bbox for when this class should persost, but acquire data for a different bbox
def adjust_bbox(self, lat, lng, lat_e, lng_e):
self._lat = round(lat, 4)
self._lng = round(lng, 4)
self._curB_lat = round(lat_e, 4)
self._curB_lng = round(lng_e, 4)
# Acquire XMLs in chunks, then store them
def acquire_osm(self, v, h):
mstr_msg("mstr_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)
}
r = requests.post(mstr_osm_endpoint, json=data)
xml = mstr_datafolder + "_cache\\tile.xml"
if os.path.isfile(xml):
os.remove(xml)
with open(xml, 'wb') as textfile:
textfile.write(r.content)
# Get all nodes from the specified OSM file
def acquire_nodes(self, xmlfile):
xml_doc = xml.dom.minidom.parse(xmlfile)
nodedata = xml_doc.getElementsByTagName("node")
nodes = []
for node in nodedata:
p = (node.getAttribute("id"), node.getAttribute("lat"), node.getAttribute("lon"))
nodes.append(p)
return nodes
# Get all waypoint data
def acquire_waypoint_data(self, xmlfile):
xml_doc = xml.dom.minidom.parse(xmlfile)
wpdata = xml_doc.getElementsByTagName("way")
wps = []
for wp in wpdata:
nddata = wp.getElementsByTagName("nd")
for nd in nddata:
p = (wp.getAttribute("id"), nd.getAttribute("ref"), "", "")
wps.append(p)
for wp in wpdata:
tagdata = wp.getElementsByTagName("tag")
for tag in tagdata:
c = tag.getAttribute("v").replace(",", "")
c = c.replace("'", "")
p = (wp.getAttribute("id"), "NULL", tag.getAttribute("k"), c)
wps.append(p)
return wps
# Checks if there is an airport or many airports with an ICAO code in the
# supplied XML data chunk
def find_icao_codes(self, xmlfile):
icao = []
xml_doc = xml.dom.minidom.parse(xmlfile)
wpdata = xml_doc.getElementsByTagName("way")
for wp in wpdata:
tags = wp.getElementsByTagName("tag")
for tag in tags:
a = tag.getAttribute("k")
if a == "icao":
v = tag.getAttribute("v")
icao.append(v)
# Return list of found airports
return icao
# Finds the surface type of a runway in the current data chunk.
# If no surface type is specified, the runway will be rendered similar
# to how motorways are rendered.
# This gets called only if some ICAO code was found
def find_runway_surface(self, xmlfile):
surface = ""
wpid = ""
xml_doc = xml.dom.minidom.parse(xmlfile)
wpdata = xml_doc.getElementsByTagName("way")
for wp in wpdata:
tags = wp.getElementsByTagName("tag")
for tag in tags:
a = tag.getAttribute("k")
v = tag.getAttribute("v")
if a == "aeroway" and v == "runway":
wpid = wp.getAttribute("id")
break
for wp in wpdata:
wid = wp.getAttribute("id")
if wid == wpid:
tags = wp.getElementsByTagName("tag")
for tag in tags:
a = tag.getAttribute("k")
v = tag.getAttribute("v")
if a == "surface":
surface = v
# Return the found surface type
return surface
# It turns out that some features hide themselves in the relations section.
# I figured this out during testing, and almost going insane over the
# question as to why some parts like forests are missing in the masks, while
# it is clearly labeled as forest on openstreetmap. We need to scan
# the relations and then scan through the outer and inner way IDs.
#
# Get all relation entries of importance.
def acquire_relations(self, xmlfile):
xml_doc = xml.dom.minidom.parse(xmlfile)
rlxml = xml_doc.getElementsByTagName("relation")
rls = []
for rl in rlxml:
rldata = rl.getElementsByTagName("member")
tagdata = rl.getElementsByTagName("tag")
for rp in rldata:
t = rp.getAttribute("role")
if t == "inner" or t == "outer":
tgd = []
for i in tagdata:
tgd.append(i.getAttribute("k"))
tgd.append(i.getAttribute("v"))
rls.append((rp.getAttribute("ref"), tgd))
return rls