Advertisement
Guest User

Yandex Maps Base64 encoding realization

a guest
Dec 18th, 2010
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.06 KB | None | 0 0
  1. # Copyright (C) 2010 Andrey Solomatin
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License along
  14. # with this program; if not, write to the Free Software Foundation, Inc.,
  15. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16.  
  17. # -*- coding: UTF-8 -*-
  18. from decimal import Decimal
  19. import re
  20.  
  21. 'http://api.yandex.ru/maps/jsapi/doc/dg/tasks/how-to-add-polyline.xml#encoding-polyline-points'
  22.  
  23. code_string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="
  24.  
  25. def to_bin(n):
  26.     HexBin = {"0":"0000", "1":"0001", "2":"0010", "3":"0011", "4":"0100", "5":"0101", "6":"0110", "7":"0111", "8":"1000", "9":"1001", "A":"1010", "B":"1011", "C":"1100", "D":"1101", "E":"1110", "F":"1111"}
  27.     res = "".join([HexBin[i] for i in '%X' % n]).lstrip('0')
  28.     return res
  29.  
  30. # gets difference between coords
  31. def _diff(coords, index):
  32.     x1, y1 = coords[index + 1]
  33.     x2, y2 = coords[index]
  34.     return x1 - x2, y1 - y2
  35.  
  36. def _fromBit(line): # and revers
  37.     eight = zip(*[iter(line)] * 8)[::-1]
  38.     num = "".join(["".join(x) for x in eight])
  39.     if num[0] == "0":
  40.         res = int(num, 2)
  41.     else:
  42.         res = int(num, 2) - 4294967296
  43.     return res
  44.          
  45. def _toBit(decim): # and revers
  46.     """convert decimal to  bit   Fill it to 4 bytes (32 bits) and reverse bytes.
  47.    Args:
  48.    decim : Decimal number for convertation
  49.    
  50.    Return:
  51.    String
  52.    """
  53.     n = int(decim)
  54.     if n < 0:
  55.         n += 4294967296
  56.     n = to_bin(n)
  57.     #HexBin ={"0":"0000", "1":"0001", "2":"0010", "3":"0011", "4":"0100", "5":"0101", "6":"0110", "7":"0111", "8":"1000", "9":"1001", "A":"1010", "B":"1011", "C":"1100", "D":"1101", "E":"1110", "F":"1111"}
  58.     #n = "".join([HexBin[i] for i in '%X'%n]).lstrip('0')
  59.     n = n.rjust(32, "0")
  60.     n = re.findall("\d{8}", n)
  61.     n.reverse()
  62.     return str().join(n)
  63.  
  64. def encode_base64_yandex(tuple_of_coord_pairs):
  65.     """Converts coordinates to string
  66.    Keyword arguments:
  67.    tuple_of_coord_pairs ((lat,lang),(lat,lang),...)
  68.    Returns: string
  69.    """
  70.    
  71.     coords = [(Decimal(str(x).strip()) * 10**6, Decimal(str(y).strip())*10 ** 6)for y, x in tuple_of_coord_pairs]
  72.     if not coords: return ""
  73.     new_coords = [coords[0]]
  74.     if len(coords) is 1:
  75.         line = str().join([_toBit(x) + _toBit(y) for x, y in new_coords])
  76.     for index in range(len(coords) - 1):
  77.         new_coords.append(_diff(coords, index))
  78.         line = str().join([_toBit(x) + _toBit(y) for x, y in new_coords])
  79.     ends = ""
  80.     if len(line) % 6 == 2:
  81.         ends = "=="
  82.         line += "0000"
  83.     elif len(line) % 6 == 4:
  84.         ends = "="
  85.         line += "00"
  86.     return  str().join([code_string[int(x, 2)] for x in re.findall("\d{6}|\d{4}|\d{2}", line)]) + ends
  87.  
  88. def decode_base64_yandex(text):
  89.     line = [to_bin(code_string.index(x)).rjust(6, "0") for x in text]
  90.     line = "".join(line)
  91.     line = zip(*[iter(line)] * 32)
  92.     nums = [_fromBit("".join(x)) for x in line]
  93.     if not nums:
  94.         return []
  95.     lats = nums[::2]
  96.     longs = nums[1::2]  
  97.     last = [(lats[0], longs[0]), ]
  98.     for ind in xrange(1, len(lats)):
  99.         last.append((lats[ind] + last[ind - 1][0], longs[ind] + last[ind - 1][1]))
  100.     last = [(Decimal(x[0]) / 10 ** 6, Decimal(x[1]) / 10 ** 6) for x in last]
  101.     return [[str(y) for y in x[::-1]] for x in last]
  102.  
  103. if __name__ == "__main__":
  104.     line = [
  105.             ("37.593578", "55.735094"),
  106.             ("37.592159", "55.732469"),
  107.             ("37.589374","55.734162"),]
  108.    
  109.    
  110.     a =  encode_base64_yandex(line)
  111.  
  112.     c = decode_base64_yandex(a)
  113.     print c
  114.     print line
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement