Today, I’m thrilled to share a fun project I worked on building an interactive map application using Python. If you’re someone who enjoys mixing coding with practical applications, this project is for you. I’ll walk you through every step of the process, the challenges I faced, and how I solved them
Idea Behind the Project
I’ve always been fascinated by maps and how they make navigation so intuitive. I wanted to create something that:
- Allows users to search for any location.
- Displays the searched location on an interactive map.
- Adds extra features like marking previous searches, creating radius circles, and saving the map for later use.
This sounded ambitious at first, but with Python libraries like folium
and geopy
, it turned out to be surprisingly doable.
The Tools I Used
Before diving into the code, let me introduce you to the libraries that made this possible:
folium
: To create interactive maps and markers.geopy
: To convert location names into geographical coordinates (latitude and longitude).IPython.display
: For rendering the map directly in a notebook or interactive environment.
The Complete Code
Here’s the code I wrote for this project, with explanations to guide you through each step:
codeimport folium
from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut
from IPython.display import display, HTML
# Initialize the geolocator for location searches
geolocator = Nominatim(user_agent="geoapi")
search_history = [] # To store previous searches
def create_map(location_name, map_type="normal", radius=None):
"""
Function to create an interactive map based on user input.
Args:
location_name (str): The name of the location to search for.
map_type (str): The type of map to display ('normal', 'terrain', 'toner').
radius (int, optional): The radius (in meters) to draw a circle around the location.
"""
try:
# Get the location's coordinates
location = geolocator.geocode(location_name, timeout=10)
if location:
# Extract latitude and longitude
latitude = location.latitude
longitude = location.longitude
# Save to search history
search_history.append({"name": location_name, "latitude": latitude, "longitude": longitude})
# Select map tiles based on user preference
tiles = "OpenStreetMap" if map_type == "normal" else "Stamen Terrain" if map_type == "terrain" else "Stamen Toner"
# Create the map
user_map = folium.Map(location=[latitude, longitude], zoom_start=12, tiles=tiles)
# Add a marker for the searched location
folium.Marker([latitude, longitude], popup=f"{location_name}").add_to(user_map)
# Optionally, add a radius circle
if radius:
folium.Circle(
location=[latitude, longitude],
radius=radius,
color="blue",
fill=True,
fill_opacity=0.3
).add_to(user_map)
# Add markers for all previous searches
for history in search_history[:-1]:
folium.Marker(
[history["latitude"], history["longitude"]],
popup=f"Previous: {history['name']}",
icon=folium.Icon(color="green", icon="info-sign")
).add_to(user_map)
# Save the map to an HTML file
map_filename = f"{location_name.replace(' ', '_')}_map.html"
user_map.save(map_filename)
print(f"Map saved as: {map_filename}")
# Display the map in the notebook or environment
display(HTML(user_map._repr_html_()))
else:
print("Location not found. Please try again.")
except GeocoderTimedOut:
print("Geocoder timed out. Please try again later.")
except Exception as e:
print(f"An error occurred: {e}")
# Main program loop for user input
while True:
location_name = input("Enter a location (or type 'exit' to quit): ").strip()
if location_name.lower() == "exit":
print("Exiting... Thank you for using the map application!")
break
map_type = input("Choose map type (normal, terrain, toner): ").strip().lower()
radius = input("Enter radius in meters for a circle around the location (or leave blank for no circle): ").strip()
radius = int(radius) if radius.isdigit() else None
create_map(location_name, map_type, radius)
Breaking Down the Code
Here’s a quick rundown of what each part of the code does:
Input and Geolocation
The program prompts the user to input a location name, which is then passed to geopy
‘s Nominatim
geocoder. This converts the name into latitude and longitude coordinates.
Map Creation
Using folium
, a map is generated, centered on the coordinates. The user can also choose between different map styles:
- Normal (OpenStreetMap): Standard map view.
- Terrain (Stamen Terrain): A topographic map style.
- Toner (Stamen Toner): A black-and-white, high-contrast map style.
Enhancing Interactivity
I added the following features:
- Radius Circles: Users can specify a radius around the location to highlight an area of interest.
- Search History: Previous searches are marked on the map with green markers.
Saving the Map
The map is saved as an HTML file (named after the location), so you can revisit it later.
Challenges and Solutions
- Handling Errors: I encountered a timeout issue with the geocoder. To fix this, I added error handling using
try
andexcept
blocks, ensuring the program doesn’t crash unexpectedly. - Dynamic Inputs: Allowing users to customize the map type and radius required extra validation to ensure valid inputs.
- Search History: Maintaining a search history was a fun challenge. I used a simple list to store past searches and displayed them as green markers on the map.
Testing the Project
Here’s how you can test this project:
Install the required libraries:
codepip install folium geopy
Run the code in any Python IDE or Jupyter Notebook.
Start entering locations and watch the interactive maps come to life!
Final Thoughts
This project was an amazing experience for me it combined problem-solving, creativity, and coding in a way that was both fun and practical. If you’re looking for a beginner-friendly project to explore Python libraries like folium
and geopy
, give this a try.