gpx_plot.py
author wim
Wed, 30 Aug 2017 09:22:19 +0200
changeset 7 43fae0b52870
parent 4 1b96bb9de1f3
child 10 89108adbc468
permissions -rwxr-xr-x
*.zip toegevoegd aan ignore
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     1
#!/usr/bin/env python
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     2
# -*- coding: utf8 -*-
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     3
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     4
'''
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     5
This program is free software: you can redistribute it and/or modify
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     6
it under the terms of the GNU General Public License as published by
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     7
the Free Software Foundation, either version 3 of the License, or
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     8
(at your option) any later version.
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
     9
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    10
This program is distributed in the hope that it will be useful,
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    11
but WITHOUT ANY WARRANTY; without even the implied warranty of
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    13
GNU General Public License for more details.
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    14
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    15
You should have received a copy of the GNU General Public License
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    17
'''
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    18
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    19
import datetime
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    20
import sys
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    21
import time
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    22
import numpy as np
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    23
import numpy.linalg as la
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    24
from math import *
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    25
import xml.etree.ElementTree as etree
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    26
from optparse import OptionParser
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    27
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    28
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    29
parser = OptionParser('usage: %prog [options] input-file.gpx')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    30
(options, args) = parser.parse_args()
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    31
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    32
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    33
if len(args) < 1:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    34
    parser.print_usage()
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    35
    exit(2)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    36
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    37
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    38
# use the WGS-84 ellipsoid
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    39
rE = 6356752.314245 # earth's radius
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    40
a = 6378137.0
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    41
b = 6356752.314245179
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    42
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    43
timeformat = '%Y-%m-%dT%H:%M:%SZ'
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    44
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    45
def rotate(x, y, phi):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    46
    return x*cos(phi) - y*sin(phi), x*sin(phi) + y*cos(phi)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    47
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    48
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    49
def project_to_meters(lat, lon, latm, lonm):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    50
    # azimuthal map projection centered at average track coordinate
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    51
    lon -= lonm
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    52
    xyz = latlonele_to_xyz(lat, lon, 0.0)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    53
    zy = rotate(xyz[2], xyz[1], radians(90 - latm))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    54
    lat2 = atan2(zy[0], la.norm([zy[1], xyz[0]]))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    55
    lon2 = atan2(xyz[0], -zy[1])
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    56
    x_meters = rE * sin(lon2) * (pi / 2.0 - lat2)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    57
    y_meters = -rE * cos(lon2) * (pi / 2.0 - lat2)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    58
    return x_meters, y_meters
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    59
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    60
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    61
def latlonele_to_xyz(lat, lon, ele):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    62
    s = sin(radians(lat))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    63
    c = cos(radians(lat))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    64
    r = ele + a * b / la.norm([s*a, c*b])
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    65
    lon = radians(lon)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    66
    return r * c * sin(lon), r * c * (-cos(lon)), r * s
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    67
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    68
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    69
def xyz_to_latlonele(x, y, z):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    70
    r = la.norm([x, y, z])
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    71
    if (r == 0):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    72
        return 0.0, 0.0, 0.0
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    73
    lat = degrees(atan2(z, la.norm([x, y])))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    74
    lon = degrees(atan2(x, -y))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    75
    ele = r * (1.0 - a * b / la.norm([a*z, b*x, b*y]))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    76
    return lat, lon, ele
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    77
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    78
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    79
############################## main function #################################
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    80
tracks = []
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    81
npoints = []
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    82
for fname in args:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    83
    # initialisations
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    84
    tracksegs = []
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    85
    sumx, sumy, sumz = 0.0, 0.0, 0.0
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    86
    ntot = 0    # total number of trackpoints (sum of segments)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    87
    
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    88
    # import xml data from files
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    89
    print 'opening file', fname
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    90
    infile = open(fname)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    91
    tree = etree.parse(infile)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    92
    infile.close()
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    93
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    94
    gpx = tree.getroot()
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    95
    nsurl = gpx.tag.split ('}')[0][1:]  # == 'http://www.topografix.com/GPX/1/1'
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    96
    etree.register_namespace('', nsurl) # default namespace -> xmlns:.... in the output
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    97
    nsmap = '{' + nsurl + '}'           # prefix for all tags in the tree
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    98
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
    99
    # extract data from xml
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   100
    for si, trkseg in enumerate (gpx.findall('.//' + nsmap + 'trkseg')):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   101
        trkpts = trkseg.findall(nsmap + 'trkpt')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   102
        n = len(trkpts)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   103
        
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   104
        # extract coordinate values
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   105
        lats = [float(trkpt.get('lat')) for trkpt in trkpts]
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   106
        lons = [float(trkpt.get('lon')) for trkpt in trkpts]
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   107
        eles = [float(trkpt.find(nsmap + 'ele').text) for trkpt in trkpts]
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   108
        try:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   109
            times = [datetime.datetime.strptime(trkpt.find(nsmap + 'time'
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   110
                                       ).text, timeformat) for trkpt in trkpts]
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   111
        except Exception as e:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   112
            print '-- trackpoint without time'
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   113
            times = None
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   114
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   115
        # save original trackseg for plotting
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   116
        tracksegs.append ([ (lats[i], lons[i], eles[i]) for i in range(n) ])
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   117
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   118
        # calculate projected points to work on
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   119
        for i in range(n):
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   120
            x, y, z = latlonele_to_xyz (lats[i], lons[i], eles[i])
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   121
            sumx += x
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   122
            sumy += y
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   123
            sumz += z
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   124
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   125
        print 'segment %d, with %d points:' % (si, n)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   126
        ntot += n
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   127
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   128
    tracks.append (tracksegs)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   129
    npoints.append ((fname.replace ('_','\_'), ntot))   # underscore -> subscripts in gnuplot
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   130
    print 'number of points in track %s = %d:' % (fname, ntot)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   131
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   132
latm, lonm, elesum = xyz_to_latlonele (sumx, sumy, sumz)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   133
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   134
data = []
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   135
xmin, xmax = ymin, ymax = float ('inf'), float ('-inf')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   136
for tracksegs in tracks:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   137
    for trkseg in tracksegs:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   138
        for lat, lon, ele in trkseg:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   139
            x, y = project_to_meters (lat, lon, latm, lonm)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   140
            data.append ('%f %f' % (x, y))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   141
            xmin, ymin = min (xmin, x), min (ymin, y)   # determine the x range
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   142
            xmax, ymax = max (xmax, x), max (ymax, y)   # and the y range
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   143
    data.append ('e')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   144
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   145
dx, dy = xmax - xmin, ymax - ymin   # make x and y ranges equal to the largest
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   146
if dx > dy:                         # and keep ranges centered
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   147
    dr = (dx - dy) / 2
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   148
    ymax += dr
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   149
    ymin -= dr
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   150
else:
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   151
    dr = (dy - dx) / 2
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   152
    xmax += dr
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   153
    xmin -= dr
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   154
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   155
from subprocess import Popen, PIPE
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   156
gnuPlotCmd = ['gnuplot']
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   157
plot = Popen (gnuPlotCmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   158
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   159
range = 'set xrange [%f:%f]\nset yrange [%f:%f]\n' % (xmin, xmax, ymin, ymax)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   160
plot.stdin.write (range)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   161
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   162
curves = ','.join ("'-' with linespoints ti '%s: %d punten'" % t for t in npoints)
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   163
plot.stdin.write ('plot ' + curves + '\n')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   164
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   165
plot.stdin.write ("\n".join (data))
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   166
plot.stdin.write ('\n')
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   167
plot.stdin.flush ()
1b96bb9de1f3 - eerste versie van gpx_plot
wim
parents:
diff changeset
   168
raw_input ('druk')