| 1 | #!/usr/bin/python
|
|---|
| 2 |
|
|---|
| 3 | def to_dms(angle):
|
|---|
| 4 | m = 60 * (angle % 1)
|
|---|
| 5 | s = 60 * (m % 1)
|
|---|
| 6 | return (int(angle), int(m), s)
|
|---|
| 7 |
|
|---|
| 8 | def encode(lat, long):
|
|---|
| 9 | if lat < -90 or lat > 90:
|
|---|
| 10 | raise ValueError("latitude out of range")
|
|---|
| 11 | if lat == -90:
|
|---|
| 12 | # South Pole special case.
|
|---|
| 13 | return b''
|
|---|
| 14 | if lat == 90:
|
|---|
| 15 | # North Pole special case.
|
|---|
| 16 | return b'\xff\xff'
|
|---|
| 17 | # Wrap longitude to range [0,360).
|
|---|
| 18 | while long >= 360:
|
|---|
| 19 | long -= 360
|
|---|
| 20 | while long < 0:
|
|---|
| 21 | long += 360
|
|---|
| 22 | lat = to_dms(lat + 90)
|
|---|
| 23 | long = to_dms(long)
|
|---|
| 24 | result = bytearray()
|
|---|
| 25 | dd = lat[0] * 360 + long[0]
|
|---|
| 26 | result.append(dd >> 8)
|
|---|
| 27 | result.append(dd & 255)
|
|---|
| 28 | m1 = (lat[1] // 4) << 4 | (long[1] // 4)
|
|---|
| 29 | result.append(m1)
|
|---|
| 30 | ms = (lat[1] % 4) << 6 | (long[1] % 4) << 4
|
|---|
| 31 | ms |= int(lat[2] // 15) << 2 | int(long[2] // 15)
|
|---|
| 32 | result.append(ms)
|
|---|
| 33 | s2 = int(lat[2] % 15) << 4 | int(long[2] % 15)
|
|---|
| 34 | result.append(s2)
|
|---|
| 35 | s3 = (int(lat[2] / 15) & 0x0f) << 4 | (int(long[2] / 15) & 0x0f);
|
|---|
| 36 | result.append(s3)
|
|---|
| 37 |
|
|---|
| 38 | # Remove trailing zeros.
|
|---|
| 39 | while len(result) and result[-1] == 0:
|
|---|
| 40 | result.pop()
|
|---|
| 41 | return result
|
|---|
| 42 |
|
|---|
| 43 | def decode(value):
|
|---|
| 44 | if len(value) == 0:
|
|---|
| 45 | return (-90.0, 0.0)
|
|---|
| 46 | if value == b'\xff\xff':
|
|---|
| 47 | return (90.0, 0.0)
|
|---|
| 48 | if len(value) == 1:
|
|---|
| 49 | dd = 0
|
|---|
| 50 | else:
|
|---|
| 51 | dd = value[1]
|
|---|
| 52 | dd |= (value[0] << 8)
|
|---|
| 53 | lat = dd // 360;
|
|---|
| 54 | long = dd % 360;
|
|---|
| 55 | if len(value) > 2:
|
|---|
| 56 | m1 = value[2]
|
|---|
| 57 | lat_m = (m1 >> 4) * 4
|
|---|
| 58 | long_m = (m1 & 15) * 4
|
|---|
| 59 | if len(value) > 3:
|
|---|
| 60 | ms = value[3]
|
|---|
| 61 | lat_m += ms >> 6
|
|---|
| 62 | long_m += (ms >> 4) & 3
|
|---|
| 63 | lat_s = ((ms >> 2) & 3) * 15
|
|---|
| 64 | long_s = (ms & 3) * 15
|
|---|
| 65 | if len(value) > 4:
|
|---|
| 66 | s2 = value[4]
|
|---|
| 67 | lat_s += s2 >> 4
|
|---|
| 68 | long_s += s2 & 15
|
|---|
| 69 | if len(value) > 5:
|
|---|
| 70 | s3 = value[5]
|
|---|
| 71 | lat_s += ((s3 >> 4) + 0.5) / 16.0
|
|---|
| 72 | long_s += ((s3 & 15) + 0.5) / 16.0
|
|---|
| 73 | else:
|
|---|
| 74 | lat_s += 0.5
|
|---|
| 75 | long_s += 0.5
|
|---|
| 76 | else:
|
|---|
| 77 | lat_s += 7.5
|
|---|
| 78 | long_s += 7.5
|
|---|
| 79 | lat_m += lat_s / 60.0
|
|---|
| 80 | long_m += long_s / 60.0
|
|---|
| 81 | else:
|
|---|
| 82 | lat_m += 2
|
|---|
| 83 | long_m += 2
|
|---|
| 84 | lat += lat_m / 60.0
|
|---|
| 85 | long += long_m / 60.0
|
|---|
| 86 | else:
|
|---|
| 87 | lat += 0.5
|
|---|
| 88 | long += 0.5
|
|---|
| 89 | return (lat - 90, long)
|
|---|