gpx_reduce.py
author wim
Thu, 15 Jun 2023 08:46:26 +0200
changeset 15 cfb0607e5afc
parent 10 89108adbc468
permissions -rwxr-xr-x
- changes for python3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
     1
#!/usr/bin/env python3
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     2
# -*- coding: utf8 -*-
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     3
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     4
'''
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     5
gpx_reduce v1.8: removes points from gpx-files to reduce filesize and
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     6
tries to keep introduced distortions to the track at a minimum.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     7
Copyright (C) 2011,2012,2013,2015,2016,2017 travelling_salesman on OpenStreetMap
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     8
10
89108adbc468 gpx_plot: numpy verijderd uit gpx_plot
wim
parents: 6
diff changeset
     9
changelog: v1.2: clarity refractoring + speedup for identical points
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    10
           v1.3: new track weighting functions, progress display
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    11
           v1.4: new track weighting function, restructuring for memory saving
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    12
           v1.5: algorithm speedup by roughly a factor of 2 by eliminating some cases.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    13
           v1.6: presets for train etc.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    14
           v1.7: introduced weighting function for elevation errors
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    15
           v1.8: speed-dependent distance limit
10
89108adbc468 gpx_plot: numpy verijderd uit gpx_plot
wim
parents: 6
diff changeset
    16
           v1.9: removal of all dependencies (lxml, scipy, numpy, pylab)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    17
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    18
This program is free software: you can redistribute it and/or modify
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    19
it under the terms of the GNU General Public License as published by
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    20
the Free Software Foundation, either version 3 of the License, or
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    21
(at your option) any later version.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    22
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    23
This program is distributed in the hope that it will be useful,
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    24
but WITHOUT ANY WARRANTY; without even the implied warranty of
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    25
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    26
GNU General Public License for more details.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    27
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    28
You should have received a copy of the GNU General Public License
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    29
along with this program.  If not, see <http://www.gnu.org/licenses/>.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    30
'''
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    31
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    32
import datetime, sys, time, operator
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    33
from math import *
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
    34
import xml.etree.ElementTree as etree
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    35
from optparse import OptionParser
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
    36
from functools import reduce
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    37
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    38
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    39
parser = OptionParser('usage: %prog [options] input-file.gpx')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    40
parser.add_option('-v', '--verbose', action='store', type='int',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    41
    dest='verbose', default=1, help='verbose=[0,1]')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    42
parser.add_option('-d', '--dist', action='store', type='float', dest='max_dist',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    43
    default=0.5, help='Maximum distance of line from original points in meters')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    44
parser.add_option('-o', '--out', action='store', type='string',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    45
    dest='ofname', default=None, help='Output file name')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    46
parser.add_option('-m', '--maxsep', action='store', type='float', dest='max_sep',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    47
    default=200.0, help='Absolute maximum separation of points. No points will be deleted where the resulting distance would become greater than maxsep. Standard JOSM settings will not display points spaced more than 200m. -1 means no limit.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    48
parser.add_option('-n', '--maxsep0', action='store', type='float', dest='max_sep0',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    49
    default=4.0, help='Maximum separation of points at zero speed.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    50
parser.add_option('-t', '--maxseptime', action='store', type='float', dest='max_sep_time',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    51
    default=3.0, help='Maximum time separation of points, which will be added to maxsep0. Maximum allowed point separation will be min(m, n + t*v) where v is the speed in m/s.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    52
parser.add_option('-e', '--ele-weight', action='store', type='float',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    53
    dest='ele_weight', default=0.0,
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    54
    help='Weighting of elevation errors vs. horizontal errors. Default is 0.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    55
parser.add_option('-b', '--bend', action='store', type='float', dest='bend',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    56
    default=1.0, help='Penalty value for large bending angles at each trackpoint. Larger values (1 or more) make the track smoother.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    57
parser.add_option('-w', '--weighting', action='store', type='string',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    58
    dest='weighting', default='exp',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    59
    help='''Weighting function to be minimized for track reduction:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    60
pnum (number of points),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    61
sqrdistsum (number of points plus sum of squared distances to leftout points),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    62
sqrdistmax (number of points plus sum of squared distances to each maximally separated leftout point per new line segment),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    63
sqrlength (number of points plus sum of squared new line segment lengths normalized by maxsep),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    64
mix (number of points plus sum of squared distances to each maximally separated leftout point per new line segment weighted with corresponding segment length),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    65
exp (number of points plus sum of squared distances to leftout points with exponential weighting of 1/2, 1/4, 1/8... from furthest to closest point). exp=standard''')
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
    66
parser.add_option ('-r', dest='remove', default='extensions,hdop', help='remove tags T1,T2,..,Tn from every trackpoint', metavar='T1 T2 Tn')
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    67
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
    68
options, args = parser.parse_args()
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    69
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    70
if len(args) < 1:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    71
    parser.print_help ()
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    72
    sys.exit (2)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    73
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    74
# use the WGS-84 ellipsoid
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    75
rE = 6356752.314245 # earth's radius
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    76
a = 6378137.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    77
b = 6356752.314245179
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    78
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    79
timeformat = '%Y-%m-%dT%H:%M:%SZ'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    80
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    81
# the linear algebra with lists
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    82
dot = lambda p1, p2: reduce (operator.add, [a * b for a, b in zip (p1, p2)])
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    83
vmin  = lambda p1, p2: [a - b for a, b in zip (p1, p2)]
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    84
smul = lambda p, c: [a * c for a in p]
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    85
sdiv = lambda p, c: [a / c for a in p]
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    86
norm = lambda p: sqrt (sum (a * a for a in p))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    87
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    88
def distance (p1, pm, p2, ele_weight=1.0):
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    89
    # returns distance of pm from line between p1 and p2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    90
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    91
    h1, hm, h2 = norm (p1), norm (pm), norm (p2)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    92
    if ele_weight != 1.0 and min(h1, hm, h2) > 0.0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    93
        hmean = (h1 + hm + h2) / 3.0
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    94
        p1 = smul (p1, ele_weight + (1.0 - ele_weight) * hmean / h1)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    95
        pm = smul (pm, ele_weight + (1.0 - ele_weight) * hmean / hm)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    96
        p2 = smul (p2, ele_weight + (1.0 - ele_weight) * hmean / h2)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    97
    line = vmin (p2, p1)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    98
    linel = norm (line)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
    99
    vm = vmin (pm, p1)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   100
    if linel == 0.0:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   101
        return norm (vm)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   102
    linem = sdiv (line, linel)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   103
    
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   104
    position = dot (vm, linem) / linel
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   105
    if position < 0.0:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   106
        return norm (vm)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   107
    elif position > 1.0:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   108
        return norm (vmin (pm, p2))
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   109
    else:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   110
        return norm (vmin (vm, smul (line, position)))
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   111
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   112
def latlonele_to_xyz (lat, lon, ele):
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   113
    s = sin (radians (lat))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   114
    c = cos (radians (lat))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   115
    r = ele + a * b / norm ([s*a, c*b])
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   116
    lon = radians (lon)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   117
    return r * c * sin (lon), r * c * (-cos (lon)), r * s
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   118
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   119
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   120
def reduced_track_indices(coordinate_list, timesteps=None):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   121
    # returns a list of indices of trackpoints that constitute the reduced track
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   122
    # takes a list of kartesian coordinate tuples
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   123
    m = len(coordinate_list)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   124
    if (m == 0): return []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   125
    if timesteps != None and len(timesteps) != len(coordinate_list):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   126
        timesteps = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   127
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   128
    # number of dimensions
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   129
    d = len(coordinate_list[0])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   130
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   131
    # remove identical entries (can speed up algorithm considerably)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   132
    original_indices = [0]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   133
    points = [{'p': coordinate_list[0], 'weight':1}]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   134
    if timesteps != None: points[0]['t'] = timesteps[0]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   135
    for i in range(1, m):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   136
        if False in [coordinate_list[i-1][j] == coordinate_list[i][j] for j in range(d)]:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   137
            original_indices.append(i)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   138
            points.append({'p': coordinate_list[i], 'weight':1})
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   139
            if timesteps != None: points[-1]['t'] = timesteps[i]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   140
        else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   141
            points[-1]['weight'] += 1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   142
    n = len(points)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   143
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   144
    # progress printing initialisations
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   145
    progress_printed = False
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   146
    progress = 0
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   147
    tprint = time.time()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   148
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   149
    # execute Dijkstra-like algorithm on points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   150
    points[0]['cost'] = 1.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   151
    points[0]['prev'] = -1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   152
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   153
    for i2 in range(1, n):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   154
        penalties = {}
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   155
        imin = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   156
        costmin = float('inf')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   157
        for i1 in reversed(range(i2)):
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   158
            p1 = points[i1]['p']
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   159
            p2 = points[i2]['p']
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   160
            seglength = norm (vmin (p2, p1))
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   161
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   162
            # estimate speed between p1 and p2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   163
            if timesteps != None:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   164
                dt = (points[i2]['t'] - points[i1]['t']).total_seconds()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   165
                v = seglength / max(0.1, dt)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   166
            else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   167
                v = seglength / float(i2 - i1) # assume 1s time spacing
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   168
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   169
            max_sep = options.max_sep0 + v * options.max_sep_time
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   170
            if options.max_dist >= 0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   171
                max_sep = min(max_sep, options.max_sep)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   172
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   173
            if (seglength >= max_sep and i1 != i2 - 1):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   174
                # point separation is too far
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   175
                # but always accept direct predecessor i1 = i2 - 1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   176
                if (seglength >= max_sep + options.max_dist):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   177
                    # no chance to find a valid earlier predecessor point
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   178
                    break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   179
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   180
                    continue
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   181
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   182
            if points[i1]['cost'] + 1.0 > costmin:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   183
                # the possible predecessor i1 is already too bad.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   184
                continue
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   185
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   186
            i1_i2_segment_valid = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   187
            lower_i1_possible = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   188
            distance_squaremax = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   189
            distance_squaresum = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   190
            distances_squared = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   191
            # iterate all medium points between i1 and i2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   192
            for im in range(i1+1, i2):
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   193
                pm = points[im]['p']
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   194
                d = distance (p1, pm, p2, options.ele_weight)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   195
                if (d <= options.max_dist):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   196
                    d_sq = (d / options.max_dist) ** 2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   197
                    distance_squaremax = max(distance_squaremax, d_sq)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   198
                    distance_squaresum += points[im]['weight'] * d_sq
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   199
                    distances_squared.append(d_sq)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   200
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   201
                    i1_i2_segment_valid = False
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   202
                
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   203
                    # check if connection to any further point i1 is impossible
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   204
                    d1 = dot (vmin (p1, p2), vmin (p1, p2))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   205
                    d2 = dot (vmin (pm, p2), vmin (pm, p2))
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   206
                    dd = options.max_dist ** 2
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   207
                    d1d2 = dot (vmin (p1, p2), vmin (pm, p2))
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   208
                    # formula from cosines of point separation angle and cone-opening angles around points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   209
                    if (d1 > dd and d2 > dd and (d1d2 + dd)**2 < (d2 - dd) * (d1 - dd)):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   210
                        lower_i1_possible = False
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   211
                        break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   212
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   213
            if (lower_i1_possible == False):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   214
                break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   215
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   216
            if i1_i2_segment_valid:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   217
                if options.weighting == 'sqrdistmax':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   218
                    penalties[i1] = distance_squaremax
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   219
                elif options.weighting == 'sqrdistsum':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   220
                    penalties[i1] = distance_squaresum
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   221
                elif options.weighting == 'sqrlength':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   222
                    penalties[i1] = (seglength / max_sep) ** 2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   223
                elif options.weighting == 'mix':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   224
                    penalties[i1] = (distance_squaremax * (1.0 + seglength / max_sep))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   225
                elif options.weighting == 'exp':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   226
                    penalties[i1] = 0.5 * sum([0.5**i * d for i, d in
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   227
                        enumerate(sorted(distances_squared, reverse=True))])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   228
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   229
                    penalties[i1] = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   230
                
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   231
                # add a penalty for kinks
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   232
                if options.bend > 0.:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   233
                    if points[i1]['prev'] != -1:
6
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   234
                        p0 = points [points [i1]['prev']] ['p']
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   235
                        v0 = vmin (p1, p0)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   236
                        v1 = vmin (p2, p1)
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   237
                        if norm (v0) > 0. and norm (v1) > 0.:
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   238
                            v0 = sdiv (v0, norm (v0))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   239
                            v1 = sdiv (v1, norm (v1))
c808c4d02550 - numpy afhankelijkheid verwijderd
wim
parents: 5
diff changeset
   240
                            kink = (1.0 - dot (v0, v1)) / 2.0
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   241
                            penalties[i1] += options.bend * kink
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   242
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   243
        # find best predecessor
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   244
        imin = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   245
        costmin = float('inf')
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   246
        for prev, penalty in penalties.items():
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   247
            # cost function is sum of points used (1.0) plus penalties
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   248
            cost = points[prev]['cost'] + 1.0 + penalty
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   249
            if cost < costmin:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   250
                imin = prev
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   251
                costmin = cost
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   252
        points[i2]['cost'] = costmin
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   253
        points[i2]['prev'] = imin
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   254
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   255
        # print progess
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   256
        if options.verbose == 1 and (100 * i2) / n > progress and time.time() >= tprint + 1:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   257
            tprint = time.time()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   258
            progress = (100 * i2) / n
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   259
            print ('\r', progress, '%', end=' ')
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   260
            sys.stdout.flush()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   261
            progress_printed = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   262
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   263
    if progress_printed:
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   264
        print ('\r', end=' ')
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   265
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   266
    # trace route backwards to collect final points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   267
    final_pnums = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   268
    i = n-1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   269
    while i >= 0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   270
        final_pnums = [i] + final_pnums
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   271
        i = points[i]['prev']
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   272
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   273
    return [original_indices[i] for i in final_pnums]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   274
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   275
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   276
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   277
############################## main function #################################
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   278
for fname in args:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   279
    # initialisations
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   280
    ntot = 0    # total number of trackpoints (sum of segments)
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   281
    newtot = 0 # total number of trackpoints after removal
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   282
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   283
    # import xml data from files
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   284
    print ('opening file', fname)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   285
    infile = open(fname)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   286
    tree = etree.parse(infile)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   287
    infile.close()
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   288
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   289
    gpx = tree.getroot()
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   290
    nsurl = gpx.tag.split ('}')[0][1:]  # == 'http://www.topografix.com/GPX/1/1'
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   291
    etree.register_namespace('', nsurl) # default namespace -> xmlns:.... in the output
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   292
    nsmap = '{' + nsurl + '}'           # prefix for all tags in the tree
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   293
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   294
    # extract data from xml
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   295
    for si, trkseg in enumerate (gpx.findall('.//' + nsmap + 'trkseg')):
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   296
        trkpts = trkseg.findall(nsmap + 'trkpt')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   297
        n = len(trkpts)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   298
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   299
        # extract coordinate values
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   300
        lats = [float(trkpt.get('lat')) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   301
        lons = [float(trkpt.get('lon')) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   302
        eles = [float(trkpt.find(nsmap + 'ele').text) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   303
        try:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   304
            times = [datetime.datetime.strptime(trkpt.find(nsmap + 'time'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   305
                                       ).text, timeformat) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   306
        except Exception as e:
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   307
            print ('-- trackpoint without time')
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   308
            times = None
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   309
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   310
        # calculate projected points to work on
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   311
        coords = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   312
        for i in range(n):
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   313
            x, y, z = latlonele_to_xyz (lats[i], lons[i], eles[i])
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   314
            coords.append((x, y, z))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   315
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   316
        # execute the reduction algorithm
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   317
        final_pnums = reduced_track_indices(coords, times)
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   318
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   319
        n_new = len (final_pnums)
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   320
        print ('segment %d, with %d - %d = %d points' % (si, n, n - n_new, n_new))
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   321
        ntot += n
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   322
        newtot += n_new
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   323
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   324
        # delete certain points from original data
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   325
        delete_pnums = [i for i in range(n) if i not in final_pnums]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   326
        for i in reversed(delete_pnums):
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   327
            trkseg.remove (trkpts[i])   # remove from the xml-tree
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   328
            del trkpts [i]              # also remove from the list
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   329
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   330
        # remove certain sub-elements from remaining points
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   331
        options.remove = options.remove.replace ('+','extensions,hdop,')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   332
        taglist = options.remove.split (',')
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   333
        if taglist: print ('remove %s subelements from points' % ', '.join (taglist))
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   334
        for trkpnt in trkpts:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   335
            for tag in taglist:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   336
                e = trkpnt.find (nsmap + tag)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   337
                if e != None: trkpnt.remove (e)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents: 3
diff changeset
   338
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   339
    print ('total number of points: %d - %d = %d' % (ntot, ntot - newtot, newtot))
5
6be382f3be34 - plot code verwijderd
wim
parents: 4
diff changeset
   340
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   341
    # export data to file
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   342
    if options.ofname != None:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   343
        ofname = options.ofname
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   344
    elif fname.endswith('.gpx'):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   345
        ofname = fname[:-4] + '_reduced.gpx'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   346
    else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   347
        ofname = fname + '_reduced.gpx'
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   348
    outfile = open(ofname, 'wb')
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   349
    tree.write (outfile, encoding="utf-8", xml_declaration=True, default_namespace=None, method="xml")
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   350
    outfile.close()
15
cfb0607e5afc - changes for python3
wim
parents: 10
diff changeset
   351
    print ('modified copy written to', ofname)