gpx_reduce.py
author wim
Tue, 22 Aug 2017 11:22:13 +0200
changeset 3 f94099a0277a
parent 2 f93786d4f68e
child 4 1b96bb9de1f3
permissions -rw-r--r--
pylab plot vervangen door gnuplot commando cntl-0 aan scite toegevoegd om python script in terminal uit te voeren zodat ook raw_input werkt
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     1
#!/usr/bin/env python
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
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
     9
changelog: v1.2: clarity refractoring + speedup for identical points
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
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    16
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    17
This program is free software: you can redistribute it and/or modify
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    18
it under the terms of the GNU General Public License as published by
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    19
the Free Software Foundation, either version 3 of the License, or
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    20
(at your option) any later version.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    21
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    22
This program is distributed in the hope that it will be useful,
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    23
but WITHOUT ANY WARRANTY; without even the implied warranty of
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    24
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    25
GNU General Public License for more details.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    26
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    27
You should have received a copy of the GNU General Public License
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    28
along with this program.  If not, see <http://www.gnu.org/licenses/>.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    29
'''
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    30
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    31
import datetime
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    32
import sys
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    33
import time
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
    34
import numpy as np
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    35
import numpy.linalg as la
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    36
from math import *
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
    37
import xml.etree.ElementTree as etree
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    38
from optparse import OptionParser
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    39
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    40
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    41
parser = OptionParser('usage: %prog [options] input-file.gpx')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    42
parser.add_option('-v', '--verbose', action='store', type='int',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    43
    dest='verbose', default=1, help='verbose=[0,1]')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    44
parser.add_option('-p', '--plot', action='store_true', dest='plot',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    45
    default=False, help='Show a plot of the result at the end.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    46
parser.add_option('-d', '--dist', action='store', type='float', dest='max_dist',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    47
    default=0.5, help='Maximum distance of line from original points in meters')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    48
parser.add_option('-o', '--out', action='store', type='string',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    49
    dest='ofname', default=None, help='Output file name')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    50
parser.add_option('-m', '--maxsep', action='store', type='float', dest='max_sep',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    51
    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
    52
parser.add_option('-n', '--maxsep0', action='store', type='float', dest='max_sep0',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    53
    default=4.0, help='Maximum separation of points at zero speed.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    54
parser.add_option('-t', '--maxseptime', action='store', type='float', dest='max_sep_time',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    55
    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
    56
parser.add_option('-e', '--ele-weight', action='store', type='float',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    57
    dest='ele_weight', default=0.0,
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    58
    help='Weighting of elevation errors vs. horizontal errors. Default is 0.')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    59
parser.add_option('-b', '--bend', action='store', type='float', dest='bend',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    60
    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
    61
parser.add_option('-w', '--weighting', action='store', type='string',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    62
    dest='weighting', default='exp',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    63
    help='''Weighting function to be minimized for track reduction:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    64
pnum (number of points),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    65
sqrdistsum (number of points plus sum of squared distances to leftout points),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    66
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
    67
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
    68
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
    69
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''')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    70
(options, args) = parser.parse_args()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    71
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    72
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    73
if len(args) < 1:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    74
    parser.print_usage()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    75
    exit(2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    76
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    77
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    78
# use the WGS-84 ellipsoid
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    79
rE = 6356752.314245 # earth's radius
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    80
a = 6378137.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    81
b = 6356752.314245179
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    82
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    83
timeformat = '%Y-%m-%dT%H:%M:%SZ'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    84
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    85
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    86
def distance(p1_, pm_, p2_, ele_weight=1.0):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    87
    # returns distance of pm from line between p1 and p2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    88
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
    89
    p1, pm, p2 = np.array(p1_), np.array(pm_), np.array(p2_)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    90
    h1, hm, h2 = la.norm(p1), la.norm(pm), la.norm(p2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    91
    if ele_weight != 1.0 and min(h1, hm, h2) > 0.0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    92
        hmean = (h1 + hm + h2) / 3.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    93
        p1 *= (ele_weight + (1.0 - ele_weight) * hmean / h1)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    94
        pm *= (ele_weight + (1.0 - ele_weight) * hmean / hm)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    95
        p2 *= (ele_weight + (1.0 - ele_weight) * hmean / h2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    96
    line = p2 - p1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    97
    linel = la.norm(line)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    98
    vm = pm - p1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
    99
    if linel == 0.0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   100
        return la.norm(vm)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   101
    linem = line / linel
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   102
    
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   103
    position = np.dot(vm, linem) / linel
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   104
    if position < 0.0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   105
        return la.norm(vm)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   106
    elif position > 1.0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   107
        return la.norm(pm - p2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   108
    else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   109
        return la.norm(vm - line * position)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   110
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   111
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   112
def rotate(x, y, phi):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   113
    return x*cos(phi) - y*sin(phi), x*sin(phi) + y*cos(phi)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   114
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   115
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   116
def project_to_meters(lat, lon, latm, lonm):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   117
    # azimuthal map projection centered at average track coordinate
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   118
    lon -= lonm
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   119
    xyz = latlonele_to_xyz(lat, lon, 0.0)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   120
    zy = rotate(xyz[2], xyz[1], radians(90 - latm))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   121
    lat2 = atan2(zy[0], la.norm([zy[1], xyz[0]]))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   122
    lon2 = atan2(xyz[0], -zy[1])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   123
    x_meters = rE * sin(lon2) * (pi / 2.0 - lat2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   124
    y_meters = -rE * cos(lon2) * (pi / 2.0 - lat2)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   125
    return x_meters, y_meters
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   126
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   127
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   128
def latlonele_to_xyz(lat, lon, ele):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   129
    s = sin(radians(lat))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   130
    c = cos(radians(lat))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   131
    r = ele + a * b / la.norm([s*a, c*b])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   132
    lon = radians(lon)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   133
    return r * c * sin(lon), r * c * (-cos(lon)), r * s
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   134
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   135
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   136
def xyz_to_latlonele(x, y, z):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   137
    r = la.norm([x, y, z])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   138
    if (r == 0):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   139
        return 0.0, 0.0, 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   140
    lat = degrees(atan2(z, la.norm([x, y])))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   141
    lon = degrees(atan2(x, -y))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   142
    ele = r * (1.0 - a * b / la.norm([a*z, b*x, b*y]))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   143
    return lat, lon, ele
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   144
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   145
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   146
def reduced_track_indices(coordinate_list, timesteps=None):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   147
    # returns a list of indices of trackpoints that constitute the reduced track
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   148
    # takes a list of kartesian coordinate tuples
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   149
    m = len(coordinate_list)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   150
    if (m == 0): return []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   151
    if timesteps != None and len(timesteps) != len(coordinate_list):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   152
        timesteps = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   153
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   154
    # number of dimensions
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   155
    d = len(coordinate_list[0])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   156
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   157
    # remove identical entries (can speed up algorithm considerably)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   158
    original_indices = [0]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   159
    points = [{'p': coordinate_list[0], 'weight':1}]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   160
    if timesteps != None: points[0]['t'] = timesteps[0]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   161
    for i in range(1, m):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   162
        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
   163
            original_indices.append(i)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   164
            points.append({'p': coordinate_list[i], 'weight':1})
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   165
            if timesteps != None: points[-1]['t'] = timesteps[i]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   166
        else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   167
            points[-1]['weight'] += 1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   168
    n = len(points)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   169
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   170
    # progress printing initialisations
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   171
    progress_printed = False
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   172
    progress = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   173
    tprint = time.time()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   174
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   175
    # execute Dijkstra-like algorithm on points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   176
    points[0]['cost'] = 1.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   177
    points[0]['prev'] = -1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   178
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   179
    for i2 in range(1, n):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   180
        penalties = {}
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   181
        imin = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   182
        costmin = float('inf')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   183
        for i1 in reversed(range(i2)):
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   184
            p1 = np.array(points[i1]['p'])
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   185
            p2 = np.array(points[i2]['p'])
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   186
            seglength = la.norm(p2 - p1)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   187
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   188
            # estimate speed between p1 and p2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   189
            if timesteps != None:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   190
                dt = (points[i2]['t'] - points[i1]['t']).total_seconds()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   191
                v = seglength / max(0.1, dt)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   192
            else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   193
                v = seglength / float(i2 - i1) # assume 1s time spacing
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   194
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   195
            max_sep = options.max_sep0 + v * options.max_sep_time
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   196
            if options.max_dist >= 0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   197
                max_sep = min(max_sep, options.max_sep)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   198
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   199
            if (seglength >= max_sep and i1 != i2 - 1):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   200
                # point separation is too far
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   201
                # but always accept direct predecessor i1 = i2 - 1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   202
                if (seglength >= max_sep + options.max_dist):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   203
                    # no chance to find a valid earlier predecessor point
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   204
                    break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   205
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   206
                    continue
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   207
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   208
            if points[i1]['cost'] + 1.0 > costmin:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   209
                # the possible predecessor i1 is already too bad.
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   210
                continue
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   211
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   212
            i1_i2_segment_valid = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   213
            lower_i1_possible = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   214
            distance_squaremax = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   215
            distance_squaresum = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   216
            distances_squared = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   217
            # iterate all medium points between i1 and i2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   218
            for im in range(i1+1, i2):
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   219
                pm = np.array(points[im]['p'])
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   220
                d = distance(p1, pm, p2, options.ele_weight)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   221
                if (d <= options.max_dist):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   222
                    d_sq = (d / options.max_dist) ** 2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   223
                    distance_squaremax = max(distance_squaremax, d_sq)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   224
                    distance_squaresum += points[im]['weight'] * d_sq
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   225
                    distances_squared.append(d_sq)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   226
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   227
                    i1_i2_segment_valid = False
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   228
                
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   229
                    # check if connection to any further point i1 is impossible
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   230
                    d1 = np.dot(p1 - p2, p1 - p2)
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   231
                    d2 = np.dot(pm - p2, pm - p2)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   232
                    dd = options.max_dist ** 2
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   233
                    d1d2 = np.dot(p1 - p2, pm - p2)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   234
                    # formula from cosines of point separation angle and cone-opening angles around points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   235
                    if (d1 > dd and d2 > dd and (d1d2 + dd)**2 < (d2 - dd) * (d1 - dd)):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   236
                        lower_i1_possible = False
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   237
                        break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   238
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   239
            if (lower_i1_possible == False):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   240
                break
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   241
            
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   242
            if i1_i2_segment_valid:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   243
                if options.weighting == 'sqrdistmax':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   244
                    penalties[i1] = distance_squaremax
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   245
                elif options.weighting == 'sqrdistsum':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   246
                    penalties[i1] = distance_squaresum
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   247
                elif options.weighting == 'sqrlength':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   248
                    penalties[i1] = (seglength / max_sep) ** 2
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   249
                elif options.weighting == 'mix':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   250
                    penalties[i1] = (distance_squaremax * (1.0 + seglength / max_sep))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   251
                elif options.weighting == 'exp':
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   252
                    penalties[i1] = 0.5 * sum([0.5**i * d for i, d in
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   253
                        enumerate(sorted(distances_squared, reverse=True))])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   254
                else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   255
                    penalties[i1] = 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   256
                
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   257
                # add a penalty for kinks
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   258
                if options.bend > 0.:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   259
                    if points[i1]['prev'] != -1:
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   260
                        p0 = np.array(points[points[i1]['prev']]['p'])
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   261
                        v0 = p1 - p0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   262
                        v1 = p2 - p1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   263
                        if la.norm(v0) > 0. and la.norm(v1) > 0.:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   264
                            v0 /= la.norm(v0)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   265
                            v1 /= la.norm(v1)
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   266
                            kink = (1.0 - np.dot(v0, v1)) / 2.0
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   267
                            penalties[i1] += options.bend * kink
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   268
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   269
        # find best predecessor
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   270
        imin = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   271
        costmin = float('inf')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   272
        for prev, penalty in penalties.iteritems():
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   273
            # cost function is sum of points used (1.0) plus penalties
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   274
            cost = points[prev]['cost'] + 1.0 + penalty
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   275
            if cost < costmin:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   276
                imin = prev
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   277
                costmin = cost
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   278
        points[i2]['cost'] = costmin
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   279
        points[i2]['prev'] = imin
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   280
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   281
        # print progess
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   282
        if options.verbose == 1 and (100 * i2) / n > progress and time.time() >= tprint + 1:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   283
            tprint = time.time()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   284
            progress = (100 * i2) / n
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   285
            print '\r', progress, '%',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   286
            sys.stdout.flush()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   287
            progress_printed = True
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   288
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   289
    if progress_printed:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   290
        print '\r',
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   291
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   292
    # trace route backwards to collect final points
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   293
    final_pnums = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   294
    i = n-1
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   295
    while i >= 0:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   296
        final_pnums = [i] + final_pnums
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   297
        i = points[i]['prev']
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   298
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   299
    return [original_indices[i] for i in final_pnums]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   300
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   301
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   302
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   303
############################## main function #################################
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   304
for fname in args:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   305
    # initialisations
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   306
    tracksegs_old = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   307
    tracksegs_new = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   308
    sumx, sumy, sumz = 0.0, 0.0, 0.0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   309
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   310
    # import xml data from files
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   311
    print 'opening file', fname
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   312
    infile = open(fname)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   313
    tree = etree.parse(infile)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   314
    infile.close()
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   315
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   316
    gpx = tree.getroot()
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   317
    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
   318
    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
   319
    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
   320
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   321
    # extract data from xml
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   322
    for trkseg in gpx.findall('.//' + nsmap + 'trkseg'):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   323
        trkpts = trkseg.findall(nsmap + 'trkpt')
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   324
        n = len(trkpts)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   325
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   326
        # extract coordinate values
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   327
        lats = [float(trkpt.get('lat')) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   328
        lons = [float(trkpt.get('lon')) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   329
        eles = [float(trkpt.find(nsmap + 'ele').text) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   330
        try:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   331
            times = [datetime.datetime.strptime(trkpt.find(nsmap + 'time'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   332
                                       ).text, timeformat) for trkpt in trkpts]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   333
        except Exception as e:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   334
            print e
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   335
            times = None
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   336
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   337
        # save original trackseg for plotting
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   338
        if options.plot:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   339
            tracksegs_old.append([[lats[i], lons[i], eles[i]] for i in range(n)])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   340
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   341
        # calculate projected points to work on
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   342
        coords = []
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   343
        for i in range(n):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   344
            x, y, z = latlonele_to_xyz(lats[i], lons[i], eles[i])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   345
            coords.append((x, y, z))
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   346
            sumx += x
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   347
            sumy += y
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   348
            sumz += z
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   349
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   350
        # execute the reduction algorithm
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   351
        final_pnums = reduced_track_indices(coords, times)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   352
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   353
        n_new = len(final_pnums)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   354
        print 'number of points:', n, '-', n - n_new, '=', n_new
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   355
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   356
        # delete certain points from original data
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   357
        delete_pnums = [i for i in range(n) if i not in final_pnums]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   358
        for i in reversed(delete_pnums):
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   359
            trkseg.remove (trkpts[i])
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   360
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   361
        # save reduced trackseg for plotting
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   362
        if options.plot:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   363
            tracksegs_new.append([[float(trkpt.get('lat')),
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   364
                float(trkpt.get('lon')), float(trkpt.find(nsmap + 'ele').text)]
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   365
                for trkpt in trkseg.findall(nsmap + 'trkpt')])
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   366
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   367
    
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   368
    # export data to file
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   369
    if options.ofname != None:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   370
        ofname = options.ofname
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   371
    elif fname.endswith('.gpx'):
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   372
        ofname = fname[:-4] + '_reduced.gpx'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   373
    else:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   374
        ofname = fname + '_reduced.gpx'
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   375
    outfile = open(ofname, 'w')
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   376
    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
   377
    outfile.close()
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   378
    print 'modified copy written to', ofname
2
f93786d4f68e - afhangelijkheid van lxml verwijderd door de gewone etree te gebruiken
wim
parents: 1
diff changeset
   379
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   380
    # plot result to screen
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   381
    if options.plot:
3
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   382
        from subprocess import Popen, PIPE
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   383
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   384
        latm, lonm, elesum = xyz_to_latlonele(sumx, sumy, sumz)
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   385
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   386
        for trkseg in tracksegs_old:
3
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   387
            data_old = []
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   388
            for trkpt in trkseg:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   389
                xy = project_to_meters(trkpt[0], trkpt[1], latm, lonm)
3
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   390
                data_old.append (xy)
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   391
        
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   392
        for trkseg in tracksegs_new:
3
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   393
            data = []
0
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   394
            for trkpt in trkseg:
8f4668cd868b check in van orginele file
wim
parents:
diff changeset
   395
                xy = project_to_meters(trkpt[0], trkpt[1], latm, lonm)
3
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   396
                data.append (xy)
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   397
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   398
        #~ gnuPlotCmd = ['gnuplot', '-persist']
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   399
        gnuPlotCmd = ['gnuplot']
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   400
        plot = Popen (gnuPlotCmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   401
        plot.stdin.write (b"plot '-' with linespoints lc rgb 'red' pt 4, '-' with linespoints pt 6\n")
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   402
        plot.stdin.write ("\n".join ('%f %f' % d for d in data).encode ())
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   403
        plot.stdin.write (b'\ne\n')
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   404
        plot.stdin.write ("\n".join ('%f %f' % d for d in data_old).encode ())
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   405
        plot.stdin.write (b'\ne\n')
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   406
        plot.stdin.flush ()
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   407
        #~ raw_input ('druk')
f94099a0277a pylab plot vervangen door gnuplot
wim
parents: 2
diff changeset
   408
        while 1: time.sleep (1)