From a96ad8d77b27251b81dead32d352c281ef788fed Mon Sep 17 00:00:00 2001 From: Buck Heroux Date: Wed, 5 Mar 2014 21:25:46 -0700 Subject: [PATCH] implemented quadkey, tests don't pass --- clean | 0 quadkey/.__init__.py.swp | Bin 0 -> 12288 bytes quadkey/__init__.py | 19 +++++++----- quadkey/tile_system.py | 65 +++++++++++++++++++++++++++++++++++++-- tests/quadkey_tests.py | 5 ++- tests/tile_system.py | 9 ++++++ 6 files changed, 87 insertions(+), 11 deletions(-) mode change 100644 => 100755 clean create mode 100644 quadkey/.__init__.py.swp 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 0000000000000000000000000000000000000000..42a9598edbde6943c8e2b2581002096762ba1391 GIT binary patch literal 12288 zcmeI2J!=#}7{@2+7K|^kun=MN3NN~M7n364KnT}G2^bQ!QHIIxoGv%Fv(C;1uTikF z5$ydA+E^>7U%@Y6so2{H{&#j4b9WIT-NCc)zqy%t-sU&cEIS9Q_qKQVMthy%Im=k@ z*M+^sOOkD2;9wLDisAn~J=o=~9U1kE8MN+L)7B=EddBTp5wLUL*g>AjNOcOU#B_E? zGQO?GohN7qXoX19#0k;P#xo&kfCvzQlMooWert1yt*_l!E!-PdF7xxtcTW>Y5tvf~E?Z#FQTt+5f1_#_rrN4Y4G|y$M1Tko0U|&IhyW2F0z`la z5CI}EhXiEI*o#w)U0Xu&`2JtN|9?Bf*hlCC^bUFpy@C|930;Mjp>xph(~SLqzC&N3 z&(J66J@f{82}RH?XdCK67onfX`2~6nrO-p@0ki|HLDwN)*Bo-Cl8FEjAOb{y2oM1x zKm>>Y5twTNL6FHjXF;s`{E>1ZGRDS9DxJ!kxVOC0Wx-bNq)Vcqa*qvOtb)KQH?k?O zt~O&Jvq|dUZbF_VPn8b2OSB4)SX8$BCf~=*-Z*z^*e;BOGoqSomQGq7D!qcJMR(G{ z2QNH|siyB0hW^i_C2A?`{7lmqR)?(@S|>d+*$w`^*huG-aRN9Z=Wcn=yL}uxl;*R- zOsmx6EJ63J8H(K5CZdMC#vEzv#0=$J>3$m~rKb>9Wmbr0F^tVYifT8e?GS##%+LQV z2aMtC2g`-vw;n*Ysg)fA3&stOf|Ye#OBZr&QZCaNOGRuht>TALCvjbOdHvnj9hOI> v+!3t7FT5s+eu2lIAd&ln!joZUkY*pdULKv&WQ1c-&t+CcCXEx9n3VkiY&I@# literal 0 HcmV?d00001 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)