DuquesnoyPaul
commited on
Commit
·
8062743
1
Parent(s):
dad800b
PDL : get minutes from distance implementation and tests / euclidian distance to km
Browse files
app/travel_resolver/libs/pathfinder/heuristic.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import math
|
|
|
|
| 2 |
|
| 3 |
-
def euclidean_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
| 4 |
"""
|
| 5 |
Calculate the Euclidean distance between two points given by their latitudes and longitudes.
|
| 6 |
The coordinates are in degrees.
|
|
@@ -11,7 +12,7 @@ def euclidean_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
|
| 11 |
lon2 (float): Longitude of the first point.
|
| 12 |
|
| 13 |
Returns:
|
| 14 |
-
(float): The Euclidean distance (
|
| 15 |
"""
|
| 16 |
# Conversion des degrés en radians
|
| 17 |
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
|
@@ -24,9 +25,9 @@ def euclidean_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
|
| 24 |
# Distance euclidienne (approximation plane)
|
| 25 |
distance = math.sqrt(delta_lat**2 + delta_lon**2)
|
| 26 |
|
| 27 |
-
return distance
|
| 28 |
|
| 29 |
-
def haversine_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
| 30 |
"""
|
| 31 |
Calculates the distance as the crow flies between two points on the Earth
|
| 32 |
(coordinates specified in degrees) using the Haversine formula.
|
|
@@ -39,9 +40,6 @@ def haversine_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
|
| 39 |
Returns:
|
| 40 |
(float): The distance as the crow flies (kilometers) between the two points.
|
| 41 |
"""
|
| 42 |
-
# Rayon de la Terre en kilomètres
|
| 43 |
-
R = 6371.0
|
| 44 |
-
|
| 45 |
# Conversion des degrés en radians
|
| 46 |
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
| 47 |
lat2, lon2 = math.radians(lat2), math.radians(lon2)
|
|
@@ -55,6 +53,22 @@ def haversine_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
|
| 55 |
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
| 56 |
|
| 57 |
# Distance à vol d'oiseau
|
| 58 |
-
distance =
|
| 59 |
|
| 60 |
return distance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import math
|
| 2 |
+
import travel_resolver.libs.pathfinder.variables as var
|
| 3 |
|
| 4 |
+
def euclidean_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float) -> float:
|
| 5 |
"""
|
| 6 |
Calculate the Euclidean distance between two points given by their latitudes and longitudes.
|
| 7 |
The coordinates are in degrees.
|
|
|
|
| 12 |
lon2 (float): Longitude of the first point.
|
| 13 |
|
| 14 |
Returns:
|
| 15 |
+
(float): The Euclidean distance (kilometers) between the two points.
|
| 16 |
"""
|
| 17 |
# Conversion des degrés en radians
|
| 18 |
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
|
|
|
| 25 |
# Distance euclidienne (approximation plane)
|
| 26 |
distance = math.sqrt(delta_lat**2 + delta_lon**2)
|
| 27 |
|
| 28 |
+
return distance*var.EARTH_RADIUS
|
| 29 |
|
| 30 |
+
def haversine_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float) -> float:
|
| 31 |
"""
|
| 32 |
Calculates the distance as the crow flies between two points on the Earth
|
| 33 |
(coordinates specified in degrees) using the Haversine formula.
|
|
|
|
| 40 |
Returns:
|
| 41 |
(float): The distance as the crow flies (kilometers) between the two points.
|
| 42 |
"""
|
|
|
|
|
|
|
|
|
|
| 43 |
# Conversion des degrés en radians
|
| 44 |
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
| 45 |
lat2, lon2 = math.radians(lat2), math.radians(lon2)
|
|
|
|
| 53 |
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
| 54 |
|
| 55 |
# Distance à vol d'oiseau
|
| 56 |
+
distance = var.EARTH_RADIUS * c
|
| 57 |
|
| 58 |
return distance
|
| 59 |
+
|
| 60 |
+
def get_minutes_from_distance(distance : float, needConversion : bool) -> float:
|
| 61 |
+
"""
|
| 62 |
+
Get minutes estimation from heuristic distance computed by in kilometers or radians
|
| 63 |
+
Args:
|
| 64 |
+
distance (float): The converted distance.
|
| 65 |
+
needConversion (bool): Determine if conversion is needed.
|
| 66 |
+
If true, this distance is in kilometers.
|
| 67 |
+
Else, it is in radians.
|
| 68 |
+
|
| 69 |
+
Returns:
|
| 70 |
+
(float): The approximated minutes needed to travel the given distance.
|
| 71 |
+
"""
|
| 72 |
+
speed : float = var.AVERAGE_KM_H_TRAIN_SPEED if needConversion else var.AVERAGE_RAD_MIN_TRAIN_SPEED
|
| 73 |
+
conversionRatio : float = 60 if needConversion else 1
|
| 74 |
+
return (distance/speed)*conversionRatio
|
app/travel_resolver/libs/pathfinder/variables.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
AVERAGE_KM_H_TRAIN_SPEED = 100
|
| 2 |
+
AVERAGE_RAD_MIN_TRAIN_SPEED = 0.000261
|
| 3 |
+
EARTH_RADIUS = 6371
|
app/travel_resolver/tests/heuristic_test.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
import unittest
|
| 2 |
-
from travel_resolver.libs.pathfinder.heuristic import euclidean_distance
|
| 3 |
|
| 4 |
class TestHeuristic(unittest.TestCase):
|
| 5 |
|
|
@@ -7,15 +7,27 @@ class TestHeuristic(unittest.TestCase):
|
|
| 7 |
self.latParis, self.lonParis = 48.8566, 2.3522
|
| 8 |
self.latLyon, self.lonLyon = 45.7640, 4.8357
|
| 9 |
|
| 10 |
-
def
|
| 11 |
-
expected_distance =
|
| 12 |
distance = euclidean_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 13 |
self.assertEqual(distance, expected_distance)
|
| 14 |
|
| 15 |
-
def
|
| 16 |
expected_distance = 391.4989316742569
|
| 17 |
distance = haversine_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 18 |
self.assertEqual(distance, expected_distance)
|
| 19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
if __name__ == '__main__':
|
| 21 |
unittest.main()
|
|
|
|
| 1 |
import unittest
|
| 2 |
+
from travel_resolver.libs.pathfinder.heuristic import haversine_distance,get_minutes_from_distance,euclidean_distance
|
| 3 |
|
| 4 |
class TestHeuristic(unittest.TestCase):
|
| 5 |
|
|
|
|
| 7 |
self.latParis, self.lonParis = 48.8566, 2.3522
|
| 8 |
self.latLyon, self.lonLyon = 45.7640, 4.8357
|
| 9 |
|
| 10 |
+
def test_euclidean_distance(self):
|
| 11 |
+
expected_distance = 441.0382031754888
|
| 12 |
distance = euclidean_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 13 |
self.assertEqual(distance, expected_distance)
|
| 14 |
|
| 15 |
+
def test_haversine_distance(self):
|
| 16 |
expected_distance = 391.4989316742569
|
| 17 |
distance = haversine_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 18 |
self.assertEqual(distance, expected_distance)
|
| 19 |
|
| 20 |
+
def test_get_minutes_from_distance(self):
|
| 21 |
+
expected_time_euclidean = 264.62292190529325
|
| 22 |
+
euclidean_dist = euclidean_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 23 |
+
time_from_euclidean_distance = get_minutes_from_distance(euclidean_dist,True)
|
| 24 |
+
|
| 25 |
+
expected_time_haversine = 234.89935900455413
|
| 26 |
+
haversine_dist = haversine_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 27 |
+
time_from_haversine_distance = get_minutes_from_distance(haversine_dist,True)
|
| 28 |
+
|
| 29 |
+
self.assertEqual(time_from_euclidean_distance, expected_time_euclidean)
|
| 30 |
+
self.assertEqual(time_from_haversine_distance, expected_time_haversine)
|
| 31 |
+
|
| 32 |
if __name__ == '__main__':
|
| 33 |
unittest.main()
|