3 # WARNING: I haven't thought much about the best way of doing
4 # this. it may get lots of extra caches, or take a long
5 # time if your path goes thru a city.
6 # there's probably a better algorithm.
11 # get geocaches, circles of "radius", then go ahead advance_dist in the track and do it again.
12 #radius = maxdist * 2 * 0.707106 # sqrt(2)
14 advance_dist
= maxdist
* 2
17 # TODO: shell escape in case mkdtemp has unsafe chars in (unlikely)
20 def __init__(self
, lat
=0.0, lon
=0.0):
24 # diff between two coords in meters.
26 from math
import acos
, sin
, cos
27 PIOVER180
= 3.14159265358979 / 180.0
28 EquatorialRadius
= 6378137 # WGS-84
29 lat1
= c1
.lat
* PIOVER180
30 lon1
= c1
.lon
* PIOVER180
31 lat2
= c2
.lat
* PIOVER180
32 lon2
= c2
.lon
* PIOVER180
33 return EquatorialRadius
* acos(sin(lat1
)*sin(lat2
)+cos(lat1
)*cos(lat2
)*cos(lon1
-lon2
));
35 def load_track ( file ):
37 latlonre
= re
.compile("lat=['\"]([0-9\\-\\.]*?)['\"].*lon=['\"]([0-9\\-\\.]*?)['\"]")
40 match
= latlonre
.search(line
)
42 lat
= float(match
.group(1))
43 lon
= float(match
.group(2))
44 track
.append ( Coord(lat
,lon
) )
47 # position inside of a track = index of trackpoint + meters past this trackpoint
49 def __init__(self
, track
):
51 self
.n_tps
= len(self
.track
)
52 self
.i_lasttp
= 0 # index of tp before current position
53 self
.dist_past
= 0 # meters past this tp
58 self
.coord
.lat
= track
[0].lat
59 self
.coord
.lon
= track
[0].lon
64 self
.finished
= True # no tps in track, nothing to do
66 def recalculate_coord(self
):
67 if self
.i_lasttp
>= self
.n_tps
- 1:
68 self
.coord
= self
.track
[self
.n_tps
- 1] # return last tp
71 c1
= self
.track
[self
.i_lasttp
]
72 c2
= self
.track
[self
.i_lasttp
+1]
75 percentage_past
= self
.dist_past
/ Coord
.diff ( c1
, c2
)
76 self
.coord
.lat
= c1
.lat
+ percentage_past
* (c2
.lat
- c1
.lat
)
77 self
.coord
.lon
= c1
.lon
+ percentage_past
* (c2
.lon
- c1
.lon
)
79 def advance(self
, distance
):
80 if self
.i_lasttp
>= (self
.n_tps
- 1):
85 # possibility one: we don't pass a TP
86 dist_to_next_tp
= Coord
.diff ( self
.track
[self
.i_lasttp
], self
.track
[self
.i_lasttp
+1] ) - self
.dist_past
87 if dist_to_next_tp
> distance
:
88 self
.dist_past
+= distance
89 self
.recalculate_coord()
91 # goto beginning of next tp and try again.
95 if self
.i_lasttp
>= (self
.n_tps
- 1):
96 self
.recalculate_coord()
98 self
.advance ( distance
- dist_to_next_tp
)
100 # dist_after_pos = dist_after_i
101 # if self.track[i_lasttp
108 def get_geocaches_for(coord
,radius
,tmpdir
,i
):
111 radiusinmiles
= radius
* 100 / 2.54 / 12 / 5280 # meters to miles
112 gcgetstr
= "gcget %f,%f %d %f > %s/%d.loc" % (coord
.lat
, coord
.lon
, MAXGCS
, radius
, tmpdir
, i
)
113 sys
.stderr
.write("%s\n" % gcgetstr
)
115 #print "type=\"trackpoint\" latitude=\"%f\" longitude=\"%f\"" % (coord.lat, coord.lon)
122 tr
= load_track ( sys
.stdin
)
126 tmpdir
= tempfile
.mkdtemp()
129 while not tpos
.end():
130 get_geocaches_for ( tpos
.coord
, radius
, tmpdir
, i
)
131 tpos
.advance ( advance_dist
)
133 get_geocaches_for ( tpos
.coord
, radius
, tmpdir
, i
)
135 ####### condense all #######
136 gb_input_args
= ["-i geo -f %s/%d.loc" % (tmpdir
,j
) for j
in range(i
)]
137 gb_string
= "gpsbabel %s -x duplicate,location -o gpx -F -" % (" ".join(gb_input_args
))
138 sys
.stderr
.write("\n%s\n" % gb_string
)
141 ####### delete temp files #######
143 os
.sys
.remove("%s/%d.loc" % (tmpdir
,j
))