Better landmark finding #27
| @@ -9,7 +9,6 @@ name = "pypi" | |||||||
| numpy = "*" | numpy = "*" | ||||||
| fastapi = "*" | fastapi = "*" | ||||||
| pydantic = "*" | pydantic = "*" | ||||||
| geopy = "*" |  | ||||||
| shapely = "*" | shapely = "*" | ||||||
| scipy = "*" | scipy = "*" | ||||||
| osmpythontools = "*" | osmpythontools = "*" | ||||||
|   | |||||||
| @@ -21,8 +21,8 @@ if constants.MEMCACHED_HOST_PATH is None: | |||||||
| else: | else: | ||||||
|     client = Client( |     client = Client( | ||||||
|         constants.MEMCACHED_HOST_PATH, |         constants.MEMCACHED_HOST_PATH, | ||||||
|         timeout=1, |         timeout = 1, | ||||||
|         allow_unicode_keys=True, |         allow_unicode_keys = True, | ||||||
|         encoding='utf-8', |         encoding = 'utf-8', | ||||||
|         serde=serde.pickle_serde |         serde = serde.pickle_serde | ||||||
|     ) |     ) | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ from uuid import uuid4 | |||||||
|  |  | ||||||
| # Output to frontend | # Output to frontend | ||||||
| class Landmark(BaseModel) : | class Landmark(BaseModel) : | ||||||
|      |  | ||||||
|     # Properties of the landmark |     # Properties of the landmark | ||||||
|     name : str |     name : str | ||||||
|     type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] |     type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] | ||||||
| @@ -22,22 +22,22 @@ class Landmark(BaseModel) : | |||||||
|  |  | ||||||
|     # Unique ID of a given landmark |     # Unique ID of a given landmark | ||||||
|     uuid: str = Field(default_factory=uuid4) |     uuid: str = Field(default_factory=uuid4) | ||||||
|      |  | ||||||
|     # Additional properties depending on specific tour |     # Additional properties depending on specific tour | ||||||
|     must_do : Optional[bool] = False |     must_do : Optional[bool] = False | ||||||
|     must_avoid : Optional[bool] = False |     must_avoid : Optional[bool] = False | ||||||
|     is_secondary : Optional[bool] = False                       # TODO future    |     is_secondary : Optional[bool] = False                       # TODO future    | ||||||
|      |  | ||||||
|     time_to_reach_next : Optional[int] = 0 |     time_to_reach_next : Optional[int] = 0 | ||||||
|     next_uuid : Optional[str] = None |     next_uuid : Optional[str] = None | ||||||
|      |  | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|         time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" |         time_to_next_str = f", time_to_next={self.time_to_reach_next}" if self.time_to_reach_next else "" | ||||||
|         is_secondary_str = f", secondary" if self.is_secondary else "" |         is_secondary_str = f", secondary" if self.is_secondary else "" | ||||||
|         type_str = '(' + self.type + ')' |         type_str = '(' + self.type + ')' | ||||||
|         if self.type in ["start", "finish", "nature", "shopping"] : type_str += '\t ' |         if self.type in ["start", "finish", "nature", "shopping"] : type_str += '\t ' | ||||||
|         return f'Landmark{type_str}: [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}{is_secondary_str}]' |         return f'Landmark{type_str}: [{self.name} @{self.location}, score={self.attractiveness}{time_to_next_str}{is_secondary_str}]' | ||||||
|      |  | ||||||
|     def distance(self, value: 'Landmark') -> float: |     def distance(self, value: 'Landmark') -> float: | ||||||
|         return (self.location[0] - value.location[0])**2 + (self.location[1] - value.location[1])**2 |         return (self.location[0] - value.location[0])**2 + (self.location[1] - value.location[1])**2 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import yaml | import yaml | ||||||
| from geopy.distance import geodesic | from math import sin, cos, sqrt, atan2, radians | ||||||
|  |  | ||||||
| import constants | import constants | ||||||
|  |  | ||||||
| @@ -8,6 +8,7 @@ with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: | |||||||
|     DETOUR_FACTOR = parameters['detour_factor'] |     DETOUR_FACTOR = parameters['detour_factor'] | ||||||
|     AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] |     AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] | ||||||
|  |  | ||||||
|  | EARTH_RADIUS_KM = 6373 | ||||||
|  |  | ||||||
| def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | ||||||
|     """ |     """ | ||||||
| @@ -22,16 +23,28 @@ def get_time(p1: tuple[float, float], p2: tuple[float, float]) -> int: | |||||||
|     """ |     """ | ||||||
|  |  | ||||||
|  |  | ||||||
|     # Compute the straight-line distance in km |     if p1 == p2: | ||||||
|     if p1 == p2 : |  | ||||||
|         return 0 |         return 0 | ||||||
|     else:  |     else: | ||||||
|         dist = geodesic(p1, p2).kilometers |         # Compute the distance in km along the surface of the Earth | ||||||
|  |         # (assume spherical Earth) | ||||||
|  |         # this is the haversine formula, stolen from stackoverflow | ||||||
|  |         # in order to not use any external libraries | ||||||
|  |         lat1, lon1 = radians(p1[0]), radians(p1[1]) | ||||||
|  |         lat2, lon2 = radians(p2[0]), radians(p2[1]) | ||||||
|  |  | ||||||
|     # Consider the detour factor for average cityto deterline walking distance (in km) |         dlon = lon2 - lon1 | ||||||
|     walk_dist = dist*DETOUR_FACTOR |         dlat = lat2 - lat1 | ||||||
|  |  | ||||||
|  |         a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 | ||||||
|  |         c = 2 * atan2(sqrt(a), sqrt(1 - a)) | ||||||
|  |  | ||||||
|  |         distance = EARTH_RADIUS_KM * c | ||||||
|  |  | ||||||
|  |     # Consider the detour factor for average an average city | ||||||
|  |     walk_distance = distance * DETOUR_FACTOR | ||||||
|  |  | ||||||
|     # Time to walk this distance (in minutes) |     # Time to walk this distance (in minutes) | ||||||
|     walk_time = walk_dist/AVERAGE_WALKING_SPEED*60 |     walk_time = walk_distance / AVERAGE_WALKING_SPEED * 60 | ||||||
|  |  | ||||||
|     return round(walk_time) |     return round(walk_time) | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import numpy as np | |||||||
|  |  | ||||||
| from scipy.optimize import linprog | from scipy.optimize import linprog | ||||||
| from collections import defaultdict, deque | from collections import defaultdict, deque | ||||||
| from geopy.distance import geodesic |  | ||||||
|  |  | ||||||
| from structs.landmark import Landmark | from structs.landmark import Landmark | ||||||
| from .get_time_separation import get_time | from .get_time_separation import get_time | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user