From 40edd923c3836f34c94de25f47b45940e71c0338 Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Wed, 9 Oct 2024 16:12:41 +0200 Subject: [PATCH] remove geopy dependency --- backend/Pipfile | 1 - backend/src/persistence.py | 8 +++---- backend/src/structs/landmark.py | 10 ++++---- backend/src/utils/get_time_separation.py | 29 +++++++++++++++++------- backend/src/utils/optimizer.py | 1 - 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/backend/Pipfile b/backend/Pipfile index 1ca056b..64002cc 100644 --- a/backend/Pipfile +++ b/backend/Pipfile @@ -9,7 +9,6 @@ name = "pypi" numpy = "*" fastapi = "*" pydantic = "*" -geopy = "*" shapely = "*" scipy = "*" osmpythontools = "*" diff --git a/backend/src/persistence.py b/backend/src/persistence.py index 033c028..390e95d 100644 --- a/backend/src/persistence.py +++ b/backend/src/persistence.py @@ -21,8 +21,8 @@ if constants.MEMCACHED_HOST_PATH is None: else: client = Client( constants.MEMCACHED_HOST_PATH, - timeout=1, - allow_unicode_keys=True, - encoding='utf-8', - serde=serde.pickle_serde + timeout = 1, + allow_unicode_keys = True, + encoding = 'utf-8', + serde = serde.pickle_serde ) diff --git a/backend/src/structs/landmark.py b/backend/src/structs/landmark.py index 12c4634..9b93195 100644 --- a/backend/src/structs/landmark.py +++ b/backend/src/structs/landmark.py @@ -5,7 +5,7 @@ from uuid import uuid4 # Output to frontend class Landmark(BaseModel) : - + # Properties of the landmark name : str type: Literal['sightseeing', 'nature', 'shopping', 'start', 'finish'] @@ -22,22 +22,22 @@ class Landmark(BaseModel) : # Unique ID of a given landmark uuid: str = Field(default_factory=uuid4) - + # Additional properties depending on specific tour must_do : Optional[bool] = False must_avoid : Optional[bool] = False is_secondary : Optional[bool] = False # TODO future - + time_to_reach_next : Optional[int] = 0 next_uuid : Optional[str] = None - + def __str__(self) -> str: 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 "" type_str = '(' + self.type + ')' 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}]' - + def distance(self, value: 'Landmark') -> float: return (self.location[0] - value.location[0])**2 + (self.location[1] - value.location[1])**2 diff --git a/backend/src/utils/get_time_separation.py b/backend/src/utils/get_time_separation.py index e482e8d..a1b7f83 100644 --- a/backend/src/utils/get_time_separation.py +++ b/backend/src/utils/get_time_separation.py @@ -1,5 +1,5 @@ import yaml -from geopy.distance import geodesic +from math import sin, cos, sqrt, atan2, radians import constants @@ -8,6 +8,7 @@ with constants.OPTIMIZER_PARAMETERS_PATH.open('r') as f: DETOUR_FACTOR = parameters['detour_factor'] AVERAGE_WALKING_SPEED = parameters['average_walking_speed'] +EARTH_RADIUS_KM = 6373 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 - else: - dist = geodesic(p1, p2).kilometers + else: + # 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) - walk_dist = dist*DETOUR_FACTOR + dlon = lon2 - lon1 + 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) - walk_time = walk_dist/AVERAGE_WALKING_SPEED*60 + walk_time = walk_distance / AVERAGE_WALKING_SPEED * 60 return round(walk_time) diff --git a/backend/src/utils/optimizer.py b/backend/src/utils/optimizer.py index 933bd28..93ea448 100644 --- a/backend/src/utils/optimizer.py +++ b/backend/src/utils/optimizer.py @@ -3,7 +3,6 @@ import numpy as np from scipy.optimize import linprog from collections import defaultdict, deque -from geopy.distance import geodesic from structs.landmark import Landmark from .get_time_separation import get_time