Skip to content

Instantly share code, notes, and snippets.

@bagage
Created October 2, 2014 21:13
Show Gist options
  • Save bagage/0025af69198e2ad71fc7 to your computer and use it in GitHub Desktop.
Save bagage/0025af69198e2ad71fc7 to your computer and use it in GitHub Desktop.
orienteering replay
import xml.etree.ElementTree as ET
from sys import argv
from os.path import splitext
import xml.dom.minidom as minidom
import random
from math import sin, cos, pi, atan, acos
import unicodedata
import re
class Color:
colors = ["ffff0000",
"ff0000ff",
"ff00ff00",
"ff00ffff",
"ffff00ff",
"ff8080ff",
"ff808080",
"ff000080",
"ff0080ff"
]
current = random.randint(0, len(colors))
def random():
Color.current = (Color.current + 1) % len(Color.colors)
return Color.colors[Color.current]
def gpx2kml(fileName, xmlNode):
tree = ET.parse(fileName)
root = tree.getroot()
trks = []
runnerName = ""
for child in root:
if child.tag == "{http://www.topografix.com/GPX/1/1}metadata":
runnerName = child[0][0].text
if child.tag == "{http://www.topografix.com/GPX/1/1}trk":
trks.append(child)
trksegs = []
for trk in trks:
for child in trk:
if child.tag == "{http://www.topografix.com/GPX/1/1}trkseg":
trksegs.append(child)
style = ET.SubElement(
document, "Style", id="s_hiker_" + slugify(runnerName))
iconstyle = ET.SubElement(style, "IconStyle")
ET.SubElement(iconstyle, "color").text = Color.random()
ET.SubElement(iconstyle, "scale").text = "1.2"
ref = ET.SubElement(iconstyle, "Icon")
ET.SubElement(
ref, "href").text = "http://maps.google.com/mapfiles/kml/shapes/hiker.png"
ET.SubElement(iconstyle, "hotSpot", x="0.5", y="0",
xunits="fraction", yunits="fraction")
folder = ET.SubElement(xmlNode, "Folder")
ET.SubElement(folder, "name").text = runnerName
ET.SubElement(folder, "open").text = "0"
ET.SubElement(folder, "description")
for seg in trksegs:
for child in seg:
if child.tag == "{http://www.topografix.com/GPX/1/1}trkpt":
lat = child.get("lat")
lon = child.get("lon")
alt = child[0].text
time = child[-1].text
placemark = ET.SubElement(folder, "Placemark")
ET.SubElement(placemark, "styleUrl").text = "#s_hiker_" + \
slugify(runnerName)
ts = ET.SubElement(placemark, "TimeStamp")
ET.SubElement(ts, "when").text = time
pt = ET.SubElement(placemark, "Point")
ET.SubElement(
pt, "coordinates").text = "{1},{0}".format(lat, lon)
def csv2kml(fileName, xmlNode ):
folder = ET.SubElement(xmlNode, "Folder")
ET.SubElement(folder, "name").text = "Checkpoints"
ET.SubElement(folder, "open").text = "0"
ET.SubElement(folder, "description")
with open(fileName, "r") as inFile:
for line in inFile:
placemark = ET.SubElement(folder, "Placemark")
ET.SubElement(placemark, "name").text = line.split(',')[0]
ET.SubElement(placemark, "styleUrl").text = "#s_checkpoint"
pt = ET.SubElement(placemark, "Point")
ET.SubElement(
pt, "coordinates").text = ",".join(line.split(',')[1:])
def imagescall( fileName, xmlNode ):
pixels = []
points = []
imageFile = ""
imageSize = []
with open(fileName, "r") as inFile:
line = inFile.readline().split(",")
imageFile = line[0]
imageSize = line[1:]
for line in inFile:
points.append(line.split(",")[:2])
pixels.append(line.split(",")[2:])
r = 6371
for point in range(0, len(points)):
print( imageFile )
print( r * sin( float(points[point][1]) * pi / 180 ) * cos( float(points[point][0]) * pi / 180 ) )
print( r * sin( float(points[point][1]) * pi / 180 ) * sin( float(points[point][0]) * pi / 180 ) )
x1 = r * sin( float(points[0][1]) * pi / 180 ) * cos( float(points[0][0]) * pi / 180 )
y1 = r * sin( float(points[0][1]) * pi / 180 ) * sin( float(points[0][0]) * pi / 180 )
x2 = r * sin( float(points[1][1]) * pi / 180 ) * cos( float(points[1][0]) * pi / 180 )
y2 = r * sin( float(points[1][1]) * pi / 180 ) * sin( float(points[1][0]) * pi / 180 )
dX1 = (x2 - x1)
dY1 = (y2 - y1)
X1 = int( pixels[0][0])
Y1 = int( pixels[0][1])
X2 = int( pixels[1][0])
Y2 = int( pixels[1][1])
dX2 = (X2 - X1)
dY2 = (Y2 - Y1)
dX = dX1/dX2
dY = dY1/dY2
x2 = r * sin( float(points[1][1]) * pi / 180 ) * cos( float(points[1][0]) * pi / 180 )
y2 = r * sin( float(points[1][1]) * pi / 180 ) * sin( float(points[1][0]) * pi / 180 )
# phi = atan( y / x )
# theta = acos( z / r )
# z = r * cos (theta)
overlay = ET.SubElement(xmlNode, "GroundOverlay")
ET.SubElement(overlay, "name").text = imageFile
icon = ET.SubElement(overlay, "Icon")
ET.SubElement(icon, "href").text = imageFile
ET.SubElement(icon, "viewBoundScale").text = "0.75"
latlonbox = ET.SubElement(overlay, "LatLonBox")
ET.SubElement(latlonbox, "north").text = "0"
ET.SubElement(latlonbox, "south").text = "0"
ET.SubElement(latlonbox, "east").text = "100"
ET.SubElement(latlonbox, "west").text = "100"
ET.SubElement(latlonbox, "rotate").text = "0"
def prettify(elem):
"""Return a pretty-printed XML string for the Element.
"""
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
def kml2file(root, filename):
"""Write a generated KML into a file
"""
with open(filename, "w") as outFile:
outFile.write(prettify(secondroot))
def slugify(name):
"""Slugify a name to an ASCII valid string"""
name = unicodedata.normalize('NFKD', name).encode('ascii', 'ignore')
name = str(re.sub('[^\w\-]', '', name.decode()).strip().lower())
return name
secondroot = ET.Element("kml", {"xmlns": "http://earth.google.com/kml/2.2"})
document = ET.SubElement(secondroot, "Document")
ET.SubElement(document, "name").text = "CO"
ET.SubElement(document, "description")
style = ET.SubElement(document, "Style", id="s_checkpoint")
iconstyle = ET.SubElement(style, "IconStyle")
ET.SubElement(iconstyle, "scale").text = "1.2"
ref = ET.SubElement(iconstyle, "Icon")
ET.SubElement(
ref, "href").text = "http://maps.google.com/mapfiles/kml/paddle/red-circle.png"
ET.SubElement(iconstyle, "hotSpot", x="0.5", y="0",
xunits="fraction", yunits="fraction")
for f in argv[1:]:
if splitext( f )[-1] == ".gpx":
gpx2kml( f, document )
if splitext( f )[-1] == ".chpt":
csv2kml( f, document )
if splitext( f )[-1] == ".map":
imagescall( f, document )
secondtree = ET.ElementTree(secondroot)
kml2file(secondroot, "output.kml")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment