Hellerick_Ferlibay

Geoindex_conversion.py

Nov 7th, 2016
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.56 KB | None | 0 0
  1. from math import pi, cos, sin, asin, log, sqrt
  2.  
  3. ##Published here: http://pastebin.com/CR6zg3jT
  4.  
  5. alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  6. ##alpha = '0123456789'
  7. ##alpha = '0123456789abcdef'
  8.  
  9. deg = pi/180
  10.  
  11. Earth_radius = 6371000
  12.  
  13. full_resolution = 5 # meters
  14.  
  15. full_code_length = int(log(4*pi*(Earth_radius/full_resolution)**2)/log(len(alpha)))+1
  16.  
  17. y0, y1, x0, x1 = range(4)
  18. ver, hor = range(2)
  19.  
  20.  
  21. def checklines(lines, box, annotate=False):
  22.     if annotate: print('Checking {} lines'.format(lines))
  23.     span = [box[y1]-box[y0], box[x1]-box[x0]]
  24.     parals = [span[ver]/lines*(i+0.5)+box[y0] for i in range(lines)]
  25.     if annotate: print('Parals:', ['{:.2f}'.format(p) for p in parals])
  26.     lengths = [span[hor] * cos(i*deg) for i in parals]
  27.     if annotate: print('Lengths:', ['{:.2f}'.format(l) for l in lengths])
  28.     share = sum(lengths)/len(alpha)
  29.     divs = lambda s: [round(lengths[i]/s) for i in range(lines)]
  30.     counter = 0
  31.     maxshare = share*1.5
  32.     minshare = share/1.5
  33.     guesses={
  34.         share    : divs(share),
  35.         maxshare : divs(maxshare),
  36.         minshare : divs(minshare),
  37.         }
  38.     while not len(alpha) in [sum(i) for i in guesses.values()]:
  39.         counter+=1
  40.         maxshare = max(i for i in guesses if sum(guesses[i])>=len(alpha))
  41.         minshare = min(i for i in guesses if sum(guesses[i])<=len(alpha))
  42.         if annotate:
  43.             for i in guesses: print(*i)
  44.             print(' ', maxshare, divs(maxshare), minshare, divs(minshare))
  45.         share = (maxshare+minshare)/2
  46.         if share in guesses:
  47. ##            if annotate:
  48. ##                print('No solution found')
  49. ##                print(' ', share, divs(share))            
  50.             if (lines%2==1) and (abs(sum(guesses[share])-len(alpha))==1):
  51.                 guesses[share][lines//2] = guesses[share][lines//2]-sum(guesses[share])+len(alpha)
  52.         else:
  53.             guesses[share] = divs(share)
  54.     if 0 in guesses[share]:
  55.         return guesses[share], len(alpha)
  56.     params = [span[ver]/lines, *[lengths[i]/divs(share)[i] for i in range(lines)] ]
  57.     inequality=max(params)/min(params)
  58.     if annotate:
  59.         print(' Params', params)
  60.         print(' Inequality {:.4f}'.format(inequality))
  61.     return guesses[share], inequality
  62.    
  63.  
  64. def split(box, annotate=False):
  65.     # box: list of four coordinates, degrees:
  66.     # y0, y1: bottom and top borders
  67.     # x0, x1: left and right borders
  68.     if annotate: print('Splitting {:.4f} {:.4f} {:.4f} {:.4f}'.format(*box))
  69.     subsectionVariants = [checklines(lines, box) for lines in range(2,int(2*len(alpha)**.5))]
  70.     subsections = min(subsectionVariants, key=lambda x: x[1])[0]
  71.     sines=[sin(box[y0]*deg), sin(box[y1]*deg)]
  72.     for i, s in enumerate(subsections[:-1]):
  73.         sines = sines + [sines[0]+sum(subsections[0:i+1])/len(alpha)*(sines[1]-sines[0])]
  74.     if annotate: print('Chosen subsection scheme:', subsections)
  75.     sines.sort()
  76.     beltborders = [asin(s)/deg for s in sines]
  77.     if annotate: print('Belt borders:', beltborders)
  78.     zoneborders = {}
  79.     zonemap = [[belt, zone]
  80.                for belt, zones in enumerate(subsections)
  81.                for zone in range(zones)]
  82.     for i, c in enumerate(alpha):
  83.         belt, zone = zonemap[i]
  84.         zoneqty = subsections[belt]
  85.         zoneborders[c] = [
  86.                 beltborders[belt],
  87.                 beltborders[belt+1],
  88.                 zone/zoneqty*(box[x1]-box[x0])+box[x0],
  89.                 (zone+1)/zoneqty*(box[x1]-box[x0])+box[x0],
  90.             ]
  91.     if annotate:
  92.         for z in sorted([[z,zoneborders[z]] for z in zoneborders]): print(z)
  93.     return zoneborders
  94.  
  95.  
  96. def metric(size): # Size in degrees
  97.     size = [i*deg*Earth_radius for i in size] # Now in meters
  98.     if max(size) > 1000:
  99.         unit = 'km'
  100.         size = [i/1000 for i in size]
  101.     else:
  102.         unit = 'm'
  103.     if max(size) > 100:
  104.         prec = '0'
  105.     elif max(size) > 10:
  106.         prec = '1'
  107.     else:
  108.         prec = '2'
  109.     return ('{:4.'+prec+'f}x{:4.'+prec+'f} {:2}').format(*size, unit)
  110.  
  111.  
  112. def index_from_coord(lat,lon, show=True):
  113.     print('== Get nested indices for {}, {} =='.format(lat,lon))
  114.     area = [-90,+90,-180,+180]
  115.     code = ''
  116.     while len(code) < full_code_length:
  117.         zones = split(area)
  118.         char = [a for a in alpha if
  119.                 zones[a][y0]<=lat<=zones[a][y1] and
  120.                 zones[a][x0]<=lon<=zones[a][x1]
  121.             ] [0]
  122.         code = code + char
  123.         area = zones[char]
  124.         size = metric([(area[y1]-area[y0]), (area[x1]-area[x0])*cos((area[y1]+area[y0])/2*deg)])
  125.         if show: print(('{:'+str(full_code_length)+'} : {:8.4f}~{:8.4f}, {:9.4f}~{:9.4f} ({})').format(code, *area, size))
  126.     return code
  127.  
  128.  
  129. def area_from_index(sought_code, show=True):
  130.     print('== Find area for the index {} =='.format(sought_code))
  131.     area = [-90,+90,-180,+180]
  132.     code = ''
  133.     while code != sought_code:
  134.         zones = split(area)
  135.         char = sought_code[len(code)]
  136.         code = code + char
  137.         area = zones[char]
  138.         size = metric([(area[y1]-area[y0]), (area[x1]-area[x0])*cos((area[y1]+area[y0])/2*deg)])
  139.         if show: print(('{:'+str(full_code_length)+'} : {:8.4f}~{:8.4f}, {:9.4f}~{:9.4f} ({})').format(code, *area, size))
  140.     if show: print('Center point: {:0.4f}, {:0.4f}'.format((area[y0]+area[y1])/2, (area[x0]+area[x1])/2))
  141.     return area
  142.  
  143.  
  144. if __name__=="__main__":
  145. ##    area_from_index('BHUDH')
  146. ##    area_from_index('HEAVEN')
  147. ##    area_from_index('PARADISE')
  148.     area_from_index('NESKA')
  149.     area_from_index('RUSSIA')
  150.     index_from_coord(45,11)
  151.     index_from_coord(55.95,92.35
Advertisement
Add Comment
Please, Sign In to add comment