111 lines
2.8 KiB
Python
Executable file
111 lines
2.8 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
import overpy
|
|
import numpy as np
|
|
import pandas as pd
|
|
import geopy.distance as distance
|
|
|
|
from tqdm import tqdm
|
|
|
|
# brandname : overpass query filters
|
|
BRANDS: dict[str, str] = {
|
|
"greggs": "[\"brand:wikidata\"=\"Q3403981\"]",
|
|
}
|
|
|
|
EncodedLocation = list[tuple[float, list[float]]]
|
|
|
|
|
|
def fetch_data(brand: str) -> list[tuple[float | None, float | None]]:
|
|
"""Fetch a list of locations from OSM."""
|
|
api = overpy.Overpass()
|
|
|
|
filters = BRANDS[brand]
|
|
query = api.query(f"nwr{filters}; out center;")
|
|
|
|
result = []
|
|
|
|
for way in query.ways:
|
|
result.append((way.center_lat, way.center_lon))
|
|
|
|
for node in query.nodes:
|
|
result.append((node.lat, node.lon))
|
|
|
|
for (lat, lon) in result:
|
|
if (lat is None) or (lon is None):
|
|
raise ValueError("Item missing coords!")
|
|
|
|
return result
|
|
|
|
|
|
def encode(location: tuple[float, float]) -> EncodedLocation:
|
|
"""Encode a location."""
|
|
|
|
print("fetching")
|
|
greggs = fetch_data("greggs")
|
|
print("fetched")
|
|
#greggs = [(55.85,-4.02),(52.443,-1.833),(51.28,-1.0)]
|
|
|
|
#relative distance matrix
|
|
dist_matrix = np.zeros((len(greggs),len(greggs)))
|
|
for i in tqdm(range(len(greggs))):
|
|
first=greggs[i]
|
|
for j in range(len(greggs)):
|
|
second=greggs[j]
|
|
#calculate the distance between i and j coordinates
|
|
#dist_matrix[i,j] = np.sqrt((first[0]-second[0])**2 + (first[1]-second[1])**2 )
|
|
dist_matrix[i,j] = distance.distance(distance.lonlat(*first), distance.lonlat(*second)).km*1000
|
|
print(dist_matrix)
|
|
|
|
#find closest greggs
|
|
distances = pd.Series(np.zeros(len(greggs)))
|
|
for i in range(len(greggs)):
|
|
current = greggs[i]
|
|
#distances[i] = np.sqrt((current[0]-location[0])**2 + (current[1]-location[1])**2
|
|
distances[i] = distance.distance(distance.lonlat(*current), distance.lonlat(*location)).km*1000
|
|
|
|
print(distances)
|
|
distances = distances.sort_values()
|
|
top3 = distances.head(3)
|
|
print(top3)
|
|
|
|
|
|
# Stub
|
|
return [
|
|
(5., [1., 2., 3.]),
|
|
(6., [4., 5., 6.]),
|
|
]
|
|
|
|
|
|
def decode(location: EncodedLocation) -> tuple[float, float]:
|
|
"""Decode into a location."""
|
|
|
|
# Stub
|
|
return (0.091659, 52.210796)
|
|
|
|
|
|
def format_location(location: EncodedLocation) -> str:
|
|
"""Format an encoded location as a string."""
|
|
return ";".join([f"{a}:{','.join(map(str, b))}" for (a, b) in location])
|
|
|
|
|
|
def parse_location(location: str) -> EncodedLocation:
|
|
"""Parse a location string into an EncodedLocation."""
|
|
|
|
# Stub
|
|
return [
|
|
(5., [1., 2., 3.]),
|
|
(6., [4., 5., 6.]),
|
|
]
|
|
|
|
|
|
def main():
|
|
"""Testing."""
|
|
print("Running query...")
|
|
#greggs = fetch_data("greggs")
|
|
#print(f"Query done - got {len(greggs)} Greggs!")
|
|
|
|
print(format_location(encode((0.091659, 52.210796))))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|