Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
jupyter-naas
GitHub Repository: jupyter-naas/awesome-notebooks
Path: blob/master/Google Maps/Google_Maps_Create_itinerary_optimisation_on_differents_waypoints.ipynb
5393 views
Kernel: Python 3

Google Maps.png

Google Maps - Create itinerary optimisation on differents waypoints

Give Feedback | Bug report

Tags: #googlemaps #optimization #data #naas_drivers #operations #snippet #dataframe #google_maps_api #directions_api

Last update: 2023-08-08 (Created: 2023-08-08)

Description: This template analyses a given set of waypoints, optimizes the order of visiting them, and outputs a list with the correct order. Thus, making it useful for travelers, who want to visit multiple locations most efficiently.

Input

Import libraries

import naas import folium try: import polyline except ImportError: !pip install polyline import polyline from geopy.geocoders import Nominatim from itertools import permutations try: import googlemaps except ImportError: !pip install googlemaps import googlemaps

Setup variables

Mandatory

Pre-requisite:

  1. Follow the steps in the link - https://developers.google.com/maps/documentation/routes/cloud-setup

  2. Sign up for an account with the Routes API provider.

  3. Make sure to enable Routes API as it is in the "Additional APIs" section in the google cloud console.

  4. Check the available countries https://developers.google.com/maps/documentation/routes/calculate_toll_fees#toll-locations

  • api_key: This variable holds the Google Cloud Platform (GCP) API key.

  • origin: This variable represents the starting location for a journey.

  • waypoints: This variable indicates the list of differents waypoints for a journey.

  • destination: This variable indicates the end location or destination for a journey.

# Mandatory api_key = naas.secret.get("GCP_MAP_API_KEY") or "YOUR_GCP_MAP_API_KEY" # Read API key from the secret variable GCP_MAP_API_KEY origin = "Circonvallazione Salaria, 00199, Rome RM, Italy" waypoints = [ "Corso Australia, 35136 Padova PD, Italy", "Viale Jacopo dal Verme, 36100 Vicenza, VI, Italy", "Viale Nino Bixio, 1, 31100 Treviso TV, Italy" ] destination = "Milan, Italy"

Model

Connect to Google Maps

gmaps = googlemaps.Client(key=api_key)

Convert the addresses to coordinates function

def get_coordinates(locations): geolocator = Nominatim(user_agent="geoapiExercises") coordinates = [] for location in locations: address = geolocator.geocode(location) if address: coordinates.append((address.latitude, address.longitude)) return coordinates

Calculate total distance function

def calculate_total_distance(gmaps, waypoints): total_distance_meters = 0 for i in range(len(waypoints) - 1): from_point = waypoints[i] to_point = waypoints[i + 1] route = gmaps.directions(from_point, to_point, mode="driving", optimize_waypoints=True) if route: total_distance_meters += route[0]["legs"][0]["distance"]["value"] else: raise ValueError(f"Error calculating distance between waypoints {i} and {i+1}") return total_distance_meters

Optimize waypoints function

def optimize_waypoints(gmaps, waypoints): min_distance = float("inf") optimized_order = None for perm in permutations(waypoints[1:-1]): waypoints_order = [waypoints[0]] + list(perm) + [waypoints[-1]] total_distance = calculate_total_distance(gmaps, waypoints_order) if total_distance < min_distance: min_distance = total_distance optimized_order = waypoints_order return optimized_order

Create a map to display the route

locations = [origin] + waypoints + [destination] coordinates = get_coordinates(locations) optimized_waypoints = optimize_waypoints(gmaps, coordinates) map_optimized_route = folium.Map(location=optimized_waypoints[0], zoom_start=5) for i in range(len(optimized_waypoints) - 1): from_point = optimized_waypoints[i] to_point = optimized_waypoints[i + 1] route = gmaps.directions(from_point, to_point, mode="driving", optimize_waypoints=True) if route: route_polyline = route[0]["overview_polyline"]["points"] decoded_points = polyline.decode(route_polyline) folium.PolyLine(locations=decoded_points, color='blue').add_to(map_optimized_route) for i, waypoint in enumerate(optimized_waypoints): location = gmaps.reverse_geocode(waypoint) address = location[0]["formatted_address"] folium.Marker(waypoint, popup=f"Waypoint {i+1}: {address}").add_to(map_optimized_route) else: raise ValueError(f"Error calculating route between waypoints {from_point} and {to_point}")

Output

print("Optimized Waypoint Order:") print() for i, waypoint in enumerate(optimized_waypoints): if isinstance(waypoint, tuple): location = gmaps.reverse_geocode(waypoint) address = location[0]["formatted_address"] if i == 0: print(f"🚦 Origin: {address}") elif i == len(optimized_waypoints) - 1: print(f"🏁 Destination: {address}") else: print(f"📍 Waypoint {i}: {address}") # Calculate and display the total distance for the optimized order total_distance = calculate_total_distance(gmaps, optimized_waypoints) total_distance_km = total_distance / 1000 print() print(f"Total Distance: {total_distance_km:.2f} km") display(map_optimized_route)