I thought I would show you how I’ve been working with my students in my GIS Programming class, and showing them SQL, Python, and ArcGIS. One of the fun things about Python packages is that there are tons of packages out there, and lots of things we can do with them – and it only takes a few lines of code.
One of the things my students do in Advanced GIS is create their own route-able networks in ArcGIS, and then we run a traveling salesman problem. The scenario is that we take 20 banks in the local area and figure out what route we would take if we wanted to rob all the banks.
As you know, building routes in ArcGIS is complex – that isn’t ArcGIS’ fault – it’s just that there are lots and lots of things to think about. But, it is important for the students to learn how to do this so that they can build their own if they have to.
Well, in my GIS Programming class, I showed them how to recreate the process with Google Maps. The code window is shown below, and comments will follow:
The first chunk of code basically brings in the Python packages:
import googlemaps, arcpy, numpy, warnings warnings.filterwarnings("ignore") gmaps = googlemaps.Client('ENTER API KEY')
The next chunk of code gets my bank shapefile (banksll.shp) and turns them into a feature layer and obtains a SearchCursor so that I can iterate through the cursor (notice too that I am grabbing the bank name and its X and Y coordinates (SHAPE@X, SHAPE@Y):
banks = arcpy.MakeFeatureLayer_management("k:/geog/geog419/labs/lab5 - network analysis/banksll.shp") banksSc = arcpy.da.FeatureClassToNumPyArray(banks,['NAME', 'SHAPE@X', 'SHAPE@Y'])
Google needs a starting and ending point. So, I’m simply starting and ending at a particular bank (the 20th bank in the list):
startAddress = [banksSc , banksSc] endAddress = [banksSc , banksSc]
I then take all the banks and create a list of waypoints (the SHAPE@Y and SHAPE@X values) and put the in a list called wp.
wp =  for bank in banksSc: wp.append(str(bank) + "," + str(bank))
Now, this is where the magic occurs. The googlemaps API is easy to use, and also makes use of the Google streets as well as the traffic conditions. Therefore, no need to build your own routes (now, as I said, an Advanced GIS student should know how to do that):
directions = gmaps.directions(startAddress,endAddress,mode='driving',waypoints=wp,optimize_waypoints=1)
yep, that really is it. Just one line that I pass the starting address, the ending address, the mode of transportation (driving), the waypoints, and whether I want to optimize the waypoints to generate a tour, rather than a simple point-t0-point path.
Believe it or not, that one command gives us our answer. Now we have to create two new loops to:
- add up all the seconds that each leg of the route takes
- print out the total time and the order of the stops
totsec = 0 for i in range(len(directions['legs'])): totsec = directions['legs'][i]['duration']['value'] + totsec print "Route will take: " + str(totsec/60) + " minutes, and will go in the following order " for b in directions['waypoint_order']: print str(banksSc[b])
that’s it! The fun part about this, that my students really like, is that we are using ArcGIS to do some things, then, we seamlessly take those results and jump to Google Maps to finish off the analysis, and then jump back into Python to print out the results. We are using the best of both worlds. In this case, the user doesn’t even need to know that Google is being used. Heck, if you just run the Python script, you don’t even need to open up ArcGIS.
Want to learn more about how to program with Python packages for geospatial? Check out my Python for Geospatial course here.