In my previous post about Visualizing your hike track using Leaflet, I showed the Python code for generating the html page with JavaScript to generate a map using the Leaflet JavaScript library.
I this article I will show how to calculate the distance and the duration of the hike.
Calculating the duration of the hike is straight forward. You just read the timestamp of the first point and last point in the track and then calculate the time difference. So I won't go into details about that calculation, you can see the code for the calculation below.
To hold all the information about track we introduce a class. It also has two methods for calculating the duration and formatting the duration:
class Track:
def __init__(self, track, distance, startTime, endTime):
self.track = track
self.distance = distance
self.startTime = startTime
self.endTime = endTime
def duration(self):
if self.startTime != "" and self.endTime != "":
return self.endTime - self.startTime
else:
return timedelta(0)
def durationToStr(self):
duration = self.duration()
hours, remainder = divmod(duration.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
Calculating the distance is not as trivial as you might think. The basic algorithm is to calculate the distance between each point in the track and the add up all those distances into the total distance.
But how do you calculate the distance between two points defined in map coordinates? This is the complex part of the problem. Not only do you have to figure out how to calculate the distance between two points in whatever the coordinate system your tracker is recording in. You actually also have to consider that the track is not in two dimensions but in three dimensions because of the curvature of the earth.
Luckily for us, some clever people have done all the complex stuff for us and implemented the Python module geopy we can use to do the distance calculation. We can call the distance method for each pair of points in the track and then add the distances when we read the points from the gpx track.
The timestamp and the coordinates for each point in the track is available in the gpx data in the load method, so we modify the load method to fetch the start and end time and calculate the track distance when we read each point.
This is how the load methods looks after the modification:
def load_track(filename: str) -> Track:
if(os.path.exists(filename) == False):
print(f"File not found: {filename}")
return None
localtime = tz.tzlocal()
gpx_file = open(filename)
current_track = Track([], 0, "", "")
try:
gpx = gpxpy.parse(gpx_file)
prevPoint = (0, 0)
for track in gpx.tracks:
for segment in track.segments:
for point in segment.points:
current_track.track.append([float(point.latitude), float(point.longitude)])
if current_track.startTime == "":
current_track.startTime = point.time.astimezone(localtime)
current_track.endTime = point.time.astimezone(localtime)
if prevPoint != (0, 0):
pointDistance = geopy.distance.distance(prevPoint, (float(point.latitude), float(point.longitude))).km
current_track.distance = current_track.distance + pointDistance
prevPoint = (float(point.latitude),float(point.longitude))
except Exception as error:
print(f"\nParsing file '{filename}' failed. Error: {error}")
current_track = None
gpx_file.close()
return(current_track)
For the entire code, check out the previous article or clone the repository with the code from the GitHub repository gpx-to-leaflet.
Top comments (0)