Spaces:
Sleeping
Sleeping
File size: 6,334 Bytes
5ecd199 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
import streamlit as st
import googlemaps
from polyline import decode
import os
# from dotenv import load_dotenv
from bs4 import BeautifulSoup # To clean HTML tags
import json
# load_dotenv()
API_KEY = 'AIzaSyBvsVrsscV50q6bVV7ofEm2tzCz08F1k1A'
gmaps = googlemaps.Client(key=API_KEY)
# Define avoided segments globally
avoid_list = [
[(24.7970264, 46.719939), (24.7388275, 46.59441409999999)],
[(24.954535, 47.0142416), (24.7258606, 46.583506)],
[(24.796827, 46.5643251), (24.7089077, 46.6195443)],
[(24.9229714, 46.7204701), (24.796827, 46.5643251)],
[(24.796827, 46.5643251), (24.6575642, 46.5630617)],
[(24.7575596, 46.6895021), (24.70444, 46.6237931)],
]
# Fetch directions from Google Maps API
def get_directions(start, end, alternatives=False):
directions_result = gmaps.directions(start, end, mode="driving", alternatives=alternatives)
if directions_result:
return directions_result
return None
# Decode a Google Maps encoded polyline to latitude and longitude points
def decode_polyline_to_points(polyline):
return decode(polyline)
# Check if two routes intersect based on their polylines
def do_routes_intersect(route_a_steps, route_b_steps):
# Loop through steps of both routes
for step_a in route_a_steps:
for step_b in route_b_steps:
if step_a == step_b:
road_name_a = get_road_name_from_step(step_a)
road_name_b = get_road_name_from_step(step_b)
if road_name_a == road_name_b:
return True
return False
def get_road_name_from_step(step):
if 'html_instructions' in step:
instruction = step['html_instructions']
road_name = extract_road_name(instruction)
return road_name
return None
def extract_road_name(instruction):
return BeautifulSoup(instruction, "html.parser").text
# Functions for avoiding segments
def find_route_avoiding_segments(start, end, avoid_list):
directions_a_b = get_directions(start, end, alternatives=True)
if not directions_a_b:
return None, None
avoided_routes = []
for route in directions_a_b:
route_a_b_points = decode_polyline_to_points(route['overview_polyline']['points'])
avoid_crossing = False
for avoid_start, avoid_end in avoid_list:
directions_c_d = get_directions(avoid_start, avoid_end, alternatives=False)
if directions_c_d:
route_c_d_points = decode_polyline_to_points(directions_c_d[0]['overview_polyline']['points'])
if do_routes_intersect(route_a_b_points, route_c_d_points):
avoid_crossing = True
avoided_routes.append(directions_c_d[0])
break
if not avoid_crossing:
return route, avoided_routes
return None, None
def find_mid_point_between(start, end):
start_lat, start_lng = map(float, start.split(','))
end_lat, end_lng = map(float, end.split(','))
mid_lat = (start_lat + end_lat) / 2
mid_lng = (start_lng + end_lng) / 2
if is_within_bounds(mid_lat, mid_lng):
return f"{mid_lat},{mid_lng}"
return None
def recursive_route_search(start, end, avoid_list, depth=0, max_depth=3):
if depth > max_depth:
return None
mid_point = find_mid_point_between(start, end)
if not mid_point:
return None
first_segment = find_valid_route(start, mid_point, avoid_list)
if not first_segment:
return recursive_route_search(start, mid_point, avoid_list, depth + 1, max_depth)
second_segment = find_valid_route(mid_point, end, avoid_list)
if not second_segment:
return recursive_route_search(mid_point, end, avoid_list, depth + 1, max_depth)
return merge_segments(first_segment, second_segment)
def merge_segments(first_segment, second_segment):
merged_route = {
'legs': first_segment['legs'] + second_segment['legs'],
'overview_polyline': {
'points': first_segment['overview_polyline']['points'] + second_segment['overview_polyline']['points']
}
}
return merged_route
def find_valid_route(start, end, avoid_list):
routes = get_directions(start, end, alternatives=True)
if not routes:
return None
for route in routes:
route_a_b_points = decode_polyline_to_points(route['overview_polyline']['points'])
if not is_route_within_bounds(route):
continue
avoid_crossing = False
for avoid_start, avoid_end in avoid_list:
directions_c_d = get_directions(avoid_start, avoid_end, alternatives=False)
if directions_c_d:
route_c_d_points = decode_polyline_to_points(directions_c_d[0]['overview_polyline']['points'])
if do_routes_intersect(route_a_b_points, route_c_d_points):
avoid_crossing = True
break
if not avoid_crossing:
return route
return None
RIYADH_BOUNDING_BOX = {
'north': 25.0885,
'south': 24.3246,
'west': 46.2613,
'east': 47.0484
}
def is_within_bounds(lat, lng):
return (RIYADH_BOUNDING_BOX['south'] <= lat <= RIYADH_BOUNDING_BOX['north'] and
RIYADH_BOUNDING_BOX['west'] <= lng <= RIYADH_BOUNDING_BOX['east'])
def is_route_within_bounds(route):
for leg in route['legs']:
for step in leg['steps']:
start_lat = step['start_location']['lat']
start_lng = step['start_location']['lng']
end_lat = step['end_location']['lat']
end_lng = step['end_location']['lng']
if not is_within_bounds(start_lat, start_lng) or not is_within_bounds(end_lat, end_lng):
return False
return True
# Helper functions for JSON formatting
def format_route_to_json(route):
return {
'start_address': route['legs'][0]['start_address'],
'end_address': route['legs'][0]['end_address'],
'distance': route['legs'][0]['distance']['text'],
'duration': route['legs'][0]['duration']['text'],
'overview_polyline': route['overview_polyline']['points']
}
# Vehicle cost and total vehicle functions
def get_truck_cost():
return 500
def get_car_cost():
return 300
def get_motorbike_cost():
return 100
def get_total_vehicles():
return 150 |