Skip to content

Commit

Permalink
Work in progress:
Browse files Browse the repository at this point in the history
-Explicit types
-Haversine distance
-Functions to re-implement
  • Loading branch information
FABallemand committed Jun 13, 2023
1 parent f869177 commit 550d5dd
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 9 deletions.
87 changes: 83 additions & 4 deletions ezgpx/gpx/gpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,23 @@ class GPX():
High level GPX object.
"""
def __init__(self, file_path: str):
self.file_path = file_path
self.parser = Parser(file_path)
self.gpx = self.parser.gpx
self.writer = Writer()
self.file_path: str = file_path
self.parser: Parser = Parser(file_path)
self.gpx: Gpx = self.parser.gpx
self.writer: Writer = Writer()

def nb_points(self):
"""
Compute the number of points in the GPX.
Returns:
int: Number of points in the GPX.
"""
nb_pts = 0
for track in self.gpx.tracks:
for track_segment in track.track_segments:
nb_pts += len(track_segment.track_points)
return nb_pts

def to_string(self) -> str:
return self.writer.gpx_to_string(self.gpx)
Expand All @@ -30,6 +43,72 @@ def to_dataframe(self) -> pd.DataFrame:
pd.DataFrame: Dataframe containing position data from GPX.
"""
return self.gpx.to_dataframe()

# def removeGPSErrors(gpx, error_distance=1000):
# """
# Remove GPS errors.

# Args:
# gpx (GPX): GPX object.
# error_distance (int, optional): GPS error threshold distance (in meters) between two points. Defaults to 1000.

# Returns:
# GPX: GPX object without GPS error.
# list: List of removed points (GPS errors).
# """
# # Create new "file"
# cleaned_gpx = gpxpy.gpx.GPX()

# previous_point = None
# GPS_errors = []

# for track in gpx.tracks:
# # Create track
# gpx_track = gpxpy.gpx.GPXTrack()
# cleaned_gpx.tracks.append(gpx_track)
# for segment in track.segments:
# # Create segment
# gpx_segment = gpxpy.gpx.GPXTrackSegment()
# gpx_track.segments.append(gpx_segment)
# for point in segment.points:
# # Create points
# if previous_point is None or gpxpy.geo.haversine_distance(previous_point.latitude,
# previous_point.longitude,
# point.latitude,
# point.longitude) < error_distance:
# gpx_segment.points.append(gpxpy.gpx.GPXTrackPoint(point.latitude, point.longitude, elevation=point.elevation))
# previous_point = point
# else:
# GPS_errors.append(point)
# return cleaned_gpx, GPS_errors

# def compressFile(gpx, compression_method="Ramer-Douglas-Peucker algorithm", vertical_smooth=True, horizontal_smooth=True):
# """
# Compress GPX file.

# Args:
# gpx (GPX): GPX object.
# compression_method (str, optional): Method used to compress GPX. Defaults to "RPD".
# vertical_smooth (bool, optional): Vertical smoothing. Defaults to True.
# horizontal_smooth (bool, optional): Horizontal smoothing. Defaults to True.

# Returns:
# GPX: Compressed GPX object.
# """
# # Smoothing
# gpx.smooth(vertical=vertical_smooth, horizontal=horizontal_smooth)

# # Compression
# if compression_method == "Ramer-Douglas-Peucker algorithm":
# gpx.simplify()
# elif compression_method == "Remove 25% points":
# gpx.reduce_points(int(gpx.get_track_points_no() * 0.75))
# elif compression_method == "Remove 50% points":
# gpx.reduce_points(int(gpx.get_track_points_no() * 0.5))
# elif compression_method == "Remove 75% points":
# gpx.reduce_points(int(gpx.get_track_points_no() * 0.25))

# return gpx

def plot(self, title: str = "Track", base_color: str = "#101010", start_stop: bool = False, elevation_color: bool = False, file_path: str = None,):

Expand Down
13 changes: 11 additions & 2 deletions ezgpx/gpx_elements/gpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ class Gpx():
"""

def __init__(self, metadata: Metadata = None, tracks: list[Track] = []):
self.metadata = metadata
self.tracks = tracks
self.metadata: Metadata = metadata
self.tracks: list[Track] = tracks

def to_dataframe(self) -> pd.DataFrame:
"""
Expand All @@ -30,3 +30,12 @@ def to_dataframe(self) -> pd.DataFrame:
})
df = pd.DataFrame(route_info)
return df

def remove_points(self, remove_factor: int = 2):
count = 0
for track in self.tracks:
for track_segment in track.track_segments:
for track_point in track_segment.track_points:
if count % remove_factor == 0:
track_segment.track_points.remove(track_point)
count += 1
4 changes: 2 additions & 2 deletions ezgpx/gpx_elements/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ class Track():
"""

def __init__(self, name: str = "", track_segments: list[TrackSegment] = []):
self.name = name
self.track_segments = track_segments
self.name: str = name
self.track_segments: list[TrackSegment] = track_segments
2 changes: 1 addition & 1 deletion ezgpx/gpx_elements/track_segment.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ class TrackSegment():
"""

def __init__(self, track_points: list[TrackPoint] = []):
self.track_points = track_points
self.track_points: list[TrackPoint] = track_points
1 change: 1 addition & 0 deletions ezgpx/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .distance import *
from .projections import *
32 changes: 32 additions & 0 deletions ezgpx/utils/distance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import math as m

# latitude/longitude in GPX files is always in WGS84 datum
# WGS84 defined the Earth semi-major axis with 6378.137 km
# https://en.wikipedia.org/wiki/World_Geodetic_System#WGS84
EARTH_RADIUS = 6378.137 * 1000

def haversine_distance(latitude_1: float, longitude_1: float, latitude_2: float, longitude_2: float) -> float:
"""
Compute Haversine distance between to points.
https://en.wikipedia.org/wiki/Haversine_formula
Args:
latitude_1 (float): Latitude of the first point.
longitude_1 (float): Longitude of the first point.
latitude_2 (float): Latitude of the second point.
longitude_2 (float): Longitude of the second point.
Returns:
float: Haversine distance between the points.
"""
# Delta and conversion to radians
delta_lat = m.radians(latitude_1 - latitude_2)
delta_long = m.radians(longitude_1 - longitude_2)

sin_1 = m.sin(delta_lat/2)
sin_2 = m.sin(delta_long/2)
a = m.sqrt(sin_1 * sin_1 + m.cos(latitude_1) * m.cos(latitude_2) * sin_2 * sin_2)
d = 2 * EARTH_RADIUS * m.asin(a)

return d

Binary file added test_files/river_run.kmz
Binary file not shown.

0 comments on commit 550d5dd

Please sign in to comment.