Skip to content

Instantly share code, notes, and snippets.

@cefn

cefn/make_xcms.py

Created Jul 11, 2020
Embed
What would you like to do?
#! /home/linuxbrew/.linuxbrew/opt/python@3.8/bin/python3.8
import os
import math
import shutil
import requests
from xml.etree import ElementTree
def decimalMinuteString(decimalDegreeString, paddegrees):
degrees = float(decimalDegreeString)
wholeDegrees = math.floor(degrees)
remainderDegrees = degrees % 1.0
minutes = remainderDegrees * 60
return f"{wholeDegrees:0{paddegrees}d}{minutes:06.3f}"
xcsoar_local_dir = "/home/cefn/Documents/kobo/xcsoar_emulator_root"
xcsoar_remote_dir = "http://download.xcsoar.org/maps/"
opendem_remote_dir = (
"http://www.muaythaiclinch.info/opendem_europe_download/eu_4326/contours/"
)
map_filenames = ["UK_HighRes.xcm", "UK.xcm", "UK_Altair.xcm"]
contour_filenames = {
"dales_west": "N54W003.zip",
"lakes": "N54W004.zip",
"dales_east": "N54W002.zip",
"pennines": "N53W003.zip",
"peaks": "N53W002.zip",
}
waypoint_urls = {
# lake district tumps and minor prominences from http://www.haroldstreet.org.uk/waypoints/download/?list=tumps&list2=lamps&area=ldnp
"lakes": "http://www.haroldstreet.org.uk/waypoints/download/satmap-gpx.php?list=tumps&area=ldnp&list2=lamps",
"dales": "http://www.haroldstreet.org.uk/waypoints/download/satmap-gpx.php?list=tumps&area=35&list2=lamps",
"pennines": "http://www.haroldstreet.org.uk/waypoints/download/satmap-gpx.php?list=tumps&area=36&list2=lamps",
}
for dirname in ["originals", "extracted", "augmented", "contours"]:
os.makedirs(dirname, exist_ok=True)
def lazy_download_url(remote_url, download_path):
if not os.path.exists(download_path):
r = requests.get(remote_url)
open(download_path, "wb").write(r.content)
return download_path
def lazy_download_filename(remote_dir, local_dir, file_name):
return lazy_download_url(
f"{remote_dir}{file_name}", os.path.join(local_dir, file_name)
)
def lazy_download_all():
for map_filename in map_filenames:
lazy_download_filename(xcsoar_remote_dir, "originals", map_filename)
for contour_file in contour_filenames.values():
lazy_download_filename(opendem_remote_dir, "contours", contour_file)
for (alias, url) in waypoint_urls.items():
download_path = f"{alias}.gpx"
lazy_download_url(url, download_path)
def make_files():
lazy_download_all()
for map_filename in map_filenames:
# unpack the map
short_name = os.path.splitext(map_filename)[0]
original_map_path = f"originals/{map_filename}"
extracted_map_path = f"extracted/{short_name}"
augmented_map_path = f"augmented/{map_filename}"
# unpack the .xcm filesystem
shutil.unpack_archive(
original_map_path, extract_dir=extracted_map_path, format="zip"
)
# add contours to extracted files
for (contour_alias, contour_filename) in contour_filenames.items():
contour_short_name = os.path.splitext(contour_filename)[0]
original_contour_path = f"contours/{contour_filename}"
extracted_contour_path = f"extracted/{contour_alias}"
# extract shapefile parts
shutil.unpack_archive(
original_contour_path, extract_dir=extracted_contour_path, format="zip"
)
# copy shapefile parts into unpacked .xcm filesystem
for extension in ["dbf", "prj", "shx", "shp"]:
shutil.copyfile(
f"{extracted_contour_path}/{contour_short_name}/{contour_short_name}.{extension}",
f"{extracted_map_path}/{contour_alias}_line.{extension}",
)
# read topology entry, add a line for the new contour
with open(f"{extracted_map_path}/topology.tpl", "r") as f:
lines = list(f.readlines())
with open(f"{extracted_map_path}/topology.tpl", "w") as f:
f.writelines(lines)
f.write(f"{contour_alias}_line,3,,,0,0,0,1,3,0\n")
# pack the .xcm filesystem again
shutil.make_archive(
augmented_map_path, root_dir=extracted_map_path, format="zip"
)
# reverse stupid shutil.make_archive suffix default
os.rename(f"{augmented_map_path}.zip", augmented_map_path)
# copy to test directory
shutil.copyfile(
augmented_map_path, f"{xcsoar_local_dir}/{short_name}_augmented.xcm"
)
for waypoint_alias in waypoint_urls.keys():
waypoint_import_filename = f"{waypoint_alias}.gpx"
waypoint_export_filename = f"{waypoint_alias}.cup"
tree = ElementTree.parse(waypoint_import_filename)
root = tree.getroot()
with open(waypoint_export_filename, "w") as f:
for childpos, child in enumerate(root):
name = child[1].text
code = name[:3].upper() + "{:03d}".format(childpos)
country = "UK"
lat = float(child.attrib["lat"])
lon = float(child.attrib["lon"])
lat = (
f"{decimalMinuteString(lat, 2)}N"
if lat > 0
else f"{decimalMinuteString(-lat, 2)}S"
)
lon = (
f"{decimalMinuteString(lon, 3)}E"
if lon > 0
else f"{decimalMinuteString(-lon, 3)}W"
)
height = child[0].text + "m" # in metres
pointtype = 7 # MntTop
desc = ""
f.write(
f""""{name}","{code}",{country},{lat},{lon},{height},{pointtype},,,,"{desc}"\n"""
)
shutil.copyfile(
waypoint_export_filename,
os.path.join(xcsoar_local_dir, waypoint_export_filename),
)
if __name__ == "__main__":
make_files()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.