Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ for waypoint in gpx.waypoints:

for route in gpx.routes:
print('Route:')
print('3D length:', route.length_3d())
print('Elevation gain/loss:', route.get_uphill_downhill())
for point in route.points:
print(f'Point at ({point.latitude},{point.longitude}) -> {point.elevtion}')
print(f'Point at ({point.latitude},{point.longitude}) -> {point.elevation}')

# There are many more utility methods and functions:
# You can manipulate/add/remove tracks, segments, points, waypoints and routes and
Expand Down
14 changes: 14 additions & 0 deletions gpxpy/gpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,20 @@ def length(self) -> float:
"""
return mod_geo.length_2d(cast(List[mod_geo.Location], self.points))

def length_3d(self) -> float:
"""Return route length in meters, including available elevation data."""
return mod_geo.length_3d(
cast(List[mod_geo.Location], self.points))

def get_uphill_downhill(self) -> UphillDownhill:
"""Return smoothed uphill and downhill elevation changes in meters.

Missing elevations are ignored, as for track segments.
"""
elevations = [point.elevation for point in self.points]
uphill, downhill = mod_geo.calculate_uphill_downhill(elevations)
return UphillDownhill(uphill, downhill)

def get_center(self) -> Optional[mod_geo.Location]:
"""
Get the center of the route.
Expand Down
33 changes: 33 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,39 @@ def test_ignore_maximums_for_max_speed(self) -> None:
mod_logging.debug('max_speed_with_extreemes = %s', max_speed_with_extreemes)
self.assertTrue(max_speed_with_more_extreemes - max_speed_with_extreemes > 10)

def test_route_elevation_calculations(self) -> None:
route = mod_gpx.GPXRoute()
route.points = [
mod_gpx.GPXRoutePoint(0, 0, elevation=0),
mod_gpx.GPXRoutePoint(0, 0, elevation=100),
mod_gpx.GPXRoutePoint(0, 0, elevation=0),
]
self.assertEqual(route.length(), 0)
self.assertEqual(route.length_3d(), 200)
# Elevation gain/loss uses the same smoothing as track segments.
self.assertEqual(route.get_uphill_downhill(),
mod_gpx.UphillDownhill(40, 40))

def test_route_missing_elevations(self) -> None:
route = mod_gpx.GPXRoute()
self.assertEqual(route.length_3d(), 0)
self.assertEqual(route.get_uphill_downhill(),
mod_gpx.UphillDownhill(0, 0))
route.points = [mod_gpx.GPXRoutePoint(0, 0)]
self.assertEqual(route.length_3d(), 0)
self.assertEqual(route.get_uphill_downhill(),
mod_gpx.UphillDownhill(0, 0))
route.points.append(mod_gpx.GPXRoutePoint(0, 0.001))
self.assertEqual(route.length_3d(), route.length())
self.assertEqual(route.get_uphill_downhill(),
mod_gpx.UphillDownhill(0, 0))
route.points[0].elevation = 0
route.points.append(
mod_gpx.GPXRoutePoint(0, 0.002, elevation=100))
self.assertEqual(route.length_3d(), route.length())
self.assertEqual(route.get_uphill_downhill(),
mod_gpx.UphillDownhill(100, 0))

def test_track_with_elevation_zero(self) -> None:
with open('test_files/cerknicko-jezero-with-elevations-zero.gpx') as f:
gpx = mod_gpxpy.parse(f)
Expand Down