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
48 changes: 48 additions & 0 deletions cmpgpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@
import geo
import gfx

def reversal_detect(track1, track2, num_points):
""" Tests whether two tracks are likely to be a reversal of each other or not """

# Ensure num_points is no greater than the length of either track
num_points = min(num_points, len(track1), len(track2))

def displacement(track1, track2, index1, index2):
""" Returns distance between track1[index1] and track2[index2] """
return gpxpy.geo.distance(track1[index1].latitude, track1[index1].longitude, None, track2[index2].latitude, track2[index2].longitude, None)

sum_displacement_regular = 0
sum_displacement_opposite = 0

for i in range(num_points):
sum_displacement_regular += displacement(track1, track2, i, i)
sum_displacement_opposite += displacement(track1, track2, i, -i)

return False if sum_displacement_regular <= sum_displacement_opposite else True

def align_tracks(track1, track2, gap_penalty):
""" Needleman-Wunsch algorithm adapted for gps tracks. """
Expand Down Expand Up @@ -115,6 +133,8 @@ def draw_alignment(track1, track2, bounds):
parser = argparse.ArgumentParser()
parser.add_argument('gpx_file1', type=argparse.FileType('r'))
parser.add_argument('gpx_file2', type=argparse.FileType('r'))
parser.add_argument('-r', '--override_reverse', action='store_true',
help="override reversal detection")
parser.add_argument('-c', '--cutoff', type=int, default=10,
help="cutoff distance in meters for similar points")
parser.add_argument('-d', '--debug', action='store_true')
Expand All @@ -138,6 +158,34 @@ def draw_alignment(track1, track2, bounds):
gpx1_points = [p for s in gpx1.tracks[0].segments for p in s.points]
gpx2_points = [p for s in gpx2.tracks[0].segments for p in s.points]

# Loop handling, including detecting whether reversal of a track is required.
# Argument -r overrides detected reversals or forces them if requred
if geo.is_loop(gpx1_points, 100):
# gpx1 is a loop
_log.info(f"Rotating loop in {args.gpx_file1.name}")
gpx1_points = geo.rotate_loop(gpx1_points, gpx2_points[0])
if reversal_detect(gpx1_points, gpx2_points, 10):
_log.info("Detected a track that needs to be reversed")
if args.override_reverse == False:
_log.info(f"Reversing track in {args.gpx_file1.name}")
gpx1_points.reverse()
else:
_log.info("Reversal overriden")
else:
if args.override_reverse == True:
_log.info(f"Reversal forced. Reversing track in {args.gpx_file1.name}")
gpx1_points.reverse()
else:
# gpx1 is not a loop
if reversal_detect(gpx1_points, gpx2_points, 10):
_log.info("Detected a track that needs to be reversed")
if args.override_reverse == False:
_log.info(f"Reversing track in {args.gpx_file1.name}")
gpx1_points.reverse()
else:
_log.info(f"Reversal forced. Reversing track in {args.gpx_file1.name}")
gpx1_points.reverse()

# Evenly distribute the points
if args.even:
gpx1_points = geo.interpolate_distance(gpx1_points, args.even)
Expand Down
376 changes: 376 additions & 0 deletions examples/derwent_loop1.gpx

Large diffs are not rendered by default.

397 changes: 397 additions & 0 deletions examples/derwent_loop2.gpx

Large diffs are not rendered by default.

Binary file added examples/derwent_loops.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/stanage_linear.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions examples/stanage_linear1.gpx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<gpx xmlns:gh="https://graphhopper.com/public/schema/gpx/1.1" xmlns:gs="http://www.topografix.com/GPX/gpx_style/0/2" xmlns:os="https://ordnancesurvey.co.uk/public/schema/route/0.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" creator="OSMaps" version="1.1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk><name>linear_1</name>
<trkseg>
<trkpt lat="53.3873051" lon="-1.6543717"><ele>357.1</ele></trkpt>
<trkpt lat="53.3873050" lon="-1.6543720"><ele>357.1</ele></trkpt>
<trkpt lat="53.3872740" lon="-1.6544700"><ele>357.1</ele></trkpt>
<trkpt lat="53.3872350" lon="-1.6544540"><ele>357.1</ele></trkpt>
<trkpt lat="53.3869560" lon="-1.6544920"><ele>356.7</ele></trkpt>
<trkpt lat="53.3864160" lon="-1.6546340"><ele>359</ele></trkpt>
<trkpt lat="53.3860820" lon="-1.6546930"><ele>363.2</ele></trkpt>
<trkpt lat="53.3856550" lon="-1.6546800"><ele>363.2</ele></trkpt>
<trkpt lat="53.3842480" lon="-1.6548470"><ele>376.4</ele></trkpt>
<trkpt lat="53.3838570" lon="-1.6549610"><ele>371.3</ele></trkpt>
<trkpt lat="53.3836170" lon="-1.6550740"><ele>374.6</ele></trkpt>
<trkpt lat="53.3826200" lon="-1.6556810"><ele>386.6</ele></trkpt>
<trkpt lat="53.3823640" lon="-1.6557870"><ele>389.9</ele></trkpt>
<trkpt lat="53.3823170" lon="-1.6558100"><ele>389.9</ele></trkpt>
<trkpt lat="53.3796790" lon="-1.6587650"><ele>406.2</ele></trkpt>
<trkpt lat="53.3790740" lon="-1.6593720"><ele>410.4</ele></trkpt>
<trkpt lat="53.3779090" lon="-1.6607480"><ele>421.9</ele></trkpt>
<trkpt lat="53.3771430" lon="-1.6615730"><ele>426.9</ele></trkpt>
<trkpt lat="53.3765200" lon="-1.6621410"><ele>435.8</ele></trkpt>
<trkpt lat="53.3763220" lon="-1.6622600"><ele>435.8</ele></trkpt>
<trkpt lat="53.3760530" lon="-1.6622520"><ele>440.7</ele></trkpt>
<trkpt lat="53.3760100" lon="-1.6622130"><ele>440.7</ele></trkpt>
<trkpt lat="53.3758390" lon="-1.6619560"><ele>440.7</ele></trkpt>
<trkpt lat="53.3757950" lon="-1.6619180"><ele>440.7</ele></trkpt>
<trkpt lat="53.3757070" lon="-1.6619160"><ele>445.3</ele></trkpt>
<trkpt lat="53.3754280" lon="-1.6620760"><ele>445.3</ele></trkpt>
<trkpt lat="53.3752430" lon="-1.6621500"><ele>449.5</ele></trkpt>
<trkpt lat="53.3751500" lon="-1.6621590"><ele>449.5</ele></trkpt>
<trkpt lat="53.3747140" lon="-1.6625550"><ele>443.6</ele></trkpt>
<trkpt lat="53.3745040" lon="-1.6627140"><ele>443.6</ele></trkpt>
<trkpt lat="53.3741980" lon="-1.6629170"><ele>451.1</ele></trkpt>
<trkpt lat="53.3741000" lon="-1.6629420"><ele>451.1</ele></trkpt>
<trkpt lat="53.3738570" lon="-1.6629520"><ele>451.1</ele></trkpt>
<trkpt lat="53.3735610" lon="-1.6628990"><ele>451.1</ele></trkpt>
<trkpt lat="53.3730290" lon="-1.6625490"><ele>445</ele></trkpt>
<trkpt lat="53.3729300" lon="-1.6625430"><ele>445</ele></trkpt>
<trkpt lat="53.3723060" lon="-1.6627900"><ele>446.7</ele></trkpt>
<trkpt lat="53.3722690" lon="-1.6627960"><ele>446.7</ele></trkpt>
<trkpt lat="53.3722692" lon="-1.6627962"><ele>446.7</ele></trkpt>
<trkpt lat="53.3722690" lon="-1.6627960"><ele>446.7</ele></trkpt>
<trkpt lat="53.3715870" lon="-1.6629040"><ele>446.5</ele></trkpt>
<trkpt lat="53.3713310" lon="-1.6629730"><ele>446.5</ele></trkpt>
<trkpt lat="53.3700470" lon="-1.6634250"><ele>440.6</ele></trkpt>
<trkpt lat="53.3696790" lon="-1.6635280"><ele>443.1</ele></trkpt>
<trkpt lat="53.3691180" lon="-1.6637470"><ele>444.2</ele></trkpt>
<trkpt lat="53.3684030" lon="-1.6637420"><ele>442.1</ele></trkpt>
<trkpt lat="53.3681290" lon="-1.6637630"><ele>442.5</ele></trkpt>
<trkpt lat="53.3679140" lon="-1.6637400"><ele>442.5</ele></trkpt>
<trkpt lat="53.3677210" lon="-1.6636490"><ele>442.5</ele></trkpt>
<trkpt lat="53.3676060" lon="-1.6638490"><ele>444.3</ele></trkpt>
<trkpt lat="53.3675580" lon="-1.6639020"><ele>444.3</ele></trkpt>
<trkpt lat="53.3674240" lon="-1.6639530"><ele>444.3</ele></trkpt>
<trkpt lat="53.3672850" lon="-1.6639480"><ele>444.3</ele></trkpt>
<trkpt lat="53.3669220" lon="-1.6640060"><ele>447</ele></trkpt>
<trkpt lat="53.3667630" lon="-1.6638270"><ele>439.7</ele></trkpt>
<trkpt lat="53.3666150" lon="-1.6636180"><ele>439.7</ele></trkpt>
<trkpt lat="53.3660180" lon="-1.6625030"><ele>449.7</ele></trkpt>
<trkpt lat="53.3658470" lon="-1.6621060"><ele>440.8</ele></trkpt>
<trkpt lat="53.3657640" lon="-1.6618450"><ele>440.8</ele></trkpt>
<trkpt lat="53.3655200" lon="-1.6612530"><ele>452.5</ele></trkpt>
<trkpt lat="53.3653480" lon="-1.6608940"><ele>453.5</ele></trkpt>
<trkpt lat="53.3650750" lon="-1.6604650"><ele>453.5</ele></trkpt>
<trkpt lat="53.3645460" lon="-1.6589170"><ele>457.3</ele></trkpt>
<trkpt lat="53.3643840" lon="-1.6585500"><ele>456.1</ele></trkpt>
<trkpt lat="53.3640010" lon="-1.6578460"><ele>449.2</ele></trkpt>
<trkpt lat="53.3638610" lon="-1.6575380"><ele>449.2</ele></trkpt>
<trkpt lat="53.3637330" lon="-1.6571040"><ele>453.7</ele></trkpt>
<trkpt lat="53.3635360" lon="-1.6562580"><ele>441.2</ele></trkpt>
<trkpt lat="53.3634500" lon="-1.6560040"><ele>441.2</ele></trkpt>
<trkpt lat="53.3631520" lon="-1.6551700"><ele>427.3</ele></trkpt>
<trkpt lat="53.3628540" lon="-1.6542520"><ele>441.9</ele></trkpt>
<trkpt lat="53.3627810" lon="-1.6541660"><ele>441.9</ele></trkpt>
<trkpt lat="53.3626780" lon="-1.6540230"><ele>427.5</ele></trkpt>
<trkpt lat="53.3625370" lon="-1.6537250"><ele>427.5</ele></trkpt>
<trkpt lat="53.3620660" lon="-1.6526090"><ele>435</ele></trkpt>
<trkpt lat="53.3620080" lon="-1.6524520"><ele>435</ele></trkpt>
<trkpt lat="53.3618210" lon="-1.6517400"><ele>435.5</ele></trkpt>
<trkpt lat="53.3616930" lon="-1.6513890"><ele>424.2</ele></trkpt>
<trkpt lat="53.3616430" lon="-1.6512850"><ele>433</ele></trkpt>
<trkpt lat="53.3611580" lon="-1.6505270"><ele>430.4</ele></trkpt>
<trkpt lat="53.3610570" lon="-1.6502960"><ele>430.4</ele></trkpt>
<trkpt lat="53.3608090" lon="-1.6496250"><ele>423.3</ele></trkpt>
<trkpt lat="53.3608091" lon="-1.6496250"><ele>423.3</ele></trkpt>
<trkpt lat="53.3608090" lon="-1.6496250"><ele>423.3</ele></trkpt>
<trkpt lat="53.3603200" lon="-1.6483030"><ele>415.6</ele></trkpt>
<trkpt lat="53.3601500" lon="-1.6475240"><ele>413.4</ele></trkpt>
<trkpt lat="53.3600870" lon="-1.6474040"><ele>413.4</ele></trkpt>
<trkpt lat="53.3597850" lon="-1.6470990"><ele>405.5</ele></trkpt>
<trkpt lat="53.3597330" lon="-1.6470430"><ele>405.5</ele></trkpt>
<trkpt lat="53.3596990" lon="-1.6469580"><ele>405.5</ele></trkpt>
<trkpt lat="53.3593850" lon="-1.6460670"><ele>419.8</ele></trkpt>
<trkpt lat="53.3593720" lon="-1.6460400"><ele>419.8</ele></trkpt>
<trkpt lat="53.3586730" lon="-1.6446400"><ele>423.1</ele></trkpt>
<trkpt lat="53.3584020" lon="-1.6442380"><ele>420</ele></trkpt>
<trkpt lat="53.3581620" lon="-1.6439600"><ele>404.7</ele></trkpt>
<trkpt lat="53.3579780" lon="-1.6438260"><ele>424</ele></trkpt>
<trkpt lat="53.3576800" lon="-1.6433720"><ele>407.9</ele></trkpt>
<trkpt lat="53.3574780" lon="-1.6430240"><ele>427.3</ele></trkpt>
<trkpt lat="53.3573910" lon="-1.6430130"><ele>427.3</ele></trkpt>
<trkpt lat="53.3570790" lon="-1.6425990"><ele>413.4</ele></trkpt>
<trkpt lat="53.3564170" lon="-1.6418300"><ele>424.3</ele></trkpt>
<trkpt lat="53.3556620" lon="-1.6407720"><ele>427.2</ele></trkpt>
<trkpt lat="53.3555900" lon="-1.6406970"><ele>427.2</ele></trkpt>
<trkpt lat="53.3555020" lon="-1.6403680"><ele>427.2</ele></trkpt>
<trkpt lat="53.3554810" lon="-1.6402090"><ele>416.6</ele></trkpt>
<trkpt lat="53.3554630" lon="-1.6398770"><ele>428</ele></trkpt>
<trkpt lat="53.3554530" lon="-1.6396530"><ele>428</ele></trkpt>
<trkpt lat="53.3554620" lon="-1.6394880"><ele>428</ele></trkpt>
<trkpt lat="53.3554890" lon="-1.6393460"><ele>431.2</ele></trkpt>
<trkpt lat="53.3555240" lon="-1.6392480"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556220" lon="-1.6391250"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556040" lon="-1.6387920"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556260" lon="-1.6383060"><ele>431.2</ele></trkpt>
<trkpt lat="53.3561670" lon="-1.6308290"><ele>442.9</ele></trkpt>
<trkpt lat="53.3561760" lon="-1.6307020"><ele>442.9</ele></trkpt>
<trkpt lat="53.3561850" lon="-1.6305610"><ele>442.9</ele></trkpt>
<trkpt lat="53.3562030" lon="-1.6304820"><ele>442.9</ele></trkpt>
<trkpt lat="53.3562031" lon="-1.6304817"><ele>442.9</ele></trkpt>
</trkseg></trk></gpx>
103 changes: 103 additions & 0 deletions examples/stanage_linear2.gpx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<gpx xmlns:gh="https://graphhopper.com/public/schema/gpx/1.1" xmlns:gs="http://www.topografix.com/GPX/gpx_style/0/2" xmlns:os="https://ordnancesurvey.co.uk/public/schema/route/0.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.topografix.com/GPX/1/1" creator="OSMaps" version="1.1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1/gpx.xsd">
<trk><name>linear_2</name>
<trkseg>
<trkpt lat="53.3560661" lon="-1.6307495"><ele>442.9</ele></trkpt>
<trkpt lat="53.3560660" lon="-1.6307500"><ele>442.9</ele></trkpt>
<trkpt lat="53.3561760" lon="-1.6307020"><ele>442.9</ele></trkpt>
<trkpt lat="53.3556260" lon="-1.6383060"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556040" lon="-1.6387920"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556110" lon="-1.6390060"><ele>431.2</ele></trkpt>
<trkpt lat="53.3556220" lon="-1.6391250"><ele>431.2</ele></trkpt>
<trkpt lat="53.3555240" lon="-1.6392480"><ele>431.2</ele></trkpt>
<trkpt lat="53.3554890" lon="-1.6393460"><ele>431.2</ele></trkpt>
<trkpt lat="53.3554620" lon="-1.6394880"><ele>428</ele></trkpt>
<trkpt lat="53.3554530" lon="-1.6396530"><ele>428</ele></trkpt>
<trkpt lat="53.3554630" lon="-1.6398770"><ele>428</ele></trkpt>
<trkpt lat="53.3555020" lon="-1.6403680"><ele>427.2</ele></trkpt>
<trkpt lat="53.3555900" lon="-1.6406970"><ele>427.2</ele></trkpt>
<trkpt lat="53.3556620" lon="-1.6407720"><ele>427.2</ele></trkpt>
<trkpt lat="53.3564170" lon="-1.6418300"><ele>424.3</ele></trkpt>
<trkpt lat="53.3570790" lon="-1.6425990"><ele>413.4</ele></trkpt>
<trkpt lat="53.3573910" lon="-1.6430130"><ele>427.3</ele></trkpt>
<trkpt lat="53.3574780" lon="-1.6430240"><ele>427.3</ele></trkpt>
<trkpt lat="53.3576800" lon="-1.6433720"><ele>407.9</ele></trkpt>
<trkpt lat="53.3579780" lon="-1.6438260"><ele>424</ele></trkpt>
<trkpt lat="53.3582630" lon="-1.6443020"><ele>420</ele></trkpt>
<trkpt lat="53.3584780" lon="-1.6449220"><ele>400.4</ele></trkpt>
<trkpt lat="53.3586040" lon="-1.6452410"><ele>400.4</ele></trkpt>
<trkpt lat="53.3588970" lon="-1.6458110"><ele>401.6</ele></trkpt>
<trkpt lat="53.3590810" lon="-1.6462410"><ele>381.2</ele></trkpt>
<trkpt lat="53.3594610" lon="-1.6473570"><ele>385.3</ele></trkpt>
<trkpt lat="53.3596670" lon="-1.6480820"><ele>390.1</ele></trkpt>
<trkpt lat="53.3597400" lon="-1.6484780"><ele>383.9</ele></trkpt>
<trkpt lat="53.3597640" lon="-1.6484760"><ele>383.9</ele></trkpt>
<trkpt lat="53.3599780" lon="-1.6493190"><ele>377.8</ele></trkpt>
<trkpt lat="53.3609700" lon="-1.6526860"><ele>400.7</ele></trkpt>
<trkpt lat="53.3610020" lon="-1.6527890"><ele>400.7</ele></trkpt>
<trkpt lat="53.3610022" lon="-1.6527894"><ele>400.7</ele></trkpt>
<trkpt lat="53.3610020" lon="-1.6527890"><ele>400.7</ele></trkpt>
<trkpt lat="53.3611880" lon="-1.6533760"><ele>397</ele></trkpt>
<trkpt lat="53.3613730" lon="-1.6538960"><ele>394.7</ele></trkpt>
<trkpt lat="53.3621100" lon="-1.6557360"><ele>403.2</ele></trkpt>
<trkpt lat="53.3622520" lon="-1.6562010"><ele>401.3</ele></trkpt>
<trkpt lat="53.3624150" lon="-1.6572130"><ele>409</ele></trkpt>
<trkpt lat="53.3626040" lon="-1.6579770"><ele>405.1</ele></trkpt>
<trkpt lat="53.3626800" lon="-1.6581480"><ele>400.8</ele></trkpt>
<trkpt lat="53.3632790" lon="-1.6588750"><ele>416.9</ele></trkpt>
<trkpt lat="53.3635000" lon="-1.6592180"><ele>416.9</ele></trkpt>
<trkpt lat="53.3637220" lon="-1.6596220"><ele>420.7</ele></trkpt>
<trkpt lat="53.3640020" lon="-1.6602280"><ele>420.7</ele></trkpt>
<trkpt lat="53.3649220" lon="-1.6624580"><ele>425.8</ele></trkpt>
<trkpt lat="53.3661410" lon="-1.6644020"><ele>420.9</ele></trkpt>
<trkpt lat="53.3663880" lon="-1.6646250"><ele>424.6</ele></trkpt>
<trkpt lat="53.3666670" lon="-1.6647150"><ele>424.6</ele></trkpt>
<trkpt lat="53.3668830" lon="-1.6647350"><ele>427.1</ele></trkpt>
<trkpt lat="53.3672510" lon="-1.6646720"><ele>427.6</ele></trkpt>
<trkpt lat="53.3680370" lon="-1.6644170"><ele>426.7</ele></trkpt>
<trkpt lat="53.3684240" lon="-1.6645360"><ele>426.5</ele></trkpt>
<trkpt lat="53.3688280" lon="-1.6645770"><ele>426.8</ele></trkpt>
<trkpt lat="53.3694380" lon="-1.6645590"><ele>427.8</ele></trkpt>
<trkpt lat="53.3694378" lon="-1.6645590"><ele>427.8</ele></trkpt>
<trkpt lat="53.3694380" lon="-1.6645590"><ele>427.8</ele></trkpt>
<trkpt lat="53.3702800" lon="-1.6645730"><ele>430.4</ele></trkpt>
<trkpt lat="53.3710530" lon="-1.6645140"><ele>427.6</ele></trkpt>
<trkpt lat="53.3715140" lon="-1.6644090"><ele>425.9</ele></trkpt>
<trkpt lat="53.3718280" lon="-1.6643670"><ele>425.8</ele></trkpt>
<trkpt lat="53.3721290" lon="-1.6642080"><ele>425.8</ele></trkpt>
<trkpt lat="53.3723320" lon="-1.6641300"><ele>426.2</ele></trkpt>
<trkpt lat="53.3724400" lon="-1.6641160"><ele>426.2</ele></trkpt>
<trkpt lat="53.3738680" lon="-1.6636450"><ele>434.5</ele></trkpt>
<trkpt lat="53.3744920" lon="-1.6635230"><ele>432.1</ele></trkpt>
<trkpt lat="53.3747250" lon="-1.6633730"><ele>432.1</ele></trkpt>
<trkpt lat="53.3748690" lon="-1.6632440"><ele>443.6</ele></trkpt>
<trkpt lat="53.3750220" lon="-1.6630680"><ele>438.3</ele></trkpt>
<trkpt lat="53.3752130" lon="-1.6630020"><ele>438.3</ele></trkpt>
<trkpt lat="53.3753680" lon="-1.6627700"><ele>437.1</ele></trkpt>
<trkpt lat="53.3754880" lon="-1.6626410"><ele>437.1</ele></trkpt>
<trkpt lat="53.3760530" lon="-1.6622520"><ele>440.7</ele></trkpt>
<trkpt lat="53.3763220" lon="-1.6622600"><ele>435.8</ele></trkpt>
<trkpt lat="53.3765200" lon="-1.6621410"><ele>435.8</ele></trkpt>
<trkpt lat="53.3771430" lon="-1.6615730"><ele>426.9</ele></trkpt>
<trkpt lat="53.3771660" lon="-1.6615490"><ele>426.9</ele></trkpt>
<trkpt lat="53.3771655" lon="-1.6615491"><ele>426.9</ele></trkpt>
<trkpt lat="53.3771660" lon="-1.6615490"><ele>426.9</ele></trkpt>
<trkpt lat="53.3779090" lon="-1.6607480"><ele>421.9</ele></trkpt>
<trkpt lat="53.3789030" lon="-1.6595670"><ele>413.2</ele></trkpt>
<trkpt lat="53.3790740" lon="-1.6593720"><ele>410.4</ele></trkpt>
<trkpt lat="53.3796790" lon="-1.6587650"><ele>406.2</ele></trkpt>
<trkpt lat="53.3823170" lon="-1.6558100"><ele>389.9</ele></trkpt>
<trkpt lat="53.3823640" lon="-1.6557870"><ele>389.9</ele></trkpt>
<trkpt lat="53.3826200" lon="-1.6556810"><ele>386.6</ele></trkpt>
<trkpt lat="53.3836170" lon="-1.6550740"><ele>374.6</ele></trkpt>
<trkpt lat="53.3838570" lon="-1.6549610"><ele>371.3</ele></trkpt>
<trkpt lat="53.3842480" lon="-1.6548470"><ele>376.4</ele></trkpt>
<trkpt lat="53.3856550" lon="-1.6546800"><ele>363.2</ele></trkpt>
<trkpt lat="53.3860820" lon="-1.6546930"><ele>363.2</ele></trkpt>
<trkpt lat="53.3864160" lon="-1.6546340"><ele>359</ele></trkpt>
<trkpt lat="53.3869560" lon="-1.6544920"><ele>356.7</ele></trkpt>
<trkpt lat="53.3872350" lon="-1.6544540"><ele>357.1</ele></trkpt>
<trkpt lat="53.3872740" lon="-1.6544700"><ele>357.1</ele></trkpt>
<trkpt lat="53.3872960" lon="-1.6544000"><ele>357.1</ele></trkpt>
<trkpt lat="53.3872964" lon="-1.6544000"><ele>357.1</ele></trkpt>
</trkseg></trk></gpx>
28 changes: 28 additions & 0 deletions geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@
_log = logging.getLogger(__name__)


def is_loop(points, tolerance):
"""
Determines whether a set of points forms a loop, to a given tolerance
"""

start = points[0]
finish = points[-1]
dist = gpxpy.geo.distance(start.latitude, start.longitude, None,
finish.latitude, finish.longitude, None)
return True if dist <= tolerance else False

def rotate_loop(points, start):
"""
Rotates a loop so that the start is the closest point to given start location
"""

min_d = gpxpy.geo.distance(points[0].latitude, points[0].longitude, None,
start.latitude, start.longitude, None)
closest = 0
for p in range(0, len(points)):
d = gpxpy.geo.distance(points[p].latitude, points[p].longitude, None,
start.latitude, start.longitude, None)
if d < min_d:
min_d = d
closest = p

return points[closest:] + points[:closest]

def bearing(point1, point2):
"""
Calculates the initial bearing between point1 and point2 relative to north
Expand Down