123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import datetime as dt
- import json
- import math
- import os
- import pytz
- import subprocess
- import sys
- import yaml
- def to_iso6801_basic(ts):
- return ts.isoformat().replace(':', '').replace('-', '') \
- .replace('+0000', 'Z')
- class Location:
- EARTH_RADIUS_METRES = 6.371e6
- def __init__(self, latitude, longitude, altitude):
- self.latitude = latitude
- self.longitude = longitude
- self.altitude = altitude
- @property
- def latitude_radian(self):
- return math.radians(self.latitude)
- @property
- def longitude_radian(self):
- return math.radians(self.longitude)
- @staticmethod
- def haversine(angle_rad):
- # http://mathworld.wolfram.com/Haversine.html
- return math.sin(angle_rad / 2) ** 2
- @staticmethod
- def haversine_inv(hav):
- # return math.atan2(math.sqrt(hav), math.sqrt(1-hav)) * 2
- return math.asin(math.sqrt(hav)) * 2
- @staticmethod
- def haversine_distance_metres(a, b):
- # https://en.wikipedia.org/wiki/Haversine_formula
- hav = Location.haversine(b.latitude_radian - a.latitude_radian) \
- + math.cos(a.latitude_radian) * math.cos(b.latitude_radian) \
- * Location.haversine(b.longitude_radian - a.longitude_radian)
- return Location.haversine_inv(hav) * Location.EARTH_RADIUS_METRES
- class Position(Location):
- def __init__(self, timestamp, latitude, longitude, altitude):
- self.timestamp = timestamp
- super().__init__(
- latitude=latitude,
- longitude=longitude,
- altitude=altitude,
- )
- @classmethod
- def from_termux_location(cls, provider='network'):
- loc_json = subprocess.check_output(['termux-location', '-p', provider]) \
- .decode(sys.stdout.encoding)
- req_ts = dt.datetime.now(pytz.utc)
- loc_attr = yaml.load(loc_json)
- if not loc_attr:
- return None
- else:
- return cls(
- timestamp=req_ts -
- dt.timedelta(milliseconds=loc_attr['elapsedMs']),
- latitude=loc_attr['latitude'],
- longitude=loc_attr['longitude'],
- altitude=loc_attr['altitude'],
- )
- @classmethod
- def load_yaml(cls, path):
- name = os.path.basename(path)
- assert name.endswith('Z.yml'), path
- ts = pytz.utc.localize(dt.datetime.strptime(
- name[:-5],
- '%Y%m%dT%H%M%S.%f',
- ))
- with open(path, 'r') as f:
- attr = yaml.load(f.read())
- return cls(
- timestamp=ts,
- latitude=attr['lat'],
- longitude=attr['lon'],
- altitude=attr['alt'],
- )
- def save_yaml(self, target_dir_path):
- path = os.path.join(
- target_dir_path,
- '{}.yml'.format(to_iso6801_basic(self.timestamp)),
- )
- attr = {
- 'lat': self.latitude,
- 'lon': self.longitude,
- 'alt': self.altitude,
- }
- with open(path, 'w') as f:
- f.write(yaml.dump(attr, default_flow_style=False))
- return path
|