Skip to content

Instantly share code, notes, and snippets.

@vabene1111
Created September 25, 2023 13:51
Show Gist options
  • Save vabene1111/d5520b24bf7c5a07b9ed2fa1f8cc1d4b to your computer and use it in GitHub Desktop.
Save vabene1111/d5520b24bf7c5a07b9ed2fa1f8cc1d4b to your computer and use it in GitHub Desktop.
import json
import os
from lxml import etree
import geopandas as gpd
def osm_replace(file, track=False):
f = open(file, "r", encoding="UTF-8")
data = f.read()
# replace all extensions with osm and specific namespaces and names
data = data.replace(
'<gpx version="1.1" creator="GDAL 3.6.4" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ogr="http://osgeo.org/gdal" xmlns="http://www.topografix.com/GPX/1/1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">',
'<gpx version="1.1" creator="OsmAnd" xmlns="http://www.topografix.com/GPX/1/1" xmlns:osmand="https://osmand.net" xmlns:test="https://test.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">'
)
data = data.replace('<ogr:', '<osmand:')
data = data.replace('</ogr:', '</osmand:')
data = data.replace('osmand:shape', 'osmand:background') # circle, square, octagon
data = data.replace('>star<', '>octagon<')
data = data.replace('osmand:symbol', 'osmand:icon')
data = data.replace('sport_swimming_outdoor', 'sport_swimming')
data = data.replace('eye-open', 'information_guidepost')
data = data.replace('food_restaurant', 'restaurants')
data = data.replace('walk', 'special_trekking')
data = data.replace('accommodation_camping', 'tourism_camp_site')
data = data.replace('<osmand:colour>', '<osmand:colour>#')
if track:
data = data.replace('<rte>', '<trk>')
data = data.replace('</rte>', '</trk>')
data = data.replace('<rtept', '<trkpt')
data = data.replace('</rtept>', '</trkpt>')
f = open(file, "w", encoding="UTF-8")
f.write(data)
def split_description(tree):
# take description dictionary and add as individual fields
for elem in tree.findall(".//{*}extensions"):
data_element = elem.find('.//{*}data')
element_data = json.loads(data_element.text)
for k in list(element_data.keys()):
new_element = etree.Element(f'{k.replace(" ", "")}')
new_element.text = element_data[k]
elem.append(new_element)
data_element.getparent().remove(data_element)
return tree
# -------------------------------
# ------------------ handle points
# -------------------------------
INPUT_FILE = 'input.geojson'
OUTPUT_FILE = os.path.join('output', 'points.gpx')
gdf = gpd.read_file(INPUT_FILE)
gdf = gdf[gdf.typeId == 1]
gdf = gdf.drop('time', axis=1)
# ogr2ogr -ntl POINT -f GPX output.gpx input.geojson
gdf.to_file(OUTPUT_FILE, 'GPX', GPX_USE_EXTENSIONS=True)
osm_replace(OUTPUT_FILE)
tree = split_description(etree.parse(OUTPUT_FILE))
tree.write(OUTPUT_FILE)
# -------------------------------
# ------------------ handle tracks
# -------------------------------
INPUT_FILE = 'input.geojson'
TRACKS_FOLDER = os.path.join('output', 'tracks')
for f in os.listdir(TRACKS_FOLDER):
os.remove(os.path.join(TRACKS_FOLDER, f))
gdf = gpd.read_file(INPUT_FILE)
gdf = gdf[gdf.typeId != 1]
gdf = gdf.drop('time', axis=1)
for i in range(len(gdf)):
OUTPUT_FILE = os.path.join(TRACKS_FOLDER, f'{gdf.iloc[[i]].iat[0, 0].replace(" ", "_")}.gpx')
gdf.iloc[[i]].to_file(OUTPUT_FILE, 'GPX', GPX_USE_EXTENSIONS=True)
osm_replace(OUTPUT_FILE, track=True)
etree.register_namespace("osmand", "https://osmand.net")
tree = etree.parse(OUTPUT_FILE)
for elem in tree.findall(".//{*}extensions"):
data_element = elem.find('.//{*}data')
element_data = json.loads(data_element.text)
new_element = etree.Element(etree.QName("https://osmand.net", "width"))
new_element.text = 'bold'
elem.append(new_element)
tree.getroot().append(elem)
meta = tree.find('.//{*}metadata')
ext = etree.Element('extensions')
desc = etree.Element(etree.QName("https://osmand.net", "desc"))
desc.text = '\n\n'.join([f'{key}: {value}' for key, value in json.loads(data_element.text).items()])
ext.append(desc)
meta.append(ext)
tree.write(OUTPUT_FILE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment