diff --git a/clean b/clean old mode 100644 new mode 100755 diff --git a/quadkey/.__init__.py.swp b/quadkey/.__init__.py.swp new file mode 100644 index 0000000..42a9598 Binary files /dev/null and b/quadkey/.__init__.py.swp differ diff --git a/quadkey/__init__.py b/quadkey/__init__.py index abe4fb5..bb07777 100644 --- a/quadkey/__init__.py +++ b/quadkey/__init__.py @@ -3,11 +3,10 @@ class QuadKey: - def __init__(self, lat, lon, level): + def __init__(self, geo, level): # assert lat, lon and level are valid - self.key = QuadKey.get_quadkey(lat, lon, level) - self.lat = lat - self.lon = lon + self.key = QuadKey.get_quadkey(geo, level) + self.geo = geo self.level = level def __str__(self): @@ -19,12 +18,16 @@ def __repr__(self): @classmethod def from_str(cls, key): level = len(key) - lat, lon = QuadKey.get_coordinates(key) - return cls(lat, lon, level) + geo = QuadKey.get_coordinates(key) + return cls(geo, level) @staticmethod - def get_quadkey(lat, lon, level): - pass + def get_quadkey(geo, level): + pixel = TileSystem.geo_to_pixel(geo, level) + tile = TileSystem.pixel_to_tile(pixel) + quadkey = TileSystem.tile_to_quadkey(tile, level) + print geo, pixel, tile, quadkey + return quadkey @staticmethod def get_coordinates(key): diff --git a/quadkey/tile_system.py b/quadkey/tile_system.py index 4d7719b..2491eb4 100644 --- a/quadkey/tile_system.py +++ b/quadkey/tile_system.py @@ -1,5 +1,5 @@ from util import precondition -from math import cos, pi +from math import sin, cos, atan, exp, log, pi def valid_level(level): LEVEL_RANGE = (1,23) @@ -9,7 +9,6 @@ class TileSystem: """ Class with static method to build quadkeys from lat, lon, levels see http://msdn.microsoft.com/en-us/library/bb259689.aspx - """ EARTH_RADIUS = 6378137 @@ -41,3 +40,65 @@ def map_scale(lat, level, dpi): """Gets the scale of the map expressed as ratio 1 : N. Returns N""" return TileSystem.ground_resolution(lat, level) * dpi / 0.0254 + @staticmethod + @precondition(lambda geo, lvl: valid_level(lvl)) + def geo_to_pixel(geo, level): + """Transform from geo coordinates to pixel coordinates""" + lat, lon = geo + lat = TileSystem.clip(lat, TileSystem.LATITUDE_RANGE) + lon = TileSystem.clip(lon, TileSystem.LONGITUDE_RANGE) + x = (lon + 180) / 360 + sin_lat = sin(lat * pi / 180) + y = 0.5 - log((1 + sin_lat) / (1 - sin_lat) / (4 * pi)) + # might need to cast to uint + map_size = TileSystem.map_size(level) + pixel_x = int(TileSystem.clip(x * map_size + 0.5, (0, map_size - 1))) + pixel_y = int(TileSystem.clip(y * map_size + 0.5, (0, map_size - 1))) + return pixel_x, pixel_y + + @staticmethod + @precondition(lambda pix, lvl: valid_level(lvl)) + def pixel_to_geo(pixel, level): + """Transform from pixel to geo coordinates""" + pixel_x = pixel[0] + pixel_y = pixel[1] + map_size = float(TileSystem.map_size(level)) + x = (TileSystem.clip(pixel_x, (0, map_size - 1)) / map_size) - 0.5 + y = 0.5 - ( TileSystem.clip(pixel_y, (0, map_size - 1)) / map_size) + lat = 90 - 360 * atan(exp(-y * 2 * pi)) / pi + lon = 360 * x + return lat, lon + + @staticmethod + def pixel_to_tile(pixel): + """Transform pixel to tile coordinates""" + return pixel[0] / 256, pixel[1] / 256 + + @staticmethod + def tile_to_pixel(tile): + """Transform tile to pixel coordinates""" + return tile[0] * 256, tile[1] * 256 + + @staticmethod + @precondition(lambda tile, lvl: valid_level(lvl)) + def tile_to_quadkey(tile, level): + """Transform tile coordinates to a quadkey""" + tile_x = tile[0] + tile_y = tile[1] + quadkey = "" + for i in xrange(level): + bit = level - i + digit = ord('0') + mask = 1 << (bit - 1) #if (bit - 1) > 0 else 1 >> (bit - 1) + if (tile_x & mask) is not 0: + digit += 1 + if (tile_y & mask) is not 0: + digit += 2 + quadkey += chr(digit) + return quadkey + + @staticmethod + def quadkey_to_tile(quadkey): + """Transform quadkey to tile coordinates""" + pass + diff --git a/tests/quadkey_tests.py b/tests/quadkey_tests.py index 3aa5970..895d703 100644 --- a/tests/quadkey_tests.py +++ b/tests/quadkey_tests.py @@ -14,7 +14,10 @@ def testToString(self): pass def testGetQuadKey(self): - pass + geo = (40, -105) + level = 9 + key = '023101012' + self.assertEqual(key, QuadKey.get_quadkey(geo, level)) def testGetCoordinates(self): pass diff --git a/tests/tile_system.py b/tests/tile_system.py index fd02aa1..527e928 100644 --- a/tests/tile_system.py +++ b/tests/tile_system.py @@ -24,19 +24,28 @@ def testMapScale(self): TileSystem.map_scale(45, 7, 45) def testGeoToPixel(self): + geo = (-105, 45) + level = 7 TileSystem.geo_to_pixel(geo, level) def testPixelToGeo(self): + pixel = (50, 45) + level = 7 TileSystem.pixel_to_geo(pixel, level) def testPixelToTile(self): + pixel = (50, 45) TileSystem.pixel_to_tile(pixel) def testTileToPixel(self): + tile = (3,3) TileSystem.tile_to_pixel(tile) def testTileToQuadkey(self): + tile = (3,3) + level = 7 TileSystem.tile_to_quadkey(tile, level) def testQuadkeyToTile(self): + quadkey = '00' TileSystem.quadkey_to_tile(quadkey)