File: gctrackbyarc.py

package info (click to toggle)
viking 1.11-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 18,468 kB
  • sloc: ansic: 81,706; xml: 2,893; sh: 2,501; makefile: 874; python: 589; perl: 384; cpp: 259
file content (144 lines) | stat: -rwxr-xr-x 4,096 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python

# WARNING: I haven't thought much about the best way of doing
#	   this. it may get lots of extra caches, or take a long
#	   time if your path goes thru a city.
# there's probably a better algorithm.

# in meters.
maxdist = 2500.0

# get geocaches, circles of "radius", then go ahead advance_dist in the track and do it again.
#radius = maxdist * 2 * 0.707106 # sqrt(2)
radius = maxdist * 2
advance_dist = maxdist * 2


# TODO: shell escape in case mkdtemp has unsafe chars in (unlikely)

class Coord:
  def __init__(self, lat=0.0, lon=0.0):
    self.lat = lat
    self.lon = lon

  # diff between two coords in meters.
  def diff(c1,c2):
    from math import acos, sin, cos
    PIOVER180 = 3.14159265358979 / 180.0
    EquatorialRadius = 6378137 # WGS-84
    lat1 = c1.lat * PIOVER180
    lon1 = c1.lon * PIOVER180
    lat2 = c2.lat * PIOVER180
    lon2 = c2.lon * PIOVER180
    return EquatorialRadius * acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2));

def load_track ( file ):
  import re
  latlonre = re.compile("lat=['\"]([0-9\\-\\.]*?)['\"].*lon=['\"]([0-9\\-\\.]*?)['\"]")
  track = []
  for line in file:
    match = latlonre.search(line)
    if match:
      lat = float(match.group(1))
      lon = float(match.group(2))
      track.append ( Coord(lat,lon) )
  return track

# position inside of a track = index of trackpoint + meters past this trackpoint
class TPos:
  def __init__(self, track):
    self.track = track
    self.n_tps = len(self.track)
    self.i_lasttp = 0 # index of tp before current position
    self.dist_past = 0 # meters past this tp

    self.coord = Coord()

    if self.n_tps > 0:
      self.coord.lat = track[0].lat
      self.coord.lon = track[0].lon

    if self.n_tps > 1:
      self.finished = False
    else:
      self.finished = True # no tps in track, nothing to do

  def recalculate_coord(self):
    if self.i_lasttp >= self.n_tps - 1:
      self.coord = self.track[self.n_tps - 1] # return last tp
      return

    c1 = self.track[self.i_lasttp]
    c2 = self.track[self.i_lasttp+1]

    # APPROXIMATE
    percentage_past = self.dist_past / Coord.diff ( c1, c2 )
    self.coord.lat = c1.lat + percentage_past * (c2.lat - c1.lat)
    self.coord.lon = c1.lon + percentage_past * (c2.lon - c1.lon)

  def advance(self, distance):
    if self.i_lasttp >= (self.n_tps - 1):
      self.finished = True
    if self.finished:
      return

    # possibility one: we don't pass a TP
    dist_to_next_tp = Coord.diff ( self.track[self.i_lasttp], self.track[self.i_lasttp+1] ) - self.dist_past
    if dist_to_next_tp > distance:
      self.dist_past += distance
      self.recalculate_coord()
    else:
      # goto beginning of next tp and try again.
      self.i_lasttp += 1
      self.dist_past = 0

      if self.i_lasttp >= (self.n_tps - 1):
        self.recalculate_coord()
      else:
        self.advance ( distance - dist_to_next_tp )

#    dist_after_pos = dist_after_i
#    if self.track[i_lasttp
# TODO!

  def end(self):
    return self.finished

  
def get_geocaches_for(coord,radius,tmpdir,i):
  import os, sys
  MAXGCS = 100
  radiusinmiles = radius * 100 / 2.54 / 12 / 5280 # meters to miles
  gcgetstr = "gcget %f,%f %d %f > %s/%d.loc" % (coord.lat, coord.lon, MAXGCS, radius, tmpdir, i)
  sys.stderr.write("%s\n" % gcgetstr)
  os.system(gcgetstr)
  #print "type=\"trackpoint\" latitude=\"%f\" longitude=\"%f\"" % (coord.lat, coord.lon)


#------------


import sys, os
tr = load_track ( sys.stdin )
tpos = TPos(tr)

import tempfile
tmpdir = tempfile.mkdtemp()

i = 0
while not tpos.end():
  get_geocaches_for ( tpos.coord, radius, tmpdir, i )
  tpos.advance ( advance_dist )
  i += 1
get_geocaches_for ( tpos.coord, radius, tmpdir, i )

####### condense all #######
gb_input_args = ["-i geo -f %s/%d.loc" % (tmpdir,j) for j in range(i)]
gb_string = "gpsbabel %s -x duplicate,location -o gpx -F -" % (" ".join(gb_input_args))
sys.stderr.write("\n%s\n" % gb_string)
os.system(gb_string)

####### delete temp files #######
for j in range(i):
  os.sys.remove("%s/%d.loc" % (tmpdir,j))
os.sys.rmdir(tmpdir)