Browse Source

Use ExtendedData and colour analysis balloon backgrounds.

debian-sid
Tom Payne 14 years ago
parent
commit
6f1309646a
  1. 1
      TODO
  2. 135
      igc2kmz/__init__.py
  3. 1
      igc2kmz/kml.py

1
TODO

@ -3,7 +3,6 @@ Check indexes in thermal folder
Check indexes in colored tracklogs
Clean up heirarchical altitude marks
Clean up global styles
Use ExtendedData for tables
MEDIUM
Competition points

135
igc2kmz/__init__.py

@ -20,6 +20,7 @@ from math import pi, sqrt
from itertools import cycle, izip
import operator
import os
import re
import unicodedata
import urlparse
@ -36,14 +37,14 @@ import util
RIGHTWARDS_ARROW = unicodedata.lookup('RIGHTWARDS ARROW').encode('utf_8')
INFINITY = unicodedata.lookup('INFINITY').encode('utf_8')
MULTIPLICATION_SIGN = unicodedata.lookup('MULTIPLICATION SIGN').encode('utf_8')
UP_TACK = unicodedata.lookup('UP TACK').encode('utf_8')
IMAGES_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__),
'..',
'images'))
def make_table(rows):
bgcolors = '#cccccc #ffffff'.split()
def make_table(rows, bgcolors='#dddddd #ffffff'.split()):
trs = ('<tr bgcolor="%s"><th align="right">%s</th><td>%s</td></tr>'
% (bgcolor, row[0], row[1])
for row, bgcolor in izip(rows, cycle(bgcolors)))
@ -66,9 +67,10 @@ class Stock(object):
style_url = self.check_hide_children_style.url()
return kml.Folder(screen_overlay, name='None', styleUrl=style_url)
def make_analysis_style(self, color):
text = kml.text(kml.CDATA('<h3>$[name]</h3>$[description]'))
balloon_style = kml.BalloonStyle(text)
def make_analysis_style(self, color, bgcolors, rows):
text = '<h3>$[name]</h3>$[description]' + make_table(rows, bgcolors)
bg_color = 'ff' + ''.join(reversed(re.findall(r'..', bgcolors[1][1:])))
balloon_style = kml.BalloonStyle(text=kml.CDATA(text), bgColor=bg_color)
icon_style = kml.IconStyle(self.icons[0],
color=color,
scale=self.icon_scales[0])
@ -91,11 +93,57 @@ class Stock(object):
self.check_hide_children_style = kml.Style(list_style)
self.kmz.add_roots(self.check_hide_children_style)
#
self.thermal_style = self.make_analysis_style('cc3333ff')
bgcolors = '#ffcccc #ffdddd'.split()
rows = [
['Altitude gain', '$[altitude_change]m'],
['Average climb', '$[average_climb]m/s'],
['Maximum climb', '$[maximum_climb]m/s'],
['Peak climb', '$[peak_climb]m/s'],
['Efficiency', '$[efficiency]%'],
['Start altitude', '$[start_altitude]m'],
['Finish altitude', '$[finish_altitude]m'],
['Start time', '$[start_time]'],
['Finish time', '$[finish_time]'],
['Duration', '$[duration]'],
['Accumulated altitude gain', '$[accumulated_altitude_gain]m'],
['Accumulated altitude loss', '$[accumulated_altitude_loss]m'],
['Drift', '$[average_speed]km/h $[drift_direction]'],
]
self.thermal_style = self.make_analysis_style('cc3333ff',
bgcolors,
rows)
self.kmz.add_roots(self.thermal_style)
self.dive_style = self.make_analysis_style('ccff3333')
bgcolors = '#ccccff #ddddff'.split()
rows = [
['Altitude change', '$[altitude_change]m'],
['Average descent', '$[average_climb]m/s'],
['Maximum descent', '$[maximum_descent]m/s'],
['Peak descent', '$[peak_descent]m/s'],
['Start altitude', '$[start_altitude]m'],
['Finish altitude', '$[finish_altitude]m'],
['Start time', '$[start_time]'],
['Finish time', '$[finish_time]'],
['Duration', '$[duration]'],
['Accumulated altitude gain', '$[accumulated_altitude_gain]m'],
['Accumulated altitude loss', '$[accumulated_altitude_loss]m'],
]
self.dive_style = self.make_analysis_style('ccff3333', bgcolors, rows)
bgcolors = '#ccffcc #ddffdd'.split()
rows = [
['Altitude change', '$[altitude_change]m'],
['Distance', '$[distance]km'],
['Average glide ratio', '$[average_ld]:1'],
['Average speed', '$[average_speed]:1'],
['Start altitude', '$[start_altitude]m'],
['Finish altitude', '$[finish_altitude]m'],
['Start time', '$[start_time]'],
['Finish time', '$[finish_time]'],
['Duration', '$[duration]'],
['Accumulated altitude gain', '$[accumulated_altitude_gain]m'],
['Accumulated altitude loss', '$[accumulated_altitude_loss]m'],
]
self.kmz.add_roots(self.dive_style)
self.glide_style = self.make_analysis_style('cc33ff33')
self.glide_style = self.make_analysis_style('cc33ff33', bgcolors, rows)
self.kmz.add_roots(self.glide_style)
#
self.time_mark_styles = []
@ -186,7 +234,7 @@ class Flight(object):
- self.track.bounds.time.min).seconds
hour, seconds = divmod(duration, 3600)
minute, second = divmod(seconds, 60)
rows.append(('Duration', '%d:%02d:%02d' % (hour, minute, second)))
rows.append(('Duration', '%dh %02dm %02ds' % (hour, minute, second)))
if self.track.elevation_data:
rows.append(('Take-off altitude', '%dm' % self.track.coords[0].ele))
rows.append(('Maximum altitude', '%dm' % self.track.bounds.ele.max))
@ -576,57 +624,44 @@ class Flight(object):
dt = self.track.t[sl.stop] - self.track.t[sl.start]
dp = coord0.distance_to(coord1)
theta = coord0.initial_bearing_to(coord1)
rows = []
if title == 'thermal':
rows.append(('Altitude gain', '%dm' % dz))
rows.append(('Average climb', '%.1fm/s' % (dz / dt)))
rows.append(('Maximum climb', '%.1fm/s' % climb.max))
rows.append(('Peak climb', '%.1fm/s' % peak_climb.max))
efficiency = dz / (dt * climb.max)
rows.append(('Efficiency', '%d%%' % (100.0 * efficiency + 0.5)))
elif title == 'glide':
rows.append(('Altitude loss', '%dm' % dz))
rows.append(('Distance', '%.1fkm' % (dp / 1000.0)))
if dz < 0:
average_ld = '%.1f:1' % (-dp / dz)
else:
average_ld = '%s:1' % INFINITY
rows.append(('Average glide ratio', average_ld))
rows.append(('Average speed', '%.1fkm/h' % (3.6 * dp / dt)))
elif title == 'dive':
rows.append(('Altitude loss', '%dm' % dz))
rows.append(('Average descent', '%.1fm/s' % (dz / dt)))
rows.append(('Maximum descent', '%.1fm/s' % climb.min))
rows.append(('Peak descent', '%.1fm/s' % peak_climb.min))
rows.append(('Start altitude', '%dm' % coord0.ele))
rows.append(('Finish alitude', '%dm' % coord1.ele))
dict = {}
dict['altitude_change'] = int(round(dz))
dict['average_climb'] = round(dz / dt, 1)
dict['maximum_climb'] = round(climb.max, 1)
dict['peak_climb'] = round(peak_climb.max, 1)
divisor = dt * climb.max
if divisor == 0:
dict['efficiency'] = UP_TACK
else:
dict['efficiency'] = int(round(100.0 * dz / divisor))
dict['distance'] = round(dp / 1000.0, 1)
average_ld = round(-dp / dz, 1) if dz < 0 else INFINITY
dict['average_ld'] = average_ld
dict['average_speed'] = round(3.6 * dp / dt, 1)
dict['maximum_descent'] = round(climb.min, 1)
dict['peak_descent'] = round(peak_climb.min, 1)
dict['start_altitude'] = coord0.ele
dict['finish_altitude'] = coord1.ele
start_time = coord0.dt + globals.tz_offset
rows.append(('Start time', start_time.strftime('%H:%M:%S')))
dict['start_time'] = start_time.strftime('%H:%M:%S')
stop_time = coord1.dt + globals.tz_offset
rows.append(('Finish time', stop_time.strftime('%H:%M:%S')))
dict['finish_time'] = stop_time.strftime('%H:%M:%S')
duration = self.track.t[sl.stop] - self.track.t[sl.start]
rows.append(('Duration', '%d:%02d' % divmod(duration, 60)))
rows.append(('Accumulated altitude gain',
'%dm' % total_dz_positive))
rows.append(('Accumulated altitude loss',
'%dm' % total_dz_negative))
if title == 'thermal':
drift_speed = dp / dt
drift_direction = rad_to_compass(theta + pi)
rows.append(('Drift', '%.1fkm/h %s'
% (3.6 * drift_speed, drift_direction)))
table = make_table(rows)
dict['duration'] = '%dm %02ds' % divmod(duration, 60)
dict['accumulated_altitude_gain'] = total_dz_positive
dict['accumulated_altitude_loss'] = total_dz_negative
dict['drift_direction'] = rad_to_compass(theta + pi)
extended_data = kml.ExtendedData.dict(dict)
if title == 'thermal':
name = '%dm at %.1fm/s' % (dz, dz / dt)
elif title == 'glide':
ld = '%.1f:1' % (-dp / dz) if dz < 0 else '%s:1' % INFINITY
name = '%.1fkm at %s, %dkm/h' % (dp / 1000.0, ld,
3.6 * dp / dt + 0.5)
name = '%.1fkm at %s:1, %dkm/h' \
% (dp / 1000.0, average_ld, round(3.6 * dp / dt))
elif title == 'dive':
name = '%dm at %.1fm/s' % (-dz, dz / dt)
placemark = kml.Placemark(point,
extended_data,
name=name,
description=kml.CDATA(table),
Snippet=None,
styleUrl=style_url)
folder.add(placemark)

1
igc2kmz/kml.py

@ -173,6 +173,7 @@ class altitude(_SimpleElement): pass
class altitudeMode(_SimpleElement): pass
class BalloonStyle(_CompoundElement): pass
class begin(_SimpleElement): pass
class bgColor(_SimpleElement): pass
class Camera(_CompoundElement): pass

Loading…
Cancel
Save