From 82bd1826dad7f6d7cec04bd9c4125230c4e50c90 Mon Sep 17 00:00:00 2001 From: "U-NORTHAMERICA\\taheroux" Date: Thu, 6 Mar 2014 13:29:05 -0700 Subject: [PATCH] cahnged QuadKey interface --- README.md | 9 ++++---- quadkey/__init__.py | 47 ++++++++++++++++++++++++------------------ quadkey/tile_system.py | 7 +++++-- tests/quadkey_tests.py | 15 +++++++++++--- 4 files changed, 49 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 14e46c4..35e2f0f 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@ QuadKey Quad key object used for Geospatial segmentation + from quadkey import QuadKey - quadkey = QuadKey(-105, 50, 17) - quadkey.lat - quadkey.lon - copy = QuadKey.from_str(quadkey.key) + qk = QuadKey((-105, 40) 17) + print qk.key # => 02310101232121212 + assert qk.level is 17 + copy = QuadKey.from_str(qk.key) diff --git a/quadkey/__init__.py b/quadkey/__init__.py index 655f188..a7fcc15 100644 --- a/quadkey/__init__.py +++ b/quadkey/__init__.py @@ -1,15 +1,24 @@ from util import precondition -from tile_system import TileSystem +from tile_system import TileSystem, valid_key class QuadKey: - def __init__(self, geo, level): - # assert lat, lon and level are valid - self.key = QuadKey.get_quadkey(geo, level) - self.geo = geo - self.latitude = geo[0] - self.longitude = geo[1] - self.level = level + @precondition(lambda c, key: valid_key(key)) + def __init__(self, key): + """ + A quadkey must be between 1 and 23 digits and can only contain digit[0-3] + """ + self.key = key + self.level = len(key) + + def is_parent(self, parent): + return self != parent and parent.key[:len(self.key)-1] == self.key + + def __eq__(self, other): + return self.key == other.key + + def __ne__(self, other): + return not self.__eq__(other) def __str__(self): return self.key @@ -17,20 +26,18 @@ def __str__(self): def __repr__(self): return self.key - @classmethod - def from_str(cls, key): - level = len(key) - geo = QuadKey.get_coordinates(key) - return cls(geo, level) - @staticmethod - def get_quadkey(geo, level): + def from_geo(geo, level): + """ + Constucts a quadkey representation from geo and level + geo => (lat, lon) + If lat or lon are outside of bounds, they will be clipped + If level is outside of bounds, an AssertionError is raised + + """ pixel = TileSystem.geo_to_pixel(geo, level) tile = TileSystem.pixel_to_tile(pixel) - quadkey = TileSystem.tile_to_quadkey(tile, level) - return quadkey + key = TileSystem.tile_to_quadkey(tile, level) + return QuadKey(key) - @staticmethod - def get_coordinates(key): - pass diff --git a/quadkey/tile_system.py b/quadkey/tile_system.py index dfd107b..8e6eb88 100644 --- a/quadkey/tile_system.py +++ b/quadkey/tile_system.py @@ -1,18 +1,21 @@ from util import precondition from math import sin, cos, atan, exp, log, pi -from decimal import * def valid_level(level): LEVEL_RANGE = (1,23) return LEVEL_RANGE[0] <= level <= LEVEL_RANGE[1] -getcontext().prec = 6 +@precondition(lambda key: valid_level(len(key))) +def valid_key(key): + return TileSystem.KEY_PATTERN.match(key) is not None class TileSystem: """ Class with static method to build quadkeys from lat, lon, levels see http://msdn.microsoft.com/en-us/library/bb259689.aspx """ + import re + KEY_PATTERN = re.compile("^[0-3]+$") EARTH_RADIUS = 6378137 LATITUDE_RANGE = (-85.05112878, 85.05112878) diff --git a/tests/quadkey_tests.py b/tests/quadkey_tests.py index b276289..afbcd57 100644 --- a/tests/quadkey_tests.py +++ b/tests/quadkey_tests.py @@ -5,7 +5,11 @@ class QuadKeyTest(TestCase): def testInit(self): - pass + qk = QuadKey('0321201120') + with self.assertRaises(AssertionError): + qk = QuadKey('') + with self.assertRaises(AssertionError): + qk = QuadKey('0156510012') def testFromString(self): pass @@ -16,8 +20,13 @@ def testToString(self): def testGetQuadKey(self): geo = (40, -105) level = 7 - key = '0231010' - self.assertEqual(key, QuadKey.get_quadkey(geo, level)) + key = QuadKey('0231010') + self.assertEqual(key, QuadKey.from_geo(geo, level)) def testGetCoordinates(self): pass + + def testIsParent(self): + child = QuadKey('0011') + parent = QuadKey('00') + self.assertTrue(child.is_parent(parent))