|
| 1 | +import numpy as np |
| 2 | +from math import sin, cos, sqrt, atan2, radians |
| 3 | + |
| 4 | + |
| 5 | +class GeographicalPositionTest: |
| 6 | + def __init__(self, file_name): |
| 7 | + self.file_name = file_name |
| 8 | + |
| 9 | + def build_dist_matrix(self, cities_names, cities_coordinates): |
| 10 | + """ |
| 11 | + This function creates a matrix containing pair distance among all cities in kilometers. Distance between each |
| 12 | + city by itself is equal to zero. |
| 13 | + """ |
| 14 | + num_cities = len(cities_names) |
| 15 | + distance_matrix = np.zeros([num_cities, num_cities]) |
| 16 | + for city_departure in cities_names: |
| 17 | + for city_arrival in cities_names: |
| 18 | + i = cities_names.index(city_departure) |
| 19 | + j = cities_names.index(city_arrival) |
| 20 | + co_i = cities_coordinates[city_departure] |
| 21 | + co_j = cities_coordinates[city_arrival] |
| 22 | + distance_matrix[i][j] = self.calculate_pair_dist(co_i, co_j) |
| 23 | + return distance_matrix |
| 24 | + |
| 25 | + def open_file(self): |
| 26 | + city_names = [] |
| 27 | + cities_coordinates = {} |
| 28 | + with open(self.file_name, "r") as file_stream: |
| 29 | + num_line = 0 |
| 30 | + for line in file_stream: |
| 31 | + num_line += 1 |
| 32 | + current_line = line.split(",") |
| 33 | + if self.is_valid(current_line): |
| 34 | + city_name = current_line[0] |
| 35 | + city_latitude = float( |
| 36 | + "{0:.2f}".format(float(current_line[1]) + float(current_line[2]) / 60)) |
| 37 | + city_longitude = float( |
| 38 | + "{0:.2f}".format(float(current_line[3]) + float(current_line[4]) / 60)) |
| 39 | + |
| 40 | + cities_coordinates[city_name] = [city_latitude, city_longitude] |
| 41 | + city_names.append(city_name) |
| 42 | + else: |
| 43 | + print('This line', num_line, 'does not pass our test.') |
| 44 | + |
| 45 | + num_cities = len(city_names) |
| 46 | + |
| 47 | + return cities_coordinates, city_names, num_cities |
| 48 | + |
| 49 | + @staticmethod |
| 50 | + def calculate_pair_dist(coordinates_1, coordinates_2): |
| 51 | + """ |
| 52 | + This function calculates distance between two cities in kilometers given geographical coordinates of two cities. |
| 53 | + """ |
| 54 | + latitude_first, longitude_first = coordinates_1 |
| 55 | + latitude_second, longitude_second = coordinates_2 |
| 56 | + |
| 57 | + r = 6373.0 |
| 58 | + a = (sin(radians(latitude_second - latitude_first) / 2)) ** 2 + \ |
| 59 | + cos(radians(latitude_first)) * cos(radians(latitude_second)) * \ |
| 60 | + (sin(radians(longitude_second - longitude_first) / 2)) ** 2 |
| 61 | + c = 2 * atan2(sqrt(a), sqrt(1 - a)) |
| 62 | + distance_kilometer = float("{0:.2f}".format(r * c)) |
| 63 | + |
| 64 | + return distance_kilometer |
| 65 | + |
| 66 | + @staticmethod |
| 67 | + def is_valid(line): |
| 68 | + """ |
| 69 | + This boolean function check each line in the imported file to have exact 5 components. Moreover, it checks |
| 70 | + whether latitude and longitude degrees are between -180 and 180, and its corresponding minutes are between |
| 71 | + 0 and 60. |
| 72 | + """ |
| 73 | + if len(line) == 5: |
| 74 | + latitude_degree = float(line[1]) |
| 75 | + latitude_minute = float(line[2]) |
| 76 | + longitude_degree = float(line[3]) |
| 77 | + longitude_minute = float(line[4]) |
| 78 | + |
| 79 | + if -180 <= latitude_degree <= 180 and 0 <= latitude_minute <= 60 and \ |
| 80 | + -180 <= longitude_degree <= 180 and 0 <= longitude_minute <= 60: |
| 81 | + return True |
| 82 | + else: |
| 83 | + return False |
0 commit comments