def test_single_way(self): "Should create basic cost matrix for a single way" ways = [LineString([(0, 0), (3, 4)])] forward_coefficients = [1] reverse_coefficients = [10] unconnected_coefficient = 100 waypoints, _, waypoint_connections, cost_matrix = process_ways( ways, forward_coefficients, reverse_coefficients, unconnected_coefficient, 10, ) self.assertEqual(waypoints[0], ImmutablePoint(0, 0)) self.assertEqual(waypoints[1], ImmutablePoint(3, 4)) self.assertIsNone(waypoint_connections[0][0]) self.assertEqual(waypoint_connections[0][1], LineString([(0, 0), (3, 4)])) self.assertEqual(waypoint_connections[1][0], LineString([(3, 4), (0, 0)])) self.assertIsNone(waypoint_connections[1][1]) self.assertEqual(cost_matrix[0][0], 0) self.assertEqual(cost_matrix[0][1], 5) self.assertEqual(cost_matrix[1][0], 50) self.assertEqual(cost_matrix[1][1], 0)
def test_two_connected_ways(self): "Should find waypoints at all endpoints of ways and compute simple cost matrix" ways = [LineString([(0, 0), (3, 0)]), LineString([(3, 0), (3, 4)])] forward_coefficients = [1, 1] reverse_coefficients = [1, 1] unconnected_coefficient = 1000 waypoints, _, waypoint_connections, cost_matrix = process_ways( ways, forward_coefficients, reverse_coefficients, unconnected_coefficient, 10, ) expected_waypoints = [ ImmutablePoint(0, 0), ImmutablePoint(3, 0), ImmutablePoint(3, 4), ] self.assertListEqual(waypoints, expected_waypoints) _way_0 = LineString([(3, 0), (0, 0)]) _way_1 = LineString([(3, 4), (3, 0)]) self.assertListEqual( waypoint_connections, [[None, ways[0], None], [_way_0, None, ways[1]], [None, _way_1, None]], ) self.assertListEqual(cost_matrix, [[0, 3, 5000], [3, 0, 4], [5000, 4, 0]])
def test_create_three_waypoints(self): waypoints, retrieve = create_waypoints( [LineString([(0, 0), (3, 4)]), LineString([(3, 4), (5, 6)])] ) p_a, p_b, p_c = ImmutablePoint(0, 0), ImmutablePoint(3, 4), ImmutablePoint(5, 6) self.assertListEqual(waypoints, [p_a, p_b, p_c]) self.assertEqual(retrieve(p_a, p_b), [0]) self.assertEqual(retrieve(p_b, p_c), [1])
def setUp(self): roundabout_features_file = "test_route_processor_roundabout_data.json" self.roundabout_features = load_test_data(roundabout_features_file) self.south_west_point = ImmutablePoint(-0.943355, 50.996674) self.north_east_point = ImmutablePoint(-0.942682, 50.996912) self.roundabout_north = (-0.943146, 50.996985) self.roundabout_east = (-0.942975, 50.996905) self.roundabout_south = (-0.943126, 50.996774) self.roundabout_west = (-0.943253, 50.996801)
def create_route(area, route_type, route_number, show_plot=False): process_route_data_results = process_route_data(area, route_type, route_number) route_features, *route_creator_inputs = process_route_data_results waypoints, waypoint_distances = route_creator_inputs[:2] place_features = download_places(area)["features"] logger.info("downloaded %s place features", len(place_features)) place_names = [ feature.get("properties", {}).get("name") for feature in place_features ] place_points = [ ImmutablePoint(*feature.get("geometry", {}).get("coordinates")) for feature in place_features ] find_closest_place_index = closest_place_index_finder(place_points) route_creator = make_route_creator(*route_creator_inputs) point_a_index, point_b_index = find_furthest_waypoints(waypoint_distances) route_a_to_b = route_creator(point_a_index, point_b_index) route_b_to_a = route_creator(point_b_index, point_a_index) waypoint_a = waypoints[point_a_index] waypoint_b = waypoints[point_b_index] place_name_a = place_names[find_closest_place_index(waypoint_a)] place_name_b = place_names[find_closest_place_index(waypoint_b)] base_name = "{} {} {}".format(abbreviate_area(area), route_type, route_number) route_a_to_b_name = "{} {} to {}".format(base_name, place_name_a, place_name_b) route_b_to_a_name = "{} {} to {}".format(base_name, place_name_b, place_name_a) if show_plot: plot_routes( route_features, [(route_a_to_b_name, route_a_to_b), (route_b_to_a_name, route_b_to_a)], ) logger.info("export gpx files for both directions") export_gpx_route(route_a_to_b, route_a_to_b_name) export_gpx_route(route_b_to_a, route_b_to_a_name) logger.info("route creation complete")
def test_single_index_storage(self): store, retrieve = waypoint_connection_storage() point_a_1 = ImmutablePoint(0, 0) point_a_2 = ImmutablePoint(0, 0) point_b_1 = ImmutablePoint(1, 1) point_b_2 = ImmutablePoint(1, 1) store(point_a_1, point_b_1, 1) store(point_a_2, point_b_2, 2) connections = retrieve(ImmutablePoint(0, 0), ImmutablePoint(1, 1)) self.assertListEqual(connections, [1, 2])
def get_line_endpoints(line: LineString) -> ImmutablePoint: return (ImmutablePoint(*line.coords[0]), ImmutablePoint(*line.coords[-1]))
def test_create_two_waypoints(self): waypoints, retrieve = create_waypoints([LineString([(0, 0), (3, 4)])]) p_a, p_b = ImmutablePoint(0, 0), ImmutablePoint(3, 4) self.assertListEqual(waypoints, [p_a, p_b]) self.assertEqual(retrieve(p_a, p_b), [0])
def test_require_constructor_arguments(self): with self.assertRaises(TypeError): ImmutablePoint() # pylint: disable=no-value-for-parameter
def test_distance_method_correct(self): point_a = ImmutablePoint(0, 0) point_b = ImmutablePoint(3, 4) distance = point_a.distance(point_b) self.assertEqual(distance, 5)
def test_hash_same_when_same_coords(self): point_a_1 = ImmutablePoint(2, 2) point_a_2 = ImmutablePoint(2, 2) self.assertEqual(hash(point_a_1), hash(point_a_2))
def test_prevent_coord_change(self): point = ImmutablePoint(1, 1) with self.assertRaises(AttributeError): point.x = 2 self.assertEqual(point.x, 1)
def load_waypoints(filename: str): return [ ImmutablePoint(*point["coordinates"]) for point in load_json(filename) ]
def find_closest_place_index(search_point: ImmutablePoint): return min(place_indexes, key=lambda i: search_point.distance(place_points[i]))