--- /dev/null
+__pycache__
+++ /dev/null
-#!/usr/bin/env python
-
-import mapnik
-
-import sys, os
-
-from lxml import html,etree
-from optparse import OptionParser
-
-from pprint import pprint
-
-import pygpx
-
-# Set up projections
-# spherical mercator (most common target map projection of osm data imported with osm2pgsql)
-merc = mapnik.Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over')
-
-# long/lat in degrees, aka ESPG:4326 and "WGS 84"
-longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
-# can also be constructed as:
-#longlat = mapnik.Projection('+init=epsg:4326')
-
-# ensure minimum mapnik version
-if not hasattr(mapnik,'mapnik_version') and not mapnik.mapnik_version() >= 600:
- raise SystemExit('This script requires Mapnik >=0.6.0)')
-
-
-def render_map(mapfile,map_uri,gpx_file,imgx,imgy):
-
- with open(gpx_file,'r') as f:
- data = f.read()
-
- xml = etree.fromstring(data)
- gpx = pygpx.GPX()
- gpx.ReadTree(xml)
-
- bbox = gpx.bound_box()
- pprint(bbox)
- cx=(bbox[0][1]+bbox[1][1])/2
- cy=(bbox[0][0]+bbox[1][0])/2
- print cx,cy
- w=(bbox[1][1]-bbox[0][1])*1.2
- h=(bbox[1][0]-bbox[0][0])*1.2
- print w,h
- bounds = (cx-w/2,cy-h/2,cx+w/2,cy+h/2)
- print bounds
-
- m = mapnik.Map(imgx,imgy)
- mapnik.load_map(m,mapfile)
-
- m.background = mapnik.Color('rgb(255,255,255)')
-
- # ensure the target map projection is mercator
- m.srs = merc.params()
-
- bbox = mapnik.Box2d(*bounds)
-
- pprint(bbox)
-
- transform = mapnik.ProjTransform(longlat,merc)
- merc_bbox = transform.forward(bbox)
- m.zoom_to_box(merc_bbox)
-
- style = mapnik.Style()
- rule = mapnik.Rule()
-
- line_symbolizer = mapnik.LineSymbolizer()
-
- line_symbolizer.stroke = mapnik.Color('rgb(0,0,127)')
- line_symbolizer.stroke_width = 4.0
- line_symbolizer.stroke_opacity = 0.5
-
- rule.symbols.append(line_symbolizer)
-
- style.rules.append(rule)
- m.append_style('GPS_tracking_points', style)
-
- layer = mapnik.Layer('GPS_tracking_points')
- layer.datasource = mapnik.Ogr(file=gpx_file, layer='tracks')
- layer.styles.append('GPS_tracking_points')
- m.layers.append(layer)
-
- im = mapnik.Image(imgx,imgy)
- mapnik.render(m, im)
- im.save(map_uri,'png')
- sys.stdout.write('output image to %s!\n' % map_uri)
-
-
-def render_all(db,mapfile,imgx,imgy):
-
- import sqlite3
- from os.path import dirname
-
- conn = sqlite3.connect(db)
- conn.text_factory = str
- cur = conn.cursor()
- updcur = conn.cursor()
-
- cur.execute ("select id,filename from tracks where preview_name is null")
-
- list=cur.fetchall()
-
- for rec in list:
-
- id = rec[0]
- filename = rec[1]
- preview_name = dirname(filename) + '/' + str(id) + '.png'
-
- print id,filename,preview_name
-
- try:
- render_map(mapfile,preview_name.encode('utf8'),filename,imgx,imgy)
- updcur.execute("update tracks set preview_name=? where id=?", (preview_name,id))
- conn.commit()
- except:
- raise
-
-
-def main():
-
- parser = OptionParser()
- parser.add_option("-m", "--map", dest="mapfile",
- help="use map file", metavar="MAP")
- parser.add_option("-o", "--output", dest="outfile",
- help="output image to file", metavar="OUT")
- parser.add_option("-g", "--gpx", dest="gpxfile",
- help="track to render", metavar="GPX")
- parser.add_option("-x", "--x-size", dest="x",
- help="image width", metavar="X")
- parser.add_option("-y", "--y-size", dest="y",
- help="image height", metavar="Y")
- parser.add_option("-d", "--db", dest="db",
- help="render all not process files in database", metavar="DB")
- (options, args) = parser.parse_args()
-
- if options.mapfile:
- mapfile = options.mapfile
- else:
- mapfile = "/etc/mapnik-osm-carto-data/veloroad-imposm.xml"
-
- if options.outfile:
- map_uri = options.outfile
- else:
- map_uri = "image.png"
-
- if options.x:
- imgx = int(options.x)
- else:
- imgx= 640
- if options.y:
- imgy = int(options.y)
- else:
- imgy= 640
-
- if options.db:
- render_all(options.db,mapfile,imgx,imgy)
- else:
- if options.gpxfile:
- gpx_file = options.gpxfile
- render_map(mapfile,map_uri,gpx_file,imgx,imgy)
- else:
- print "No input file"
- exit(1)
-
-if __name__ == "__main__":
-
- main()
+++ /dev/null
-#!/usr/bin/env python
-# coding: UTF-8
-
-import sys
-import os
-from lxml import etree
-from urllib2 import unquote
-import pygpx
-import pygeocode
-import sqlite3
-import datetime
-
-def check_db_for_training(db,sport,timestamp):
-
- conn = sqlite3.connect(db)
- conn.text_factory = str
- cur = conn.cursor()
-
- cur.execute ("select count(*) from tracks where sport=? and start_time=?" , (sport,timestamp))
- return cur.fetchall()[0][0]
-
-def write_parsed_to_db(db,gpx,filename):
-
- conn = sqlite3.connect(db)
- conn.text_factory = str
- cur = conn.cursor()
-
- if type(filename) is str:
- filename=filename.decode('UTF-8')
-
- cur.execute ("delete from tracks where filename=?" , (filename,))
-
- tracks = gpx.tracks
-
- for track in tracks:
-
- try:
- author = gpx.author
- except:
- author = None
-
- try:
- name = gpx.name
- if type(name) is str:
- name=name.decode('UTF-8')
- except:
- name = None
-
- if author:
- try:
- cur.execute("insert into authors(name,description) values(?,?)", (author,''))
- print "created author %s" % (author)
- except:
- print "failed to create author %s" % (author)
- pass
-
- try:
-
- print "processing..."
- start = track.start()
- if start:
- printable = pygeocode.GeoName(start.lat,start.lon).printable
- start_time = track.start_time()
- full_duration = track.full_duration().total_seconds()
- distance = track.distance()
- filtered_distance = track.filtered_distance(max_speed=50)
- ascent = track.elevation_gain()
- descent = track.elevation_loss()
- ((minlat,minlon),(maxlat,maxlon)) = track.bound_box()
- params = (
- gpx.author,name,filename,
- track.sport,start_time,full_duration,
- distance,filtered_distance,ascent,descent,
- start.lat,start.lon,
- printable,
- minlat,minlon,maxlat,maxlon
- )
- print(params)
- cur.execute("""
- insert into tracks(
- author,name,filename,sport,
- start_time,duration,
- distance,distance_filtered,
- ascent,descent,
- lat,lon,printable_location,minlat,minlon,maxlat,maxlon)
- values(
- ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
- """
- , params )
- conn.commit()
- print "created track %s" % (filename)
-
- except:
-
- raise
-
-def write_tree_to_db(db,tree,filename):
-
- gpx = pygpx.GPX()
- gpx.ReadTree(tree)
-
- write_parsed_to_db(db,gpx,filename)
-
-def print_parsed_file(filename):
-
- gpx = pygpx.GPX()
- gpx.ReadFile(filename)
-
- for track in gpx.tracks:
-
- try:
- author = gpx.author
- except:
- author = None
-
- try:
- name = gpx.name
- except:
- name = None
-
- start = track.start()
- if start:
- printable = pygeocode.GeoName(start.lat,start.lon).printable
- start_time = track.start_time()
- full_duration = track.full_duration().total_seconds()
- distance = track.distance()
- filtered_distance = track.filtered_distance(max_speed=50)
- ascent = track.elevation_gain()
- descent = track.elevation_loss()
- ((minlat,minlon),(maxlat,maxlon)) = track.bound_box()
- params = (
- gpx.author,name,filename.decode('UTF-8'),
- track.sport,start_time,full_duration,
- distance,filtered_distance,ascent,descent,
- start.lat,start.lon,
- printable,
- minlat,minlon,maxlat,maxlon
- )
- print(params)
+++ /dev/null
-# coding=UTF-8
-"""
-nominatim.openstreetmap.org API
-"""
-
-import urllib2
-
-def GetDescr(lat,lon):
-
- reqstr = "http://maps.rvb.name/geocode.php?lat=%s&lon=%s" %(lat,lon)
- headers = { 'User-Agent' : 'PyRunGPS/1.0', 'Referer' : 'https://maps.rvb.name' }
- req = urllib2.Request(reqstr, None, headers)
- page = urllib2.urlopen(req).read()
-
- return page
-
-class GeoName:
-
- def __init__(self, lat, lon):
-
- self.printable = GetDescr(lat,lon)
-
\ No newline at end of file
+++ /dev/null
-# coding: UTF-8
-#------------------------
-# Работа с GPX-файлами
-#------------------------
-from lxml import etree
-import os
-import math
-import datetime
-from dateutil.parser import parse
-from pprint import pprint
-
-def deg2rad(deg):
-# Преобразование из градусов в радианы.
- return deg / (180 / math.pi)
-
-tagprefix = { '1.0': '{http://www.topografix.com/GPX/1/0}', '1.1': '{http://www.topografix.com/GPX/1/1}'}
-
-def StripPrefix(tag,version):
- nstag=tagprefix[version]
- return tag.replace(nstag,'')
-
-def formattime(dt):
- return dt.strftime("%Y-%m-%dT%H:%M:%S")+"."+str(int(dt.microsecond/1000)).zfill(3)+"Z"
-
-class Link:
- # Ссылка. Может присутствовать в точке, треке, файле.
- def __init__(self, node, version):
- self.version = version
- self.href = node.get("href")
- self.text = None
- self.type = None
- if node is not None:
- for child in node:
- if child.tag == tagprefix[version] + "text":
- self.text = child.text
- elif child.tag == tagprefix[version] + "type":
- self.type = child.text
- else:
- raise ValueError("Неизвестный тип узла: '%s' " % child.tag)
-
- def write(self,root):
- linknode = etree.SubElement(root,"link");
- linknode.set("href",self.href)
- if self.text:
- etree.SubElement(linknode,"text").text = self.text
- if self.type:
- etree.SubElement(linknode,"type").text = self.type
-
-class GPXTrackPt:
- # Точка с координатами. Может присутствовать в последовательности точек в треке, маршруте, а также в списке путевых точек.#
-
- def __init__(self, node, version):
- # Извлекаем данные из GPX-тэгов.#
- self.version = version
- # Сначала обязательные.#
- if node is not None:
- self.lat = float(node.get("lat"))
- self.lon = float(node.get("lon"))
- self.elevation = None
- self.time = None
- self.speed = None
- self.link = None
- self.additional_info = {}
- # Потом необязательные.#
- if node is not None:
- for child in node:
- if child.tag == tagprefix[version] + "time":
- self.time = parse(child.text)
- elif child.tag == tagprefix[version] + "ele":
- self.elevation = float(child.text)
- # Стандартом скорость не предусмотрена, но де-факто в Run.GPS используется.#
- elif child.tag == tagprefix[version] + "speed":
- self.speed = float(child.text)
- elif child.tag == tagprefix[version] + "link":
- self.link = Link(child,version)
- elif StripPrefix(child.tag,version) in ['magvar','geoidheight','name','cmt','desc',
- 'src','sym','type','fix','sat','hdop','vdop','pdop','ageofdgpsdata','dgpsid']:
- self.additional_info[StripPrefix(child.tag,version)]=child.text
- elif child.tag == tagprefix[version] + "extensions":
- pass
- else:
- raise ValueError("Неизвестный тип узла: '%s'" % child.tag)
-
- for i in self.additional_info.keys():
- val = self.additional_info[i];
- if val:
- if not val.strip(' \n\t'):
- del self.additional_info[i]
-
-
- def write(self,root,tag ="wpt"):
- wptnode = etree.SubElement(root,tag)
- wptnode.set("lat",repr(self.lat));
- wptnode.set("lon",repr(self.lon));
- if self.elevation:
- etree.SubElement(wptnode,"ele").text = repr(self.elevation)
- if self.time:
- etree.SubElement(wptnode,"time").text = formattime(self.time)
- if self.speed:
- etree.SubElement(wptnode,"speed").text = repr(self.speed)
- if self.link:
- self.link.write(wptnode)
- for i in self.additional_info.keys():
- etree.SubElement(wptnode,i).text = self.additional_info[i]
-
- def distance(self, other):
- # Расстояние между двумя точками на глобусе.#
- try:
- # http://www.platoscave.net/blog/2009/oct/5/calculate-distance-latitude-longitude-python/
-
- radius = 6378700.0 # meters
-
- lat1, lon1 = self.lat, self.lon
- lat2, lon2 = other.lat, other.lon
-
- dlat = math.radians(lat2-lat1)
- dlon = math.radians(lon2-lon1)
- a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
- * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
- c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
- d = radius * c
-
- except ValueError, e:
- raise ValueError(e)
- return d
-
- def duration(self, other):
- # Время между двумя точками.#
- return other.time - self.time
-
-class GPXRoute:
- # Маршрут.#
-
- def __init__(self, node, version):
- self.name = None
- self.version = version
- self.rtepts = []
- self.additional_info = {}
- self.link = None
- if node is not None:
- for child in node:
- if child.tag == tagprefix[version] + "name":
- self.name = child.text
- elif child.tag == tagprefix[version] + "link":
- self.link = Link(child,version)
- elif StripPrefix(child.tag,version) in [ "cmt", "desc", "src", "number", "type" ]:
- self.additional_info[StripPrefix(child.tag,version)]=child.text
- elif child.tag == tagprefix[version] + "rtept":
- self.rtepts.append(GPXTrackPt(child, version))
- elif child.tag == tagprefix[version] + "extensions":
- pass
- else:
- raise ValueError("Неизвестный тип узла <%s>" % child.tag)
- for i in self.additional_info.keys():
- val = self.additional_info[i];
- if val:
- if not val.strip(' \n\t'):
- del self.additional_info[i]
-
- def write(self,root):
- rtenode = etree.SubElement(root,"rte")
- if self.name:
- etree.SubElement(rtenode,"name").text = self.name
- if self.link:
- self.link.write(rtenode)
- for i in self.additional_info.keys():
- print "storing %s " % ( i )
- etree.SubElement(rtenode,i).text = self.additional_info[i]
- for i in self.rtepts:
- i.write(rtenode,"rtept")
-
-class GPXTrackSeg:
- # Один сегмент трека.#
-
- def __init__(self, node, version):
- self.version = version
- self.trkpts = []
- self.elevation_gain = 0.0
- self.elevation_loss = 0.0
- if node is not None:
- for child in node:
- if child.tag == tagprefix[version] + "trkpt":
- self.trkpts.append(GPXTrackPt(child, self.version))
- else:
- raise ValueError("Неизвестный тип узла <%s>" % node.nodeName)
- self._get_elevation()
-
- def write(self,root):
- trksegnode = etree.SubElement(root,"trkseg")
- for i in self.trkpts:
- i.write(trksegnode,"trkpt")
-
- def _get_elevation(self):
-
- elev_data = []
- for pt in self.trkpts:
- if pt.elevation:
- elev_data.append(pt.elevation)
-
- gain = 0.0
- loss = 0.0
- last_elevation = None
-
- window_size = 5
- i = 0
- moving_averages = []
-
- while i < len(elev_data) - window_size + 1:
- this_window = elev_data[i : i + window_size]
- window_average = sum(this_window) / window_size
- moving_averages.append(window_average)
- i += 1
-
- if len(moving_averages)>2:
- elev_data = moving_averages
-
- for pt in elev_data:
- if last_elevation is not None:
- try:
- if pt > last_elevation:
- gain += pt - last_elevation
- else:
- loss += last_elevation - pt
- except:
- pass
- last_elevation=pt
-
- self.elevation_gain = gain
- self.elevation_loss = loss
-
- def distance(self):
- # Расчет длины сегмента.#
- _length = 0.0
- last_pt = None
- for pt in self.trkpts:
- if last_pt is not None:
- _length += last_pt.distance(pt)
- last_pt = pt
- return _length
-
- def filtered_distance(self,max_speed):
- # Расчет длины сегмента с фильтрацией предположительно сбойных участков.#
- _length = 0.0
- last_pt = None
- for pt in self.trkpts:
- if last_pt is not None:
- _delta = last_pt.distance(pt)
- _time_delta = pt.time - last_pt.time
- _time_delta_s = _time_delta.days*86400 + _time_delta.seconds + _time_delta.microseconds/1000000
- if _time_delta_s > 0:
- if _delta/_time_delta_s < max_speed:
- _length += _delta
- else:
- _length += _delta
- last_pt = pt
- return _length
-
- def duration(self):
- # Расчет продолжительности сегмента.#
- return self.trkpts[0].duration(self.trkpts[-1])
-
- def bound_box(self):
- # Обрамляющий прямоугольник для сегмента.#
- minlat =360
- maxlat = -360
- minlon = 360
- maxlon = -360
- for pt in self.trkpts:
- if pt.lat<minlat:
- minlat=pt.lat
- if pt.lat>maxlat:
- maxlat=pt.lat
- if pt.lon<minlon:
- minlon=pt.lon
- if pt.lon>maxlon:
- maxlon=pt.lon
- return ((minlat,minlon),(maxlat,maxlon))
-
-class GPXTrack:
- # Трек.#
-
- def __init__(self, node, version):
- # Создаем трек из GPX-данных.#
-
- self.version = version
- self.trksegs = []
- self.sport= None
- self.additional_info = {}
- self.name = None
- self.link = None
-
- if node is not None:
- for child in node:
- if child.tag == tagprefix[version] + "name":
- self.name = child.text
- elif child.tag == tagprefix[version] + "trkseg":
- if len(child) > 0:
- self.trksegs.append(GPXTrackSeg(child, self.version))
- elif child.tag == tagprefix[version] + "link":
- self.link = Link(child,version)
- elif StripPrefix(child.tag,version) in [ "number", "desc", "cmt", "src", "type" ]:
- self.additional_info[StripPrefix(child.tag,version)] = child.text
- elif child.tag == tagprefix[version] + "extensions":
- for ext in child:
- # Из расширений извлекаем вид спорта - специфично для Run.GPS.#
- if ext.tag == tagprefix[version] + "sport":
- self.sport = ext.text
-
- for i in self.additional_info.keys():
- val = self.additional_info[i];
- if val:
- if not val.strip(' \n\t'):
- del self.additional_info[i]
-
- def write(self,root):
- trknode = etree.SubElement(root,"trk")
- if self.name:
- etree.SubElement(trknode,"name").text = self.name
- if self.sport:
- etree.SubElement(etree.SubElement(trknode,"extensions"),"sport").text=self.sport
- if self.link:
- self.link.write(trknode)
- for i in self.additional_info.keys():
- etree.SubElement(trknode,i).text = self.additional_info[i]
- for i in self.trksegs:
- i.write(trknode)
-
- def elevation_gain(self):
- # Набор высоты по треку.#
- return sum([trkseg.elevation_gain for trkseg in self.trksegs])
-
- def elevation_loss(self):
- # Сброс высоты по треку.#
- return sum([trkseg.elevation_loss for trkseg in self.trksegs])
-
- def distance(self):
- # Длина трека.#
- try:
- return sum([trkseg.distance() for trkseg in self.trksegs])
- except IndexError:
- print "Пустой сегмент трека, расчет длины невозможен."
-
- def filtered_distance(self,max_speed=100):
- # Длина трека с фильтрацией сбойных участков.#
- try:
- return sum([trkseg.filtered_distance(max_speed=max_speed) for trkseg in self.trksegs])
- except IndexError:
- print "Пустой сегмент трека, расчет длины невозможен."
-
- def duration(self):
- # Продолжительность трека, не включая паузы между сегментами.#
- dur = datetime.timedelta(0)
- for trkseg in self.trksegs:
- try:
- dur += trkseg.duration()
- except:
- pass
- return dur
-
- def full_duration(self):
- # Продолжительность трека, включая паузы между сегментами.#
- try:
- return self.start().duration(self.end())
- except:
- return None
-
- def start(self):
- # Стартовая точка.#
- try:
- return self.trksegs[0].trkpts[0]
- except IndexError:
- return None
-
- def end(self):
- # Финишная точка.#
- try:
- return self.trksegs[-1].trkpts[-1]
- except IndexError:
- return None
-
- def start_time(self):
- # Время старта.#
- try:
- return self.start().time
- except:
- return None
-
- def end_time(self):
- # Время финиша.#
- try:
- return self.end().time
- except:
- return None
-
- def bound_box(self):
- # Обрамляющий прямоугольник для всего трека.#
- minlat =360
- maxlat = -360
- minlon = 360
- maxlon = -360
- for trkseg in self.trksegs:
- for pt in trkseg.trkpts:
- if pt.lat<minlat:
- minlat=pt.lat
- if pt.lat>maxlat:
- maxlat=pt.lat
- if pt.lon<minlon:
- minlon=pt.lon
- if pt.lon>maxlon:
- maxlon=pt.lon
- return ((minlat,minlon),(maxlat,maxlon))
-
-
-class GPX:
- # Работа с GPX-документами.#
-
- def __init__(self):
- # Создание пустого GPX-объекта#
- PATH = os.path.dirname(__file__)
- self.creator = None
- self.time = None
- self.tracks = []
- self.routes = []
- self.waypoints = []
- self.version = ""
- self.author = None
- self.name = None
- self.link = None
- self.copyright = None
- self.meta = {}
-
- def ReadTree(self,tree):
- # Загрузка из дерева etree.#
- root = tree
-
- # Test if this is a GPX file or not and if it's version 1.1
- if root.tag == "{http://www.topografix.com/GPX/1/1}gpx" and root.get("version") == "1.1":
- self.version = "1.1"
- elif root.tag == "{http://www.topografix.com/GPX/1/0}gpx" and root.get("version") == "1.0":
- self.version = "1.0"
- elif root.get("version") not in [ "1.1", "1.0"]:
- raise ValueError("Версия формата %s не поддерживается. Используйте GPX 1.1." % root.get("version"))
- else:
- raise ValueError("Неизвестный формат дерева")
- # attempt to validate the xml file against the schema
-
- # initalize the GPX document for parsing.
- self._init_version(root)
-
-
- def ReadFile(self, fd):
- # Загрузка из файла.#
- gpx_doc = etree.parse(fd)
- root = gpx_doc.getroot()
-
- # Test if this is a GPX file or not and if it's version 1.1
- if root.tag == "{http://www.topografix.com/GPX/1/1}gpx" and root.get("version") == "1.1":
- self.version = "1.1"
- elif root.tag == "{http://www.topografix.com/GPX/1/0}gpx" and root.get("version") == "1.0":
- self.version = "1.0"
- elif root.get("version") not in [ "1.1", "1.0"]:
- raise ValueError("Версия формата %s не поддерживается. Используйте GPX 1.1." % root.get("version"))
- else:
- raise ValueError("Неизвестный формат файла")
- # initalize the GPX document for parsing.
- self._init_version(root)
-
- def _init_version(self,root):
- # Инициализация объекта.#
- self.creator = root.get("creator")
- if root is not None:
- for child in root:
- if child.tag == tagprefix[self.version] + "author":
- self.author = child.text
- elif child.tag == tagprefix[self.version] + "trk":
- self.tracks.append(GPXTrack(child, self.version))
- elif child.tag == tagprefix[self.version] + "rte":
- self.routes.append(GPXRoute(child, self.version))
- elif child.tag == tagprefix[self.version] + "wpt":
- self.waypoints.append(GPXTrackPt(child, self.version))
- elif child.tag == tagprefix[self.version] + "metadata":
- for meta in child:
- if meta.tag == tagprefix[self.version] + "author":
- self.author = meta.text
- elif meta.tag == tagprefix[self.version] + "name":
- self.name = meta.text
- elif meta.tag == tagprefix[self.version] + "bounds":
- # Границы пропускаем - их будем вычислять сами заново
- pass
- elif meta.tag == tagprefix[self.version] + "copyright":
- self.copyright = meta.text
- elif meta.tag == tagprefix[self.version] + "link":
- self.link = Link(meta,self.version)
- else:
- self.meta[StripPrefix(meta.tag,self.version)]=meta.text
-
- for i in self.meta.keys():
- val = self.meta[i];
- if val:
- if not val.strip(' \n\t'):
- del self.meta[i]
-
- def elevation_gain(self):
- # Суммарный набор высоты.#
- return sum([track.elevation_gain() for track in self.tracks])
-
- def elevation_loss(self):
- # Суммарная потеря высоты.#
- return sum([track.elevation_loss() for track in self.tracks])
-
- def distance(self):
- # Суммарная дистанция.#
- try:
- return sum([track.distance() for track in self.tracks])
- except IndexError:
- print "Пустой файл!"
-
- def filtered_distance(self):
- # Суммарная дистанция с фильтрацией сбойных данных.#
- try:
- return sum([track.filtered_distance() for track in self.tracks])
- except IndexError:
- print "Пустой файл!"
-
- def duration(self):
- # Суммарная продолжительность, не включая паузы.#
- dur = datetime.timedelta(0)
- for track in self.tracks:
- dur += track.duration()
- return dur
-
- def full_duration(self):
- # Суммарная продолжительность, включая паузы#
- if hasattr(self.start(), 'duration'):
- return self.start().duration(self.end())
- else:
- return None
-
- def start(self):
- # Точка старта.#
- return self.tracks[0].start()
-
- def end(self):
- # Точка финиша.#
- return self.tracks[-1].end()
-
- def start_time(self):
- # Время старта.#
- if self.start():
- return self.start().time
- else:
- return None
-
- def end_time(self):
- # Время финиша.#
- return self.end().time
-
- def bound_box(self):
- # Обрамляющий прямоугольник для всех треков в файле.#
- minlat =360
- maxlat = -360
- minlon = 360
- maxlon = -360
- for track in self.tracks:
- for trkseg in track.trksegs:
- for pt in trkseg.trkpts:
- if pt.lat<minlat:
- minlat=pt.lat
- if pt.lat>maxlat:
- maxlat=pt.lat
- if pt.lon<minlon:
- minlon=pt.lon
- if pt.lon>maxlon:
- maxlon=pt.lon
- return ((minlat,minlon),(maxlat,maxlon))
-
- def FixNames(self,linkname):
- pprint(linkname)
- pprint(type(linkname))
- if type(linkname) is unicode:
- goodname=linkname
- else:
- goodname = linkname.decode('UTF-8')
- badname = goodname.encode('ascii','replace')
- if self.name and self.name.startswith(badname):
- self.name=self.name.replace(badname,goodname)
- for i in self.tracks:
- if i.name and i.name.startswith(badname):
- i.name = i.name.replace(badname,goodname)
-
- def ProcessTrackSegs(self,seconds_gap=120):
- for tr in self.tracks:
- # Объединяем все точки трека в единую последовательность
- all_trackpoints = []
- for trseg in tr.trksegs:
- all_trackpoints.extend(trseg.trkpts)
- new_segs = []
- current_seg = None
- prev_pt = None
- for pt in all_trackpoints:
- if not current_seg:
- # Начало нового сегмента
- current_seg = GPXTrackSeg(None,self.version)
- current_seg.trkpts.append(pt)
- else:
- delta = pt.time - prev_pt.time
- if delta.days > 0 or delta.seconds > seconds_gap:
- # Нашли место разрыва
- new_segs.append(current_seg)
- current_seg = None
- else:
- current_seg.trkpts.append(pt)
- prev_pt=pt
- # Если есть, что закинуть в хвост - пишем
- if current_seg is not None:
- new_segs.append(current_seg)
- # Обработали
- for trs in new_segs:
- trs._get_elevation()
- tr.trksegs = new_segs
-
-
- def XMLTree(self):
- root = etree.Element("gpx", attrib ={"creator": "pygpx",
- "version": "1.1",
- "xmlns": "http://www.topografix.com/GPX/1/1"});
-
- # meta subtree
-
- meta = etree.SubElement( root, "metadata" );
- if self.name:
- metarecord = etree.SubElement( meta, "name" )
- metarecord.text = self.name
- if self.author:
- metarecord = etree.SubElement( meta, "author" )
- metarecord.text = self.author
- if self.copyright:
- metarecord = etree.SubElement( meta, "copyright" )
- metarecord.text = self.copyright
- if self.link:
- self.link.write(meta)
- for metatag in self.meta.iterkeys():
- metarecord = etree.SubElement( meta, metatag )
- metarecord.text = self.meta[metatag]
-
- # wpts subtree
-
- for i in self.waypoints:
- i.write(root)
-
- # routes subtree
-
- for i in self.routes:
- i.write(root)
-
- # tracks subtree
-
- for i in self.tracks:
- i.write(root)
-
- return root
-
\ No newline at end of file
+++ /dev/null
-# coding=UTF-8
-"""
-nominatim.openstreetmap.org API
-"""
-
-import urllib2
-from lxml import etree
-
-def GetXMLDescr(lat,lon):
-
- reqstr = "http://nominatim.openstreetmap.org/reverse?lat=%s&lon=%s&accept-language=ru,en" %(lat,lon)
- print reqstr
- headers = { 'User-Agent' : 'PyRunGPS/1.0', 'Referer' : 'https://maps.rvb.name' }
- req = urllib2.Request(reqstr, None, headers)
- page = urllib2.urlopen(req).read()
-
- return etree.fromstring(page)
-
-def printable_name(addr):
-
- if 'country' in addr:
- if 'state' in addr:
- if addr['country'] == u"Российская Федерация" and addr['state'] == u"Москва":
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['state'] + ', ' + addr['country']
- else:
- if 'city' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['city'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['city'] + ', ' + addr['state'] + ', ' + addr['country']
- elif 'town' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['town'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['town'] + ', ' + addr['state'] + ', ' + addr['country']
- elif 'village' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['village'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['village'] + ', ' + addr['state'] + ', ' + addr['country']
- elif 'county' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['county'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['county'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['state'] + ', ' + addr['country']
- else:
- str = addr['state'] + ', ' + addr['country']
- else:
- if 'city' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['city'] + ', ' + addr['country']
- else:
- str = addr['city'] + ', ' + addr['country']
- elif 'village' in addr:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['village'] +', ' + addr['country']
- else:
- str = addr['village'] + ', ' + addr['country']
- else:
- if 'road' in addr:
- str = addr['road'] + ', ' + addr['country']
- else:
- str = addr['country']
- else:
- str = u"Планета Земля, "
- if addr['lat'] > 0:
- str = str + u"%s с.ш.," % (addr['lat'])
- else:
- str = str + u"%s ю.ш.," % (-addr['lat'])
- if addr['lon'] > 0:
- str = str + u"%s в.д." % (addr['lon'])
- else:
- str = str + u"%s з.д." % (-addr['lon'])
-
- return str
-
-class GeoName:
-
- def __init__(self, lat, lon):
-
- for elem in GetXMLDescr(lat,lon):
- self.addr = {'lat':lat,'lon':lon}
- self.road = ''
- self.city = ''
- self.country = ''
-
- if elem.tag == "addressparts":
- for addrpart in elem:
- tag = addrpart.tag
- text = urllib2.unquote(addrpart.text)
- self.addr[tag] = text
- if tag == "road":
- self.road = text
- elif tag == "city":
- self.city = text
- elif tag == "country":
- self.country = text
-
- self.printable = printable_name(self.addr)
-
-
\ No newline at end of file
+++ /dev/null
-#!/usr/bin/python pyrungps.py
+++ /dev/null
-#!/usr/bin/env python
-# coding: UTF-8
-
-import requests
-
-from urllib3.exceptions import InsecureRequestWarning
-requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
-
-#import sys
-import os
-from urllib2 import quote,unquote
-from lxml import html,etree
-from optparse import OptionParser
-from datetime import date,datetime
-from mx.DateTime.ISO import ParseDateTimeUTC
-from parsegpx import write_parsed_to_db,check_db_for_training
-import pygpx
-
-from tempfile import NamedTemporaryFile
-
-from pprint import pprint
-
-import render_tiles
-
-import generate_image
-
-def get_page(uname,year,month):
-
- trainings = []
-
- req = requests.get("http://www.gps-sport.net/services/getMonthlyTrainingDataHTML_V2.jsp?userName=%s&year=%s&month=%s&rnd=0.645673"% (uname,year,month), headers = {'User-agent': 'Mozilla/5.0'}, verify=False)
- page = req.text.encode('utf-8')
- dom = html.document_fromstring(page)
-
- for element, attribute, link, pos in dom.iterlinks():
- if attribute == "href":
- if link.startswith("/trainings/"):
- dummy, dummy, link = link.split('/')
- name, id = link.split('_')
- trainings.append([ unquote(name), id ])
-
- return trainings
-
-def get_gpx_track(trid,name):
-
- print "trid=",trid
-
- req = requests.get("http://www.gps-sport.net/services/trainingGPX.jsp?trainingID=%s&tz=-180" % (trid), verify=False)
- xml = etree.fromstring(req.text.encode('utf-8'))
-
- return xml
-
-def get_osm_list(username,password,year,month):
-
- url = "https://www.openstreetmap.org/api/0.6/user/gpx_files"
-
- req = requests.get(url,auth=(username,password))
-
- xml = etree.fromstring(req.text.encode('utf-8'))
-
- res=[]
-
- for gpx_file in xml:
- attrib = dict(gpx_file.attrib)
- try:
- timestamp=datetime.fromtimestamp(ParseDateTimeUTC(attrib['timestamp']))
- id = attrib['id']
- description=None
- for descr in gpx_file.iter('description'):
- description=descr.text
- sport=None
- for tag in gpx_file.iter('tag'):
- sport=tag.text
- if timestamp.year==year and timestamp.month==month and description=='Run.GPS Track':
- record={ 'id': id, 'sport': sport }
- res.append(record)
- except:
- None
-
- return res
-
-def get_osm_gpx(username,password,track_id):
-
- url = "https://www.openstreetmap.org/api/0.6/gpx/"+track_id+"/data"
-
- req = requests.get(url,auth=(username,password))
- xml = etree.fromstring(req.text.encode('utf-8'))
-
- return xml
-
-def get_db_gpx(dbx,track_id):
-
- md, res = dbx.files_download(track_id)
-
- fs = NamedTemporaryFile(suffix='.tcx',delete = False)
- tmp_tcx_name=fs.name
- fs.write(res.content)
- fs.close()
- fs = NamedTemporaryFile(suffix='.gpx',delete = False)
- tmp_gpx_name=fs.name
- fs.close()
-
- os.system("gpsbabel -i gtrnctr -f "+tmp_tcx_name+" -o gpx -F "+tmp_gpx_name)
-
- with open (tmp_gpx_name, "r") as gpxfile:
- data=gpxfile.read()
-
- os.remove(tmp_gpx_name)
- os.remove(tmp_tcx_name)
-
- xml = etree.fromstring(data.encode('utf-8'))
- return xml
-
-def get_dbx_list(dbx,username,year,month):
-
- gpx_list_id = None
-
- for entry in dbx.files_list_folder('').entries:
- if entry.name == u'Приложения':
- for entry_app in dbx.files_list_folder(entry.id).entries:
- if entry_app.name == u'Run.GPS':
- print "id="+entry_app.id
- gpx_list_id=entry_app.id
- break
- break
-
- res = []
-
- if gpx_list_id:
-
- for file in dbx.files_list_folder(gpx_list_id).entries:
-
- filename,ext = os.path.splitext(file.name)
- if ext == '.tcx':
- try:
- fyear = int(filename[0:4])
- fmonth = int(filename[5:7])
- if fyear == year and fmonth == month:
- sport = filename[41:]
- timestamp = datetime.strptime(filename[0:19],'%Y-%m-%dT%H_%M_%S')
- record={ 'id': file.id, 'timestamp': timestamp, 'sport': sport }
- res.append(record)
- except:
- try:
- fyear = int(filename[0:4])
- fmonth = int(filename[5:7])
- if fyear == year and fmonth == month:
- sport = filename[18:]
- timestamp = datetime.strptime(filename[0:16],'%Y-%m-%d_%H%M%S')
- record={ 'id': file.id, 'timestamp': timestamp, 'sport': sport }
- res.append(record)
- except:
- None
-
- return res
-
-
-def sync_db(dbx,username,year,month,dir=".",verbose=False,force=False):
-
- training_list = get_dbx_list(dbx,username,year,month)
-
- for training in training_list:
-
- filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,month,training['sport'],training['id'][3:])
- dirname = "%s/%04d/%02d" % (dir,year,month)
-
- if os.path.exists(filename) and not force:
-
- if verbose:
- print "training %s exists, skipping" % (filename)
-
- else:
-
- try:
- os.makedirs(dirname)
- except:
- None
-
- xml = get_db_gpx(dbx,training['id'])
-
- if verbose:
- print "writing training %s" % (filename)
-
- gpx = pygpx.GPX()
- gpx.ReadTree(xml)
-
- sport = training['sport']
- timestamp = gpx.tracks[0].start_time()
-
- print sport, timestamp
-
- if check_db_for_training(db,sport,timestamp):
- print "The same training found"
- continue
-
- gpx.author = username
- gpx.FixNames(training['sport'])
- gpx.ProcessTrackSegs()
- for track in gpx.tracks:
- track.sport=training['sport']
-
- xml = gpx.XMLTree();
- f = open(filename,"w")
- f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
- f.close
- write_parsed_to_db(db,gpx,filename)
- try:
- render_tiles.queue_render(db,filename)
- except:
- None
-
-
-def sync_osm(username,password,year,month,dir=".",verbose=False,force=False):
-
- training_list = get_osm_list(username,password,year,month)
-
- for training in training_list:
-
- filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,month,training['sport'],training['id'])
- dirname = "%s/%04d/%02d" % (dir,year,month)
-
- if os.path.exists(filename) and not force:
-
- if verbose:
- print "training %s exists, skipping" % (filename)
-
- else:
-
- try:
- os.makedirs(dirname)
- except:
- None
-
- xml = get_osm_gpx(username,password,training['id'])
-
- if verbose:
- print "writing training %s" % (filename)
-
- gpx = pygpx.GPX()
- gpx.ReadTree(xml)
-
- sport = training['sport']
- timestamp = gpx.tracks[0].start_time()
-
- if check_db_for_training(db,sport,timestamp):
- print "The same training found"
- continue
-
- gpx.author = username
- gpx.FixNames(training['sport'])
- gpx.ProcessTrackSegs()
- for track in gpx.tracks:
- track.sport=training['sport']
-
- xml = gpx.XMLTree();
- f = open(filename,"w")
- f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
- f.close
- write_parsed_to_db(db,gpx,filename)
- try:
- render_tiles.queue_render(db,filename)
- except:
- None
-
-def sync_folder(username,year,month,dir=".",verbose=False,force=False):
-
- training_list = get_page(username,year,month)
- for tr in training_list:
- try:
-
- filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,(month+1),tr[0],tr[1])
- dirname = "%s/%04d/%02d" % (dir,year,(month+1))
-
- if os.path.exists(filename) and not force:
-
- if verbose:
- print "training %s exists, skipping" % (filename)
-
- else:
-
- try:
- os.makedirs(dirname)
- except:
- None
-
- xml=get_gpx_track(tr[1],tr[0])
-
- if verbose:
- print "writing training %s" % (filename)
-
- gpx = pygpx.GPX()
- gpx.ReadTree(xml)
-
- sport = tr[0]
- timestamp = gpx.tracks[0].start_time()
-
- if check_db_for_training(db,sport,timestamp):
- print "The same training found"
- continue
-
- gpx.FixNames(tr[0])
- gpx.ProcessTrackSegs()
-
- xml = gpx.XMLTree();
- f = open(filename,"w")
- f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
- f.close
- write_parsed_to_db(db,gpx,filename)
- try:
- render_tiles.queue_render(db,filename)
- except:
- None
-
- except:
- raise
-
-def main():
-
- global db;
- parser = OptionParser()
- parser.add_option("-d", "--dir", dest="dirname",
- help="write data to directory", metavar="DIR")
- parser.add_option("-q", "--quiet",
- action="store_false", dest="verbose", default=True,
- help="don't print status messages to stdout")
- parser.add_option("-f", "--force",
- action="store_true", dest="force", default=False,
- help="rewrite all files")
- parser.add_option("-y", "--yearmonth", dest="yearmonth",
- help="year and month in YYYY-MM format", metavar="YYYY-MM")
- parser.add_option("-u", "--username", dest="username",
- help="Run.GPS username")
- parser.add_option("-o", "--osm-username", dest="osmname",
- help="OpenStreetMap username")
- parser.add_option("-p", "--osm-passwd", dest="osmpasswd",
- help="OpenStreetMap password")
- parser.add_option("-b", "--dropbox", dest="dropboxauth",
- help="DropBox Auth token")
- (options, args) = parser.parse_args()
-
- username = options.username
- osmname = options.osmname
- osmpwd = options.osmpasswd
- dbauth = options.dropboxauth
- if not (username or (osmname and osmpwd) or dbauth):
- print "Run.GPS username or OSM username/password or Dropbox Auth token is mandatory!"
- return
-
- if username:
- pusername = username+'@Run.GPS'
- elif osmname:
- pusername = osmname+'@OSM'
- elif dbauth:
- import dropbox
- dbx = dropbox.Dropbox(dbauth)
- pusername = dbx.users_get_current_account().email+'@DBX'
-
- try:
- if options.yearmonth:
- year,month = options.yearmonth.split('-')
- month = int(month) -1
- year = int(year)
- if month<0 or month>11:
- raise invalid_number
- else:
- year = None
- month = None
- except:
- print "Year and month should be in YYYY-MM format!"
- return
-
- if options.dirname:
- outdir = options.dirname
- else:
- outdir = '.'
-
- db = outdir + '/gpx.db'
-
- if year:
- if options.verbose:
- print "retrieving trainings for user %s, year %s, month %s to %s" % (pusername,year,month+1,outdir)
- if username:
- sync_folder(username,year,month,outdir,options.verbose,options.force)
- elif osmname:
- sync_osm(osmname,osmpwd,year,month+1,outdir,options.verbose,options.force)
- elif dbauth:
- sync_db(dbx,pusername,year,month+1,outdir,options.verbose,options.force)
- else:
- if options.verbose:
- print "retrieving two last months for user %s to %s" % (pusername ,outdir)
- now = date.today()
- current_year = now.year
- current_month = now.month
- if username:
- sync_folder(username,current_year,current_month-1,outdir,options.verbose,options.force)
- elif osmname:
- sync_osm(osmname,osmpwd,current_year,current_month,outdir,options.verbose,options.force)
- elif dbauth:
- sync_db(dbx,pusername,current_year,current_month,outdir,options.verbose,options.force)
- current_month = current_month -1
- if current_month == 0:
- current_month = 12
- current_year = current_year -1
- if username:
- sync_folder(username,current_year,current_month-1,outdir,options.verbose,options.force)
- elif osmname:
- sync_osm(osmname,osmpwd,current_year,current_month,outdir,options.verbose,options.force)
- elif dbauth:
- sync_db(dbx,pusername,current_year,current_month,outdir,options.verbose,options.force)
-
- generate_image.render_all(db,'/etc/mapnik-osm-carto-data/veloroad-imposm.xml',640,640)
-
-if __name__ == "__main__":
-
- main()
-
\ No newline at end of file
--- /dev/null
+from .render_tiles import deg2num, queue_render, queue_tiles, process_queue
+from .parsegpx import check_db_for_training, write_parsed_to_db, write_tree_to_db, print_parsed_file
+from .pygeocode import GetDescr, GeoName
+from .pygpx import deg2rad, StripPrefix, formattime, Link, GPXTrackPt, GPXRoute, GPXTrackSeg, GPXTrack, GPX
+from .pyrungps_sync import get_page, get_gpx_track, get_osm_list, get_osm_gpx, get_db_gpx, get_dbx_list, sync_db, sync_osm, sync_folder
+from .generate_image import render_map, render_all
+
+__all__ = [
+ "deg2num", "queue_render", "queue_tiles", "process_queue",
+ "check_db_for_training", "write_parsed_to_db", "write_tree_to_db", "print_parsed_file",
+ "GetDescr", "GeoName",
+ "deg2rad", "StripPrefix", "formattime", "Link", "GPXTrackPt", "GPXRoute", "GPXTrackSeg", "GPXTrack", "GPX",
+ "get_page", "get_gpx_track", "get_osm_list", "get_osm_gpx", "get_db_gpx", "get_dbx_list", "sync_db", "sync_osm", "sync_folder",
+ "render_map", "render_all"
+ ]
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+
+import mapnik
+
+import sys, os
+
+from lxml import html,etree
+from optparse import OptionParser
+
+from pprint import pprint
+
+import pyrungps.pygpx
+
+# Set up projections
+# spherical mercator (most common target map projection of osm data imported with osm2pgsql)
+merc = mapnik.Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over')
+
+# long/lat in degrees, aka ESPG:4326 and "WGS 84"
+longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
+# can also be constructed as:
+#longlat = mapnik.Projection('+init=epsg:4326')
+
+# ensure minimum mapnik version
+if not hasattr(mapnik,'mapnik_version') and not mapnik.mapnik_version() >= 600:
+ raise SystemExit('This script requires Mapnik >=0.6.0)')
+
+
+def render_map(mapfile,map_uri,gpx_file,imgx,imgy):
+
+ with open(gpx_file,'r') as f:
+ data = f.read()
+
+ xml = etree.fromstring(data)
+ gpx = pygpx.GPX()
+ gpx.ReadTree(xml)
+
+ bbox = gpx.bound_box()
+ pprint(bbox)
+ cx=(bbox[0][1]+bbox[1][1])/2
+ cy=(bbox[0][0]+bbox[1][0])/2
+ print(cx,cy)
+ w=(bbox[1][1]-bbox[0][1])*1.2
+ h=(bbox[1][0]-bbox[0][0])*1.2
+ print(w,h)
+ bounds = (cx-w/2,cy-h/2,cx+w/2,cy+h/2)
+ print(bounds)
+
+ m = mapnik.Map(imgx,imgy)
+ mapnik.load_map(m,mapfile)
+
+ m.background = mapnik.Color('rgb(255,255,255)')
+
+ # ensure the target map projection is mercator
+ m.srs = merc.params()
+
+ bbox = mapnik.Box2d(*bounds)
+
+ pprint(bbox)
+
+ transform = mapnik.ProjTransform(longlat,merc)
+ merc_bbox = transform.forward(bbox)
+ m.zoom_to_box(merc_bbox)
+
+ style = mapnik.Style()
+ rule = mapnik.Rule()
+
+ line_symbolizer = mapnik.LineSymbolizer()
+
+ line_symbolizer.stroke = mapnik.Color('rgb(0,0,127)')
+ line_symbolizer.stroke_width = 4.0
+ line_symbolizer.stroke_opacity = 0.5
+
+ rule.symbols.append(line_symbolizer)
+
+ style.rules.append(rule)
+ m.append_style('GPS_tracking_points', style)
+
+ layer = mapnik.Layer('GPS_tracking_points')
+ layer.datasource = mapnik.Ogr(file=gpx_file, layer='tracks')
+ layer.styles.append('GPS_tracking_points')
+ m.layers.append(layer)
+
+ im = mapnik.Image(imgx,imgy)
+ mapnik.render(m, im)
+ im.save(map_uri,'png')
+ sys.stdout.write('output image to %s!\n' % map_uri)
+
+
+def render_all(db,mapfile,imgx,imgy):
+
+ import sqlite3
+ from os.path import dirname
+
+ conn = sqlite3.connect(db)
+ conn.text_factory = str
+ cur = conn.cursor()
+ updcur = conn.cursor()
+
+ cur.execute ("select id,filename from tracks where preview_name is null")
+
+ list=cur.fetchall()
+
+ for rec in list:
+
+ id = rec[0]
+ filename = rec[1]
+ preview_name = dirname(filename) + '/' + str(id) + '.png'
+
+ print(id,filename,preview_name)
+
+ try:
+ render_map(mapfile,preview_name.encode('utf8'),filename,imgx,imgy)
+ updcur.execute("update tracks set preview_name=? where id=?", (preview_name,id))
+ conn.commit()
+ except:
+ raise
+
+
+def main():
+
+ parser = OptionParser()
+ parser.add_option("-m", "--map", dest="mapfile",
+ help="use map file", metavar="MAP")
+ parser.add_option("-o", "--output", dest="outfile",
+ help="output image to file", metavar="OUT")
+ parser.add_option("-g", "--gpx", dest="gpxfile",
+ help="track to render", metavar="GPX")
+ parser.add_option("-x", "--x-size", dest="x",
+ help="image width", metavar="X")
+ parser.add_option("-y", "--y-size", dest="y",
+ help="image height", metavar="Y")
+ parser.add_option("-d", "--db", dest="db",
+ help="render all not process files in database", metavar="DB")
+ (options, args) = parser.parse_args()
+
+ if options.mapfile:
+ mapfile = options.mapfile
+ else:
+ mapfile = "/etc/mapnik-osm-carto-data/veloroad-imposm.xml"
+
+ if options.outfile:
+ map_uri = options.outfile
+ else:
+ map_uri = "image.png"
+
+ if options.x:
+ imgx = int(options.x)
+ else:
+ imgx= 640
+ if options.y:
+ imgy = int(options.y)
+ else:
+ imgy= 640
+
+ if options.db:
+ render_all(options.db,mapfile,imgx,imgy)
+ else:
+ if options.gpxfile:
+ gpx_file = options.gpxfile
+ render_map(mapfile,map_uri,gpx_file,imgx,imgy)
+ else:
+ print("No input file")
+ raise IOError("No input file")
+
+if __name__ == "__main__":
+
+ try:
+ main()
+ except:
+ exit(1)
--- /dev/null
+#!/usr/bin/env python
+# coding: UTF-8
+
+import sys
+import os
+from lxml import etree
+from urllib.parse import unquote
+import pyrungps.pygpx
+import pyrungps.pygeocode
+import sqlite3
+import datetime
+
+def check_db_for_training(db,sport,timestamp):
+
+ conn = sqlite3.connect(db)
+ conn.text_factory = str
+ cur = conn.cursor()
+
+ cur.execute ("select count(*) from tracks where sport=? and start_time=?" , (sport,timestamp))
+ return cur.fetchall()[0][0]
+
+def write_parsed_to_db(db,gpx,filename):
+
+ conn = sqlite3.connect(db)
+ conn.text_factory = str
+ cur = conn.cursor()
+
+ cur.execute ("delete from tracks where filename=?" , (filename,))
+
+ tracks = gpx.tracks
+
+ for track in tracks:
+
+ try:
+ author = gpx.author
+ except:
+ author = None
+
+ try:
+ name = gpx.name
+ except:
+ name = None
+
+ if author:
+ try:
+ cur.execute("insert into authors(name,description) values(?,?)", (author,''))
+ print("created author %s" % (author))
+ except:
+ print("failed to create author %s" % (author))
+ pass
+
+ try:
+
+ print("processing...")
+ start = track.start()
+ if start:
+ printable = pygeocode.GeoName(start.lat,start.lon).printable
+ start_time = track.start_time()
+ full_duration = track.full_duration().total_seconds()
+ distance = track.distance()
+ filtered_distance = track.filtered_distance(max_speed=50)
+ ascent = track.elevation_gain()
+ descent = track.elevation_loss()
+ ((minlat,minlon),(maxlat,maxlon)) = track.bound_box()
+ params = (
+ gpx.author,name,filename,
+ track.sport,start_time,full_duration,
+ distance,filtered_distance,ascent,descent,
+ start.lat,start.lon,
+ printable,
+ minlat,minlon,maxlat,maxlon
+ )
+ print(params)
+ cur.execute("""
+ insert into tracks(
+ author,name,filename,sport,
+ start_time,duration,
+ distance,distance_filtered,
+ ascent,descent,
+ lat,lon,printable_location,minlat,minlon,maxlat,maxlon)
+ values(
+ ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+ """
+ , params )
+ conn.commit()
+ print("created track %s" % (filename))
+
+ except:
+
+ raise
+
+def write_tree_to_db(db,tree,filename):
+
+ gpx = pygpx.GPX()
+ gpx.ReadTree(tree)
+
+ write_parsed_to_db(db,gpx,filename)
+
+def print_parsed_file(filename):
+
+ gpx = pygpx.GPX()
+ gpx.ReadFile(filename)
+
+ for track in gpx.tracks:
+
+ try:
+ author = gpx.author
+ except:
+ author = None
+
+ try:
+ name = gpx.name
+ except:
+ name = None
+
+ start = track.start()
+ if start:
+ printable = pygeocode.GeoName(start.lat,start.lon).printable
+ start_time = track.start_time()
+ full_duration = track.full_duration().total_seconds()
+ distance = track.distance()
+ filtered_distance = track.filtered_distance(max_speed=50)
+ ascent = track.elevation_gain()
+ descent = track.elevation_loss()
+ ((minlat,minlon),(maxlat,maxlon)) = track.bound_box()
+ params = (
+ gpx.author,name,filename,
+ track.sport,start_time,full_duration,
+ distance,filtered_distance,ascent,descent,
+ start.lat,start.lon,
+ printable,
+ minlat,minlon,maxlat,maxlon
+ )
+ print(params)
--- /dev/null
+# coding=UTF-8
+"""
+nominatim.openstreetmap.org API
+"""
+
+import urllib3
+
+def GetDescr(lat,lon):
+
+ reqstr = "http://maps.rvb.name/geocode.php?lat=%s&lon=%s" %(lat,lon)
+ headers = { 'User-Agent' : 'PyRunGPS/1.0', 'Referer' : 'https://maps.rvb.name' }
+ http_pool = urllib3.connection_from_url(reqstr, headers=headers)
+ req = http_pool.urlopen('GET',reqstr)
+ return req.data.decode('utf-8','ignore')
+
+class GeoName:
+
+ def __init__(self, lat, lon):
+
+ self.printable = GetDescr(lat,lon)
+
\ No newline at end of file
--- /dev/null
+# coding: UTF-8
+#------------------------
+# Работа с GPX-файлами
+#------------------------
+from lxml import etree
+import os
+import math
+import datetime
+from dateutil.parser import parse
+from pprint import pprint
+
+def deg2rad(deg):
+# Преобразование из градусов в радианы.
+ return deg / (180 / math.pi)
+
+tagprefix = { '1.0': '{http://www.topografix.com/GPX/1/0}', '1.1': '{http://www.topografix.com/GPX/1/1}'}
+
+def StripPrefix(tag,version):
+ nstag=tagprefix[version]
+ return tag.replace(nstag,'')
+
+def formattime(dt):
+ return dt.strftime("%Y-%m-%dT%H:%M:%S")+"."+str(int(dt.microsecond/1000)).zfill(3)+"Z"
+
+class Link:
+ # Ссылка. Может присутствовать в точке, треке, файле.
+ def __init__(self, node, version):
+ self.version = version
+ self.href = node.get("href")
+ self.text = None
+ self.type = None
+ if node is not None:
+ for child in node:
+ if child.tag == tagprefix[version] + "text":
+ self.text = child.text
+ elif child.tag == tagprefix[version] + "type":
+ self.type = child.text
+ else:
+ raise ValueError("Неизвестный тип узла: '%s' " % child.tag)
+
+ def write(self,root):
+ linknode = etree.SubElement(root,"link");
+ linknode.set("href",self.href)
+ if self.text:
+ etree.SubElement(linknode,"text").text = self.text
+ if self.type:
+ etree.SubElement(linknode,"type").text = self.type
+
+class GPXTrackPt:
+ # Точка с координатами. Может присутствовать в последовательности точек в треке, маршруте, а также в списке путевых точек.#
+
+ def __init__(self, node, version):
+ # Извлекаем данные из GPX-тэгов.#
+ self.version = version
+ # Сначала обязательные.#
+ if node is not None:
+ self.lat = float(node.get("lat"))
+ self.lon = float(node.get("lon"))
+ self.elevation = None
+ self.time = None
+ self.speed = None
+ self.link = None
+ self.additional_info = {}
+ # Потом необязательные.#
+ if node is not None:
+ for child in node:
+ if child.tag == tagprefix[version] + "time":
+ self.time = parse(child.text)
+ elif child.tag == tagprefix[version] + "ele":
+ self.elevation = float(child.text)
+ # Стандартом скорость не предусмотрена, но де-факто в Run.GPS используется.#
+ elif child.tag == tagprefix[version] + "speed":
+ self.speed = float(child.text)
+ elif child.tag == tagprefix[version] + "link":
+ self.link = Link(child,version)
+ elif StripPrefix(child.tag,version) in ['magvar','geoidheight','name','cmt','desc',
+ 'src','sym','type','fix','sat','hdop','vdop','pdop','ageofdgpsdata','dgpsid']:
+ self.additional_info[StripPrefix(child.tag,version)]=child.text
+ elif child.tag == tagprefix[version] + "extensions":
+ pass
+ else:
+ raise ValueError("Неизвестный тип узла: '%s'" % child.tag)
+
+ for i in self.additional_info.keys():
+ val = self.additional_info[i];
+ if val:
+ if not val.strip(' \n\t'):
+ del self.additional_info[i]
+
+
+ def write(self,root,tag ="wpt"):
+ wptnode = etree.SubElement(root,tag)
+ wptnode.set("lat",repr(self.lat));
+ wptnode.set("lon",repr(self.lon));
+ if self.elevation:
+ etree.SubElement(wptnode,"ele").text = repr(self.elevation)
+ if self.time:
+ etree.SubElement(wptnode,"time").text = formattime(self.time)
+ if self.speed:
+ etree.SubElement(wptnode,"speed").text = repr(self.speed)
+ if self.link:
+ self.link.write(wptnode)
+ for i in self.additional_info.keys():
+ etree.SubElement(wptnode,i).text = self.additional_info[i]
+
+ def distance(self, other):
+ # Расстояние между двумя точками на глобусе.#
+ # http://www.platoscave.net/blog/2009/oct/5/calculate-distance-latitude-longitude-python/
+
+ radius = 6378700.0 # meters
+
+ lat1, lon1 = self.lat, self.lon
+ lat2, lon2 = other.lat, other.lon
+
+ dlat = math.radians(lat2-lat1)
+ dlon = math.radians(lon2-lon1)
+ a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \
+ * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)
+ c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
+ d = radius * c
+
+ return d
+
+ def duration(self, other):
+ # Время между двумя точками.#
+ return other.time - self.time
+
+class GPXRoute:
+ # Маршрут.#
+
+ def __init__(self, node, version):
+ self.name = None
+ self.version = version
+ self.rtepts = []
+ self.additional_info = {}
+ self.link = None
+ if node is not None:
+ for child in node:
+ if child.tag == tagprefix[version] + "name":
+ self.name = child.text
+ elif child.tag == tagprefix[version] + "link":
+ self.link = Link(child,version)
+ elif StripPrefix(child.tag,version) in [ "cmt", "desc", "src", "number", "type" ]:
+ self.additional_info[StripPrefix(child.tag,version)]=child.text
+ elif child.tag == tagprefix[version] + "rtept":
+ self.rtepts.append(GPXTrackPt(child, version))
+ elif child.tag == tagprefix[version] + "extensions":
+ pass
+ else:
+ raise ValueError("Неизвестный тип узла <%s>" % child.tag)
+ for i in self.additional_info.keys():
+ val = self.additional_info[i];
+ if val:
+ if not val.strip(' \n\t'):
+ del self.additional_info[i]
+
+ def write(self,root):
+ rtenode = etree.SubElement(root,"rte")
+ if self.name:
+ etree.SubElement(rtenode,"name").text = self.name
+ if self.link:
+ self.link.write(rtenode)
+ for i in self.additional_info.keys():
+ print("storing %s " % ( i ))
+ etree.SubElement(rtenode,i).text = self.additional_info[i]
+ for i in self.rtepts:
+ i.write(rtenode,"rtept")
+
+class GPXTrackSeg:
+ # Один сегмент трека.#
+
+ def __init__(self, node, version):
+ self.version = version
+ self.trkpts = []
+ self.elevation_gain = 0.0
+ self.elevation_loss = 0.0
+ if node is not None:
+ for child in node:
+ if child.tag == tagprefix[version] + "trkpt":
+ self.trkpts.append(GPXTrackPt(child, self.version))
+ else:
+ raise ValueError("Неизвестный тип узла <%s>" % node.nodeName)
+ self._get_elevation()
+
+ def write(self,root):
+ trksegnode = etree.SubElement(root,"trkseg")
+ for i in self.trkpts:
+ i.write(trksegnode,"trkpt")
+
+ def _get_elevation(self):
+
+ elev_data = []
+ for pt in self.trkpts:
+ if pt.elevation:
+ elev_data.append(pt.elevation)
+
+ gain = 0.0
+ loss = 0.0
+ last_elevation = None
+
+ window_size = 5
+ i = 0
+ moving_averages = []
+
+ while i < len(elev_data) - window_size + 1:
+ this_window = elev_data[i : i + window_size]
+ window_average = sum(this_window) / window_size
+ moving_averages.append(window_average)
+ i += 1
+
+ if len(moving_averages)>2:
+ elev_data = moving_averages
+
+ for pt in elev_data:
+ if last_elevation is not None:
+ try:
+ if pt > last_elevation:
+ gain += pt - last_elevation
+ else:
+ loss += last_elevation - pt
+ except:
+ pass
+ last_elevation=pt
+
+ self.elevation_gain = gain
+ self.elevation_loss = loss
+
+ def distance(self):
+ # Расчет длины сегмента.#
+ _length = 0.0
+ last_pt = None
+ for pt in self.trkpts:
+ if last_pt is not None:
+ _length += last_pt.distance(pt)
+ last_pt = pt
+ return _length
+
+ def filtered_distance(self,max_speed):
+ # Расчет длины сегмента с фильтрацией предположительно сбойных участков.#
+ _length = 0.0
+ last_pt = None
+ for pt in self.trkpts:
+ if last_pt is not None:
+ _delta = last_pt.distance(pt)
+ _time_delta = pt.time - last_pt.time
+ _time_delta_s = _time_delta.days*86400 + _time_delta.seconds + _time_delta.microseconds/1000000
+ if _time_delta_s > 0:
+ if _delta/_time_delta_s < max_speed:
+ _length += _delta
+ else:
+ _length += _delta
+ last_pt = pt
+ return _length
+
+ def duration(self):
+ # Расчет продолжительности сегмента.#
+ return self.trkpts[0].duration(self.trkpts[-1])
+
+ def bound_box(self):
+ # Обрамляющий прямоугольник для сегмента.#
+ minlat =360
+ maxlat = -360
+ minlon = 360
+ maxlon = -360
+ for pt in self.trkpts:
+ if pt.lat<minlat:
+ minlat=pt.lat
+ if pt.lat>maxlat:
+ maxlat=pt.lat
+ if pt.lon<minlon:
+ minlon=pt.lon
+ if pt.lon>maxlon:
+ maxlon=pt.lon
+ return ((minlat,minlon),(maxlat,maxlon))
+
+class GPXTrack:
+ # Трек.#
+
+ def __init__(self, node, version):
+ # Создаем трек из GPX-данных.#
+
+ self.version = version
+ self.trksegs = []
+ self.sport= None
+ self.additional_info = {}
+ self.name = None
+ self.link = None
+
+ if node is not None:
+ for child in node:
+ if child.tag == tagprefix[version] + "name":
+ self.name = child.text
+ elif child.tag == tagprefix[version] + "trkseg":
+ if len(child) > 0:
+ self.trksegs.append(GPXTrackSeg(child, self.version))
+ elif child.tag == tagprefix[version] + "link":
+ self.link = Link(child,version)
+ elif StripPrefix(child.tag,version) in [ "number", "desc", "cmt", "src", "type" ]:
+ self.additional_info[StripPrefix(child.tag,version)] = child.text
+ elif child.tag == tagprefix[version] + "extensions":
+ for ext in child:
+ # Из расширений извлекаем вид спорта - специфично для Run.GPS.#
+ if ext.tag == tagprefix[version] + "sport":
+ self.sport = ext.text
+
+ for i in self.additional_info.keys():
+ val = self.additional_info[i];
+ if val:
+ if not val.strip(' \n\t'):
+ del self.additional_info[i]
+
+ def write(self,root):
+ trknode = etree.SubElement(root,"trk")
+ if self.name:
+ etree.SubElement(trknode,"name").text = self.name
+ if self.sport:
+ etree.SubElement(etree.SubElement(trknode,"extensions"),"sport").text=self.sport
+ if self.link:
+ self.link.write(trknode)
+ for i in self.additional_info.keys():
+ etree.SubElement(trknode,i).text = self.additional_info[i]
+ for i in self.trksegs:
+ i.write(trknode)
+
+ def elevation_gain(self):
+ # Набор высоты по треку.#
+ return sum([trkseg.elevation_gain for trkseg in self.trksegs])
+
+ def elevation_loss(self):
+ # Сброс высоты по треку.#
+ return sum([trkseg.elevation_loss for trkseg in self.trksegs])
+
+ def distance(self):
+ # Длина трека.#
+ try:
+ return sum([trkseg.distance() for trkseg in self.trksegs])
+ except IndexError:
+ print("Пустой сегмент трека, расчет длины невозможен.")
+
+ def filtered_distance(self,max_speed=100):
+ # Длина трека с фильтрацией сбойных участков.#
+ try:
+ return sum([trkseg.filtered_distance(max_speed=max_speed) for trkseg in self.trksegs])
+ except IndexError:
+ print("Пустой сегмент трека, расчет длины невозможен.")
+
+ def duration(self):
+ # Продолжительность трека, не включая паузы между сегментами.#
+ dur = datetime.timedelta(0)
+ for trkseg in self.trksegs:
+ try:
+ dur += trkseg.duration()
+ except:
+ pass
+ return dur
+
+ def full_duration(self):
+ # Продолжительность трека, включая паузы между сегментами.#
+ try:
+ return self.start().duration(self.end())
+ except:
+ return None
+
+ def start(self):
+ # Стартовая точка.#
+ try:
+ return self.trksegs[0].trkpts[0]
+ except IndexError:
+ return None
+
+ def end(self):
+ # Финишная точка.#
+ try:
+ return self.trksegs[-1].trkpts[-1]
+ except IndexError:
+ return None
+
+ def start_time(self):
+ # Время старта.#
+ try:
+ return self.start().time
+ except:
+ return None
+
+ def end_time(self):
+ # Время финиша.#
+ try:
+ return self.end().time
+ except:
+ return None
+
+ def bound_box(self):
+ # Обрамляющий прямоугольник для всего трека.#
+ minlat =360
+ maxlat = -360
+ minlon = 360
+ maxlon = -360
+ for trkseg in self.trksegs:
+ for pt in trkseg.trkpts:
+ if pt.lat<minlat:
+ minlat=pt.lat
+ if pt.lat>maxlat:
+ maxlat=pt.lat
+ if pt.lon<minlon:
+ minlon=pt.lon
+ if pt.lon>maxlon:
+ maxlon=pt.lon
+ return ((minlat,minlon),(maxlat,maxlon))
+
+
+class GPX:
+ # Работа с GPX-документами.#
+
+ def __init__(self):
+ # Создание пустого GPX-объекта#
+ PATH = os.path.dirname(__file__)
+ self.creator = None
+ self.time = None
+ self.tracks = []
+ self.routes = []
+ self.waypoints = []
+ self.version = ""
+ self.author = None
+ self.name = None
+ self.link = None
+ self.copyright = None
+ self.meta = {}
+
+ def ReadTree(self,tree):
+ # Загрузка из дерева etree.#
+ root = tree
+
+ # Test if this is a GPX file or not and if it's version 1.1
+ if root.tag == "{http://www.topografix.com/GPX/1/1}gpx" and root.get("version") == "1.1":
+ self.version = "1.1"
+ elif root.tag == "{http://www.topografix.com/GPX/1/0}gpx" and root.get("version") == "1.0":
+ self.version = "1.0"
+ elif root.get("version") not in [ "1.1", "1.0"]:
+ raise ValueError("Версия формата %s не поддерживается. Используйте GPX 1.1." % root.get("version"))
+ else:
+ raise ValueError("Неизвестный формат дерева")
+ # attempt to validate the xml file against the schema
+
+ # initalize the GPX document for parsing.
+ self._init_version(root)
+
+
+ def ReadFile(self, fd):
+ # Загрузка из файла.#
+ gpx_doc = etree.parse(fd)
+ root = gpx_doc.getroot()
+
+ # Test if this is a GPX file or not and if it's version 1.1
+ if root.tag == "{http://www.topografix.com/GPX/1/1}gpx" and root.get("version") == "1.1":
+ self.version = "1.1"
+ elif root.tag == "{http://www.topografix.com/GPX/1/0}gpx" and root.get("version") == "1.0":
+ self.version = "1.0"
+ elif root.get("version") not in [ "1.1", "1.0"]:
+ raise ValueError("Версия формата %s не поддерживается. Используйте GPX 1.1." % root.get("version"))
+ else:
+ raise ValueError("Неизвестный формат файла")
+ # initalize the GPX document for parsing.
+ self._init_version(root)
+
+ def _init_version(self,root):
+ # Инициализация объекта.#
+ self.creator = root.get("creator")
+ if root is not None:
+ for child in root:
+ if child.tag == tagprefix[self.version] + "author":
+ self.author = child.text
+ elif child.tag == tagprefix[self.version] + "trk":
+ self.tracks.append(GPXTrack(child, self.version))
+ elif child.tag == tagprefix[self.version] + "rte":
+ self.routes.append(GPXRoute(child, self.version))
+ elif child.tag == tagprefix[self.version] + "wpt":
+ self.waypoints.append(GPXTrackPt(child, self.version))
+ elif child.tag == tagprefix[self.version] + "metadata":
+ for meta in child:
+ if meta.tag == tagprefix[self.version] + "author":
+ self.author = meta.text
+ elif meta.tag == tagprefix[self.version] + "name":
+ self.name = meta.text
+ elif meta.tag == tagprefix[self.version] + "bounds":
+ # Границы пропускаем - их будем вычислять сами заново
+ pass
+ elif meta.tag == tagprefix[self.version] + "copyright":
+ self.copyright = meta.text
+ elif meta.tag == tagprefix[self.version] + "link":
+ self.link = Link(meta,self.version)
+ else:
+ self.meta[StripPrefix(meta.tag,self.version)]=meta.text
+
+ for i in self.meta.keys():
+ val = self.meta[i];
+ if val:
+ if not val.strip(' \n\t'):
+ del self.meta[i]
+
+ def elevation_gain(self):
+ # Суммарный набор высоты.#
+ return sum([track.elevation_gain() for track in self.tracks])
+
+ def elevation_loss(self):
+ # Суммарная потеря высоты.#
+ return sum([track.elevation_loss() for track in self.tracks])
+
+ def distance(self):
+ # Суммарная дистанция.#
+ try:
+ return sum([track.distance() for track in self.tracks])
+ except IndexError:
+ print("Пустой файл!")
+
+ def filtered_distance(self):
+ # Суммарная дистанция с фильтрацией сбойных данных.#
+ try:
+ return sum([track.filtered_distance() for track in self.tracks])
+ except IndexError:
+ print("Пустой файл!")
+
+ def duration(self):
+ # Суммарная продолжительность, не включая паузы.#
+ dur = datetime.timedelta(0)
+ for track in self.tracks:
+ dur += track.duration()
+ return dur
+
+ def full_duration(self):
+ # Суммарная продолжительность, включая паузы#
+ if hasattr(self.start(), 'duration'):
+ return self.start().duration(self.end())
+ else:
+ return None
+
+ def start(self):
+ # Точка старта.#
+ return self.tracks[0].start()
+
+ def end(self):
+ # Точка финиша.#
+ return self.tracks[-1].end()
+
+ def start_time(self):
+ # Время старта.#
+ if self.start():
+ return self.start().time
+ else:
+ return None
+
+ def end_time(self):
+ # Время финиша.#
+ return self.end().time
+
+ def bound_box(self):
+ # Обрамляющий прямоугольник для всех треков в файле.#
+ minlat =360
+ maxlat = -360
+ minlon = 360
+ maxlon = -360
+ for track in self.tracks:
+ for trkseg in track.trksegs:
+ for pt in trkseg.trkpts:
+ if pt.lat<minlat:
+ minlat=pt.lat
+ if pt.lat>maxlat:
+ maxlat=pt.lat
+ if pt.lon<minlon:
+ minlon=pt.lon
+ if pt.lon>maxlon:
+ maxlon=pt.lon
+ return ((minlat,minlon),(maxlat,maxlon))
+
+ def FixNames(self,linkname):
+ pprint(linkname)
+ pprint(type(linkname))
+ goodname = linkname
+ badname = goodname.encode('ascii','replace')
+ if self.name and self.name.startswith(badname):
+ self.name=self.name.replace(badname,goodname)
+ for i in self.tracks:
+ if i.name and i.name.startswith(badname):
+ i.name = i.name.replace(badname,goodname)
+
+ def ProcessTrackSegs(self,seconds_gap=120):
+ for tr in self.tracks:
+ # Объединяем все точки трека в единую последовательность
+ all_trackpoints = []
+ for trseg in tr.trksegs:
+ all_trackpoints.extend(trseg.trkpts)
+ new_segs = []
+ current_seg = None
+ prev_pt = None
+ for pt in all_trackpoints:
+ if not current_seg:
+ # Начало нового сегмента
+ current_seg = GPXTrackSeg(None,self.version)
+ current_seg.trkpts.append(pt)
+ else:
+ delta = pt.time - prev_pt.time
+ if delta.days > 0 or delta.seconds > seconds_gap:
+ # Нашли место разрыва
+ new_segs.append(current_seg)
+ current_seg = None
+ else:
+ current_seg.trkpts.append(pt)
+ prev_pt=pt
+ # Если есть, что закинуть в хвост - пишем
+ if current_seg is not None:
+ new_segs.append(current_seg)
+ # Обработали
+ for trs in new_segs:
+ trs._get_elevation()
+ tr.trksegs = new_segs
+
+
+ def XMLTree(self):
+ root = etree.Element("gpx", attrib ={"creator": "pygpx",
+ "version": "1.1",
+ "xmlns": "http://www.topografix.com/GPX/1/1"});
+
+ # meta subtree
+
+ meta = etree.SubElement( root, "metadata" );
+ if self.name:
+ metarecord = etree.SubElement( meta, "name" )
+ metarecord.text = self.name
+ if self.author:
+ metarecord = etree.SubElement( meta, "author" )
+ metarecord.text = self.author
+ if self.copyright:
+ metarecord = etree.SubElement( meta, "copyright" )
+ metarecord.text = self.copyright
+ if self.link:
+ self.link.write(meta)
+ for metatag in self.meta.keys():
+ metarecord = etree.SubElement( meta, metatag )
+ metarecord.text = self.meta[metatag]
+
+ # wpts subtree
+
+ for i in self.waypoints:
+ i.write(root)
+
+ # routes subtree
+
+ for i in self.routes:
+ i.write(root)
+
+ # tracks subtree
+
+ for i in self.tracks:
+ i.write(root)
+
+ return root
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+# coding: UTF-8
+
+import requests
+
+import urllib3
+urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+#import sys
+import os
+from urllib.parse import quote,unquote
+from lxml import html,etree
+from optparse import OptionParser
+from datetime import date,datetime
+from dateutil.parser import isoparse
+from pyrungps.parsegpx import write_parsed_to_db,check_db_for_training
+import pyrungps.pygpx
+
+from tempfile import NamedTemporaryFile
+
+from pprint import pprint
+
+import pyrungps.render_tiles
+
+import pyrungps.generate_image
+
+def get_page(uname,year,month):
+
+ trainings = []
+
+ req = requests.get("http://www.gps-sport.net/services/getMonthlyTrainingDataHTML_V2.jsp?userName=%s&year=%s&month=%s&rnd=0.645673"% (uname,year,month), headers = {'User-agent': 'Mozilla/5.0'}, verify=False)
+ page = req.text.encode('utf-8')
+ dom = html.document_fromstring(page)
+
+ for element, attribute, link, pos in dom.iterlinks():
+ if attribute == "href":
+ if link.startswith("/trainings/"):
+ dummy, dummy, link = link.split('/')
+ name, id = link.split('_')
+ trainings.append([ unquote(name), id ])
+
+ return trainings
+
+def get_gpx_track(trid,name):
+
+ print("trid=",trid)
+
+ req = requests.get("http://www.gps-sport.net/services/trainingGPX.jsp?trainingID=%s&tz=-180" % (trid), verify=False)
+ xml = etree.fromstring(req.text.encode('utf-8'))
+
+ return xml
+
+def get_osm_list(username,password,year,month):
+
+ url = "https://www.openstreetmap.org/api/0.6/user/gpx_files"
+
+ req = requests.get(url,auth=(username,password))
+
+ xml = etree.fromstring(req.text.encode('utf-8'))
+
+ res=[]
+
+ for gpx_file in xml:
+ attrib = dict(gpx_file.attrib)
+ try:
+ timestamp=datetime.fromtimestamp(isoparse(attrib['timestamp']))
+ id = attrib['id']
+ description=None
+ for descr in gpx_file.iter('description'):
+ description=descr.text
+ sport=None
+ for tag in gpx_file.iter('tag'):
+ sport=tag.text
+ if timestamp.year==year and timestamp.month==month and description=='Run.GPS Track':
+ record={ 'id': id, 'sport': sport }
+ res.append(record)
+ except:
+ None
+
+ return res
+
+def get_osm_gpx(username,password,track_id):
+
+ url = "https://www.openstreetmap.org/api/0.6/gpx/"+track_id+"/data"
+
+ req = requests.get(url,auth=(username,password))
+ xml = etree.fromstring(req.text.encode('utf-8'))
+
+ return xml
+
+def get_db_gpx(dbx,track_id):
+
+ md, res = dbx.files_download(track_id)
+
+ fs = NamedTemporaryFile(suffix='.tcx',delete = False)
+ tmp_tcx_name=fs.name
+ fs.write(res.content)
+ fs.close()
+ fs = NamedTemporaryFile(suffix='.gpx',delete = False)
+ tmp_gpx_name=fs.name
+ fs.close()
+
+ os.system("gpsbabel -i gtrnctr -f "+tmp_tcx_name+" -o gpx -F "+tmp_gpx_name)
+
+ with open (tmp_gpx_name, "r") as gpxfile:
+ data=gpxfile.read()
+
+ os.remove(tmp_gpx_name)
+ os.remove(tmp_tcx_name)
+
+ xml = etree.fromstring(data.encode('utf-8'))
+ return xml
+
+def get_dbx_list(dbx,username,year,month):
+
+ gpx_list_id = None
+
+ for entry in dbx.files_list_folder('').entries:
+ if entry.name == u'Приложения':
+ for entry_app in dbx.files_list_folder(entry.id).entries:
+ if entry_app.name == u'Run.GPS':
+ print("id="+entry_app.id)
+ gpx_list_id=entry_app.id
+ break
+ break
+
+ res = []
+
+ if gpx_list_id:
+
+ for file in dbx.files_list_folder(gpx_list_id).entries:
+
+ filename,ext = os.path.splitext(file.name)
+ if ext == '.tcx':
+ try:
+ fyear = int(filename[0:4])
+ fmonth = int(filename[5:7])
+ if fyear == year and fmonth == month:
+ sport = filename[41:]
+ timestamp = datetime.strptime(filename[0:19],'%Y-%m-%dT%H_%M_%S')
+ record={ 'id': file.id, 'timestamp': timestamp, 'sport': sport }
+ res.append(record)
+ except:
+ try:
+ fyear = int(filename[0:4])
+ fmonth = int(filename[5:7])
+ if fyear == year and fmonth == month:
+ sport = filename[18:]
+ timestamp = datetime.strptime(filename[0:16],'%Y-%m-%d_%H%M%S')
+ record={ 'id': file.id, 'timestamp': timestamp, 'sport': sport }
+ res.append(record)
+ except:
+ None
+
+ return res
+
+
+def sync_db(dbx,username,year,month,dir=".",verbose=False,force=False):
+
+ training_list = get_dbx_list(dbx,username,year,month)
+
+ for training in training_list:
+
+ filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,month,training['sport'],training['id'][3:])
+ dirname = "%s/%04d/%02d" % (dir,year,month)
+
+ if os.path.exists(filename) and not force:
+
+ if verbose:
+ print("training %s exists, skipping" % (filename))
+
+ else:
+
+ try:
+ os.makedirs(dirname)
+ except:
+ None
+
+ xml = get_db_gpx(dbx,training['id'])
+
+ if verbose:
+ print("writing training %s" % (filename))
+
+ gpx = pygpx.GPX()
+ gpx.ReadTree(xml)
+
+ sport = training['sport']
+ timestamp = gpx.tracks[0].start_time()
+
+ print(sport, timestamp)
+
+ if check_db_for_training(db,sport,timestamp):
+ print("The same training found")
+ continue
+
+ gpx.author = username
+ gpx.FixNames(training['sport'])
+ gpx.ProcessTrackSegs()
+ for track in gpx.tracks:
+ track.sport=training['sport']
+
+ xml = gpx.XMLTree();
+ f = open(filename,"wb")
+ f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
+ f.close
+ write_parsed_to_db(db,gpx,filename)
+ try:
+ render_tiles.queue_render(db,filename)
+ except:
+ None
+
+
+def sync_osm(username,password,year,month,dir=".",verbose=False,force=False):
+
+ training_list = get_osm_list(username,password,year,month)
+
+ for training in training_list:
+
+ filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,month,training['sport'],training['id'])
+ dirname = "%s/%04d/%02d" % (dir,year,month)
+
+ if os.path.exists(filename) and not force:
+
+ if verbose:
+ print("training %s exists, skipping" % (filename))
+
+ else:
+
+ try:
+ os.makedirs(dirname)
+ except:
+ None
+
+ xml = get_osm_gpx(username,password,training['id'])
+
+ if verbose:
+ print("writing training %s" % (filename))
+
+ gpx = pygpx.GPX()
+ gpx.ReadTree(xml)
+
+ sport = training['sport']
+ timestamp = gpx.tracks[0].start_time()
+
+ if check_db_for_training(db,sport,timestamp):
+ print("The same training found")
+ continue
+
+ gpx.author = username
+ gpx.FixNames(training['sport'])
+ gpx.ProcessTrackSegs()
+ for track in gpx.tracks:
+ track.sport=training['sport']
+
+ xml = gpx.XMLTree();
+ f = open(filename,"wb")
+ f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
+ f.close
+ write_parsed_to_db(db,gpx,filename)
+ try:
+ render_tiles.queue_render(db,filename)
+ except:
+ None
+
+def sync_folder(username,year,month,dir=".",verbose=False,force=False):
+
+ training_list = get_page(username,year,month)
+ for tr in training_list:
+ try:
+
+ filename = "%s/%04d/%02d/%s_%s.gpx" % (dir,year,(month+1),tr[0],tr[1])
+ dirname = "%s/%04d/%02d" % (dir,year,(month+1))
+
+ if os.path.exists(filename) and not force:
+
+ if verbose:
+ print("training %s exists, skipping" % (filename))
+
+ else:
+
+ try:
+ os.makedirs(dirname)
+ except:
+ None
+
+ xml=get_gpx_track(tr[1],tr[0])
+
+ if verbose:
+ print("writing training %s" % (filename))
+
+ gpx = pygpx.GPX()
+ gpx.ReadTree(xml)
+
+ sport = tr[0]
+ timestamp = gpx.tracks[0].start_time()
+
+ if check_db_for_training(db,sport,timestamp):
+ print("The same training found")
+ continue
+
+ gpx.FixNames(tr[0])
+ gpx.ProcessTrackSegs()
+
+ xml = gpx.XMLTree();
+ f = open(filename,"wb")
+ f.write(etree.tostring(xml,encoding='UTF-8',pretty_print=True))
+ f.close
+ write_parsed_to_db(db,gpx,filename)
+ try:
+ render_tiles.queue_render(db,filename)
+ except:
+ None
+
+ except:
+ raise
+
+def main():
+
+ global db;
+ parser = OptionParser()
+ parser.add_option("-d", "--dir", dest="dirname",
+ help="write data to directory", metavar="DIR")
+ parser.add_option("-q", "--quiet",
+ action="store_false", dest="verbose", default=True,
+ help="don't print status messages to stdout")
+ parser.add_option("-f", "--force",
+ action="store_true", dest="force", default=False,
+ help="rewrite all files")
+ parser.add_option("-y", "--yearmonth", dest="yearmonth",
+ help="year and month in YYYY-MM format", metavar="YYYY-MM")
+ parser.add_option("-u", "--username", dest="username",
+ help="Run.GPS username")
+ parser.add_option("-o", "--osm-username", dest="osmname",
+ help="OpenStreetMap username")
+ parser.add_option("-p", "--osm-passwd", dest="osmpasswd",
+ help="OpenStreetMap password")
+ parser.add_option("-b", "--dropbox", dest="dropboxauth",
+ help="DropBox Auth token")
+ (options, args) = parser.parse_args()
+
+ username = options.username
+ osmname = options.osmname
+ osmpwd = options.osmpasswd
+ dbauth = options.dropboxauth
+ if not (username or (osmname and osmpwd) or dbauth):
+ print("Run.GPS username or OSM username/password or Dropbox Auth token is mandatory!")
+ return
+
+ if username:
+ pusername = username+'@Run.GPS'
+ elif osmname:
+ pusername = osmname+'@OSM'
+ elif dbauth:
+ import dropbox
+ dbx = dropbox.Dropbox(dbauth)
+ pusername = dbx.users_get_current_account().email+'@DBX'
+
+ try:
+ if options.yearmonth:
+ year,month = options.yearmonth.split('-')
+ month = int(month) -1
+ year = int(year)
+ if month<0 or month>11:
+ raise invalid_number
+ else:
+ year = None
+ month = None
+ except:
+ print("Year and month should be in YYYY-MM format!")
+ return
+
+ if options.dirname:
+ outdir = options.dirname
+ else:
+ outdir = '.'
+
+ db = outdir + '/gpx.db'
+
+ if year:
+ if options.verbose:
+ print("retrieving trainings for user %s, year %s, month %s to %s" % (pusername,year,month+1,outdir))
+ if username:
+ sync_folder(username,year,month,outdir,options.verbose,options.force)
+ elif osmname:
+ sync_osm(osmname,osmpwd,year,month+1,outdir,options.verbose,options.force)
+ elif dbauth:
+ sync_db(dbx,pusername,year,month+1,outdir,options.verbose,options.force)
+ else:
+ if options.verbose:
+ print("retrieving two last months for user %s to %s" % (pusername ,outdir))
+ now = date.today()
+ current_year = now.year
+ current_month = now.month
+ if username:
+ sync_folder(username,current_year,current_month-1,outdir,options.verbose,options.force)
+ elif osmname:
+ sync_osm(osmname,osmpwd,current_year,current_month,outdir,options.verbose,options.force)
+ elif dbauth:
+ sync_db(dbx,pusername,current_year,current_month,outdir,options.verbose,options.force)
+ current_month = current_month -1
+ if current_month == 0:
+ current_month = 12
+ current_year = current_year -1
+ if username:
+ sync_folder(username,current_year,current_month-1,outdir,options.verbose,options.force)
+ elif osmname:
+ sync_osm(osmname,osmpwd,current_year,current_month,outdir,options.verbose,options.force)
+ elif dbauth:
+ sync_db(dbx,pusername,current_year,current_month,outdir,options.verbose,options.force)
+
+ generate_image.render_all(db,'/etc/mapnik-osm-carto-data/veloroad-imposm.xml',640,640)
+
+if __name__ == "__main__":
+
+ main()
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python
+# coding: UTF-8
+
+import sqlite3
+import math
+from pprint import pprint
+
+def queue_render(db,filename,forced_max_zoom=None):
+
+ conn = sqlite3.connect(db)
+ conn.text_factory = str
+ cur = conn.cursor()
+
+ cur.execute("select minlat,minlon,maxlat,maxlon from tracks where filename=?" , (filename,))
+ minlat,minlon,maxlat,maxlon=cur.fetchone()
+ queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom)
+
+def deg2num(lat_deg, lon_deg, zoom):
+ lat_rad = math.radians(lat_deg)
+ n = 2.0 ** zoom
+ xtile = int((lon_deg + 180.0) / 360.0 * n)
+ ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
+ return (xtile, ytile)
+
+def queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom=None):
+
+ conn = sqlite3.connect(db)
+
+ # определяем примерный стартовый зум
+
+ minzoom=8
+
+ if forced_max_zoom:
+ maxzoom=forced_max_zoom
+ else:
+ maxzoom=minzoom
+ while True:
+ minx,miny=deg2num(minlat,minlon,maxzoom)
+ maxx,maxy=deg2num(maxlat,maxlon,maxzoom)
+
+ print(maxzoom,':',minx,'-',maxx,'/',miny,'-',maxy)
+ if (maxx-minx>16) or (maxy-miny>12) or (maxzoom==16):
+ break
+ else:
+ maxzoom=maxzoom+1
+
+ if maxzoom<minzoom:
+ minzoom=maxzoom
+
+ ins = conn.cursor()
+ print(minlat,minlon,maxlat,maxlon,minzoom,maxzoom)
+ ins.execute('insert into render_queue(minlat,maxlat,minlon,maxlon,minzoom,maxzoom) values(?,?,?,?,?,?)',(minlat,maxlat,minlon,maxlon,minzoom,maxzoom))
+
+ conn.commit()
+
+def process_queue(db,map,force=False,backend="renderd"):
+
+ from os import system
+
+ conn = sqlite3.connect(db)
+ cur = conn.cursor()
+ cur.execute('select id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom from render_queue')
+ list=cur.fetchall()
+
+ for rec in list:
+
+ id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom=rec
+
+ if backend == "tirex" or backend == "default":
+
+ command = 'map='+map+ \
+ ' z='+str(minzoom)+'-'+str(maxzoom)+ \
+ ' lat='+str(minlat)+','+str(maxlat)+ \
+ ' lon='+str(minlon)+','+str(maxlon)
+
+ if force:
+ command = 'tirex-batch -n 0 --prio=50 '+command
+ else:
+ command = 'tirex-batch -n 0 --prio=50 '+command+' -f not-exists'
+
+ print(command )
+
+ if system(command)==0:
+ dcur=conn.cursor()
+ dcur.execute('delete from render_queue where id=?',(id,))
+ conn.commit()
+
+ elif backend == "renderd":
+
+ print(minlat,minlon,maxlat,maxlon)
+
+ for zoom in range(minzoom,maxzoom+1):
+ minx,miny=deg2num(minlat,minlon,zoom)
+ maxx,maxy=deg2num(maxlat,maxlon,zoom)
+
+ if minx>maxx:
+ tx=minx
+ maxx=minx
+ minx=tx
+
+ if miny>maxy:
+ ty=miny
+ maxy=miny
+ miny=ty
+
+ print(zoom,minx,miny,maxx,maxy)
+
+ maps = map.split(',')
+
+ for map_name in maps:
+
+ command = 'render_list -a -m '+map+ \
+ ' -z '+str(zoom)+' -Z '+str(zoom)+ \
+ ' -x '+str(minx)+' -X '+str(maxx)+ \
+ ' -y '+str(miny)+' -Y '+str(maxy)
+ if force:
+ command = command+ ' --force'
+
+ print(command )
+
+ if not system(command) == 0:
+ return
+
+ dcur=conn.cursor()
+ dcur.execute('delete from render_queue where id=?',(id,))
+ conn.commit()
+
+def main():
+
+ from optparse import OptionParser
+
+ parser = OptionParser()
+ parser.add_option("-d", "--data", dest="directory",
+ help="Data directory", metavar="DIR")
+ parser.add_option("-m", "--map", dest="map",
+ help="Map name", metavar="MAP")
+ parser.add_option("-z", "--zoom", dest="zoom",
+ help="Maximal zoom (forced), used with coordinates pairs (minlat minlon maxlat maxlon) or filename in arguments", metavar="MAP")
+ parser.add_option("-f", "--force", dest="force",
+ help="Force tile regeneration (on/off), default off")
+ parser.add_option("-r", "--renderer", dest="renderer",
+ help="Rendering backend: tirex or renderd")
+ (options, args) = parser.parse_args()
+
+ db=options.directory+'/gpx.db'
+ map=options.map
+ zoom=options.zoom
+ if not zoom:
+ zoom=12
+ force=(options.force=='on')
+
+ if options.renderer:
+ renderer=options.renderer
+ else:
+ print("Using default rendering backend...")
+ renderer="default"
+
+ if len(args)==1:
+ filename,=args
+ print("Rendering file: "+filename+"\n")
+ queue_render(db,filename)
+ elif len(args)==4:
+ minlat,minlon,maxlat,maxlon=args
+ print("Rendering region "+minlat+'..'+maxlat+' / '+minlon+'..'+maxlon+"\n")
+ queue_tiles(db,float(minlat),float(minlon),float(maxlat),float(maxlon),int(zoom))
+
+ if map:
+ print("Processing map(s) "+map+"\n")
+ process_queue(db,map,force,renderer)
+
+if __name__ == "__main__":
+
+ main()
+
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python pyrungps.py
+++ /dev/null
-#!/usr/bin/env python
-# coding: UTF-8
-
-import sqlite3
-import math
-from pprint import pprint
-
-def queue_render(db,filename,forced_max_zoom=None):
-
- conn = sqlite3.connect(db)
- conn.text_factory = str
- cur = conn.cursor()
-
- cur.execute("select minlat,minlon,maxlat,maxlon from tracks where filename=?" , (filename.decode('UTF-8'),))
- minlat,minlon,maxlat,maxlon=cur.fetchone()
- queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom)
-
-def deg2num(lat_deg, lon_deg, zoom):
- lat_rad = math.radians(lat_deg)
- n = 2.0 ** zoom
- xtile = int((lon_deg + 180.0) / 360.0 * n)
- ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
- return (xtile, ytile)
-
-def queue_tiles(db,minlat,minlon,maxlat,maxlon,forced_max_zoom=None):
-
- conn = sqlite3.connect(db)
-
- # определяем примерный стартовый зум
-
- minzoom=8
-
- if forced_max_zoom:
- maxzoom=forced_max_zoom
- else:
- maxzoom=minzoom
- while True:
- minx,miny=deg2num(minlat,minlon,maxzoom)
- maxx,maxy=deg2num(maxlat,maxlon,maxzoom)
-
- print maxzoom,':',minx,'-',maxx,'/',miny,'-',maxy
- if (maxx-minx>16) or (maxy-miny>12) or (maxzoom==16):
- break
- else:
- maxzoom=maxzoom+1
-
- if maxzoom<minzoom:
- minzoom=maxzoom
-
- ins = conn.cursor()
- print minlat,minlon,maxlat,maxlon,minzoom,maxzoom
- ins.execute('insert into render_queue(minlat,maxlat,minlon,maxlon,minzoom,maxzoom) values(?,?,?,?,?,?)',(minlat,maxlat,minlon,maxlon,minzoom,maxzoom))
-
- conn.commit()
-
-def process_queue(db,map,force=False,backend="renderd"):
-
- from os import system
-
- conn = sqlite3.connect(db)
- cur = conn.cursor()
- cur.execute('select id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom from render_queue')
- list=cur.fetchall()
-
- for rec in list:
-
- id,minlat,maxlat,minlon,maxlon,minzoom,maxzoom=rec
-
- if backend == "tirex" or backend == "default":
-
- command = 'map='+map+ \
- ' z='+str(minzoom)+'-'+str(maxzoom)+ \
- ' lat='+str(minlat)+','+str(maxlat)+ \
- ' lon='+str(minlon)+','+str(maxlon)
-
- if force:
- command = 'tirex-batch -n 0 --prio=50 '+command
- else:
- command = 'tirex-batch -n 0 --prio=50 '+command+' -f not-exists'
-
- print command
-
- if system(command)==0:
- dcur=conn.cursor()
- dcur.execute('delete from render_queue where id=?',(id,))
- conn.commit()
-
- elif backend == "renderd":
-
- print minlat,minlon,maxlat,maxlon
-
- for zoom in range(minzoom,maxzoom+1):
- minx,miny=deg2num(minlat,minlon,zoom)
- maxx,maxy=deg2num(maxlat,maxlon,zoom)
-
- if minx>maxx:
- tx=minx
- maxx=minx
- minx=tx
-
- if miny>maxy:
- ty=miny
- maxy=miny
- miny=ty
-
- print zoom,minx,miny,maxx,maxy
-
- maps = map.split(',')
-
- for map_name in maps:
-
- command = 'render_list -a -m '+map+ \
- ' -z '+str(zoom)+' -Z '+str(zoom)+ \
- ' -x '+str(minx)+' -X '+str(maxx)+ \
- ' -y '+str(miny)+' -Y '+str(maxy)
- if force:
- command = command+ ' --force'
-
- print command
-
- if system(command)<>0:
- return
-
- dcur=conn.cursor()
- dcur.execute('delete from render_queue where id=?',(id,))
- conn.commit()
-
-def main():
-
- from optparse import OptionParser
-
- parser = OptionParser()
- parser.add_option("-d", "--data", dest="directory",
- help="Data directory", metavar="DIR")
- parser.add_option("-m", "--map", dest="map",
- help="Map name", metavar="MAP")
- parser.add_option("-z", "--zoom", dest="zoom",
- help="Maximal zoom (forced), used with coordinates pairs (minlat minlon maxlat maxlon) or filename in arguments", metavar="MAP")
- parser.add_option("-f", "--force", dest="force",
- help="Force tile regeneration (on/off), default off")
- parser.add_option("-r", "--renderer", dest="renderer",
- help="Rendering backend: tirex or renderd")
- (options, args) = parser.parse_args()
-
- db=options.directory+'/gpx.db'
- map=options.map
- zoom=options.zoom
- if not zoom:
- zoom=12
- force=(options.force=='on')
-
- if options.renderer:
- renderer=options.renderer
- else:
- print "Using default rendering backend..."
- renderer="default"
-
- if len(args)==1:
- filename,=args
- print "Rendering file: "+filename+"\n"
- queue_render(db,filename)
- elif len(args)==4:
- minlat,minlon,maxlat,maxlon=args
- print "Rendering region "+minlat+'..'+maxlat+' / '+minlon+'..'+maxlon+"\n"
- queue_tiles(db,float(minlat),float(minlon),float(maxlat),float(maxlon),int(zoom))
-
- if map:
- print "Processing map(s) "+map+"\n"
- process_queue(db,map,force,renderer)
-
-if __name__ == "__main__":
-
- main()
-
\ No newline at end of file
--- /dev/null
+from setuptools import setup, find_packages
+
+setup(
+ name='pyrungps',
+ version='0.1',
+ description='Simple python tool to sync gpx tracks from GPS-SPORT site',
+ url='http://rvb.name/gpx',
+ author='Roman Bazalevskiy',
+ author_email='rvb@rvb.name',
+ license='WTFPL?',
+ packages=['pyrungps'],
+ zip_safe=False
+)