Skip to content

Commit 73d417b

Browse files
committed
Merge pull request #15 from tomasbedrich/dev
Added UTFGrid parsing, localization independant parsing
2 parents 618f7fd + d7455c0 commit 73d417b

15 files changed

+1155
-55
lines changed

README.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,21 @@ Find all caches on some adress
129129
for cache in geocaching.search(point, limit=10):
130130
print(cache.name)
131131

132+
Find approximate location of caches in area
133+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
134+
135+
::
136+
137+
from pycaching import Geocaching, Point, Rectangle
138+
139+
geocaching = pycaching.Geocaching()
140+
geocaching.login("user", "pass")
141+
rect = Rectangle(Point(60.15, 24.95), Point(60.17, 25.00))
142+
for c in geocaching.search_quick(rect, strict=True):
143+
print('{:8} ({:.5f}, {:.5f}) (+- {:.1f} m); {}'.format(
144+
c.wp, c.location.latitude, c.location.longitude,
145+
c.location.precision, c.name))
146+
132147

133148
--------
134149
Appendix

pycaching/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pycaching.cache import Cache # NOQA
77
from pycaching.util import Util # NOQA
88
from pycaching.point import Point # NOQA
9+
from pycaching.area import Rectangle # NOQA
910
from pycaching.errors import * # NOQA
1011

1112

pycaching/area.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env python3
2+
3+
from pycaching.point import Point
4+
5+
6+
class Area:
7+
"""Geometrical area"""
8+
pass
9+
10+
11+
class Polygon(Area):
12+
"""Area defined by bordering Point instances"""
13+
14+
def __init__(self, *points):
15+
"""Define polygon by list of consecutive Points"""
16+
assert len(points) >= 3
17+
self.points = points
18+
19+
@property
20+
def bounding_box(self):
21+
"""Get extreme latitude and longitude values.
22+
23+
Return Rectangle that contains all points"""
24+
25+
lats = sorted([p.latitude for p in self.points])
26+
lons = sorted([p.longitude for p in self.points])
27+
return Rectangle(Point(min(lats), min(lons)),
28+
Point(max(lats), max(lons)))
29+
30+
@property
31+
def mean_point(self):
32+
"""Return point with average latitude and longitude of points"""
33+
lats = [p.latitude for p in self.points]
34+
lons = [p.longitude for p in self.points]
35+
return Point(sum(lats) / len(lats), sum(lons) / len(lons))
36+
37+
@property
38+
def diagonal(self):
39+
"""Return bounding box diagonal"""
40+
return self.bounding_box.diagonal
41+
42+
43+
class Rectangle(Polygon):
44+
"""Upright rectangle"""
45+
46+
def __init__(self, point_a, point_b):
47+
"""Create rectangle defined by opposite corners
48+
49+
Parameters point_a and point_b are Point instances."""
50+
51+
assert point_a != point_b, "Corner points cannot be the same"
52+
self.corners = [point_a, point_b]
53+
self.points = [point_a, Point(point_a.latitude, point_b.longitude),
54+
point_b, Point(point_b.latitude, point_a.longitude)]
55+
56+
def inside_area(self, point):
57+
"""Is point inside area?"""
58+
lats = sorted([p.latitude for p in self.points])
59+
lons = sorted([p.longitude for p in self.points])
60+
if min(lats) <= point.latitude <= max(lats):
61+
if min(lons) <= point.longitude <= max(lons):
62+
return True
63+
return False
64+
65+
@property
66+
def diagonal(self):
67+
"""Return rectangle diagonal"""
68+
return self.corners[0].distance(self.corners[1])

pycaching/cache.py

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -97,37 +97,36 @@ class Cache(object):
9797
}
9898

9999
_possible_types = {
100-
"Traditional Cache",
101-
"Multi-Cache",
102-
"Unknown Cache",
103-
"Mystery Cache",
104-
"Letterbox Hybrid",
105-
"Event Cache",
106-
"Mega-Event Cache",
107-
"Giga-Event Cache",
108-
"Earthcache",
109-
"Cache In Trash Out Event",
110-
"Webcam Cache",
111-
"Virtual Cache",
112-
"Wherigo Cache",
113-
"Lost And Found Event Cache",
114-
"Project Ape Cache",
115-
"Groundspeak Hq",
116-
"Gps Adventures Exhibit",
117-
"Groundspeak Block Party",
118-
"Locationless (Reverse) Cache",
100+
# key is cache image url, used for parsing: http://www.geocaching.com/images/WptTypes/[KEY].gif
101+
"2": "Traditional Cache",
102+
"3": "Multi-cache",
103+
"8": "Mystery Cache",
104+
"__8": "Unknown Cache", # same as Mystery, key not used
105+
"5": "Letterbox hybrid",
106+
"6": "Event Cache",
107+
"mega": "Mega-Event Cache",
108+
"giga": "Giga-Event Cache",
109+
"earthcache": "Earthcache",
110+
"13": "Cache in Trash out Event",
111+
"11": "Webcam Cache",
112+
"4": "Virtual Cache",
113+
"1858": "Wherigo Cache",
114+
"10Years_32": "Lost and Found Event Cache",
115+
"ape_32": "Project Ape Cache",
116+
"HQ_32": "Groundspeak HQ",
117+
"1304": "GPS Adventures Exhibit",
118+
"4738": "Groundspeak Block Party",
119+
"12": "Locationless (Reverse) Cache",
119120
}
120121

121122
_possible_sizes = {
122-
"nano",
123-
"micro",
124-
"small",
125-
"regular",
126-
"large",
127-
"very large",
128-
"not chosen",
129-
"virtual",
130-
"other"
123+
"micro": "micro",
124+
"small": "small",
125+
"regular": "regular",
126+
"large": "large",
127+
"not_chosen": "not chosen",
128+
"virtual": "virtual",
129+
"other": "other",
131130
}
132131

133132
def __init__(self, wp, geocaching, *, name=None, cache_type=None, location=None, state=None,
@@ -225,11 +224,14 @@ def cache_type(self):
225224

226225
@cache_type.setter
227226
def cache_type(self, cache_type):
228-
cache_type = cache_type.strip().title()
227+
cache_type = cache_type.strip()
229228
cache_type = cache_type.replace("Geocache", "Cache")
230-
if cache_type not in self._possible_types:
229+
if cache_type in self._possible_types.values(): # try to search in values
230+
self._cache_type = cache_type
231+
elif cache_type in self._possible_types.keys(): # not in values => it must be a key
232+
self._cache_type = self._possible_types[cache_type]
233+
else:
231234
raise ValueError("Cache type '{}' is not possible.".format(cache_type))
232-
self._cache_type = cache_type
233235

234236
@property
235237
@lazy_loaded
@@ -257,9 +259,12 @@ def size(self):
257259
@size.setter
258260
def size(self, size):
259261
size = size.strip().lower()
260-
if size not in self._possible_sizes:
262+
if size in self._possible_sizes.values(): # try to search in values
263+
self._size = size
264+
elif size in self._possible_sizes.keys(): # not in values => it must be a key
265+
self._size = self._possible_sizes[size]
266+
else:
261267
raise ValueError("Size '{}' is not possible.".format(size))
262-
self._size = size
263268

264269
@property
265270
@lazy_loaded
@@ -372,3 +377,7 @@ def pm_only(self):
372377
@pm_only.setter
373378
def pm_only(self, pm_only):
374379
self._pm_only = bool(pm_only)
380+
381+
def inside_area(self, area):
382+
"""Calculate if geocache is inside given area"""
383+
return area.inside_area(self.location)

0 commit comments

Comments
 (0)