elevation_chart_gen.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """Generate an elevation chart from a GPX file."""
  4. import gpxpy
  5. import logging
  6. import sys
  7. from math import sin, cos, sqrt, atan2, radians
  8. logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
  9. level=logging.DEBUG,
  10. stream=sys.stdout)
  11. def main(gpx_file):
  12. """Orchestrate."""
  13. gpx_points = parse_gpx_points(gpx_file)
  14. logging.info("Loaded %i points from file '%s'.", len(gpx_points), gpx_file)
  15. chart_points = get_chart_points(gpx_points)
  16. with open("data.csv", "w") as f:
  17. f.write("dist,ele\n")
  18. for p in chart_points:
  19. f.write("%0.4f,%0.4f\n" % (p['dist']/1000.0, p['ele']))
  20. def get_dist(lat1, lon1, lat2, lon2):
  21. """Get the distance in km of two points on earth."""
  22. R = 6373.0
  23. lat1 = radians(52.2296756)
  24. lon1 = radians(21.0122287)
  25. lat2 = radians(52.406374)
  26. lon2 = radians(16.9251681)
  27. dlon = lon2 - lon1
  28. dlat = lat2 - lat1
  29. a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
  30. c = 2 * atan2(sqrt(a), sqrt(1 - a))
  31. distance = R * c
  32. return distance
  33. def parse_gpx_points(gpx_file):
  34. """Get all points as a list from gpx_file."""
  35. with open(gpx_file) as f:
  36. gpx_data_txt = f.read()
  37. gpx = gpxpy.parse(gpx_data_txt)
  38. points = []
  39. for track in gpx.tracks:
  40. for segment in track.segments:
  41. for point in segment.points:
  42. points.append({'lat': point.latitude,
  43. 'lon': point.longitude,
  44. 'ele': point.elevation})
  45. return points
  46. def get_chart_points(points):
  47. """Get a list of points (x, y) with x=traveled distance, y=eleveation."""
  48. chart_points = [{'dist': 0, 'ele': points[0]['ele']}]
  49. dist = 0.0
  50. get_dist = gpxpy.geo.haversine_distance
  51. for i in range(1, len(points)):
  52. dist += get_dist(points[i - 1]['lat'], points[i - 1]['lon'],
  53. points[i]['lat'], points[i]['lon'])
  54. chart_points.append({'dist': dist, 'ele': points[i]['ele']})
  55. return chart_points
  56. def get_parser():
  57. """Get parser object for elevation_chart_gen.py."""
  58. from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
  59. parser = ArgumentParser(description=__doc__,
  60. formatter_class=ArgumentDefaultsHelpFormatter)
  61. parser.add_argument("-f", "--file",
  62. dest="filename",
  63. help="GPX file",
  64. metavar="FILE",
  65. required=True)
  66. return parser
  67. if __name__ == "__main__":
  68. args = get_parser().parse_args()
  69. main(args.filename)