Austin Marathon Mashup with Google Maps, USGS Elevation Data, and ESRI Elevation Service

Posted on December 10, 2009. Filed under: Uncategorized |

I’m training for the upcoming Austin Marathon and Half Marathon and thought it would be cool to put together a simple mashup showing elevation information for the course.  The terrain for this particular race can be pretty challenging.  So, what I’ve done is put together a quick mashup using a variety of resources including the Google Maps API, the USGS Elevation Query Web Services, an elevation profile REST service from ESRI, and Dojo to tie everything together.  It’s nothing fancy, but you can see the final product here.

To find the elevation at any mile marker along the marathon route simply click the marker and the application will query the USGS Elevation Query Web Service to determine the elevation in meters at that point.  To see an elevation profile for the entire course, click the ‘Get Elevation Profile’ button which uses the ArcGIS JavaScript Extension for the Google Maps API along with the ProfileService task.

In this post I’ll detail how I quickly put together this mashup.

Google Maps API
Obviously the base map for this mashup is Google Maps so we reference the API to create our map and then add the marathon mile markers and route.  I’m not going to go into much detail on creating the base map.  If you need basic information on the Google Maps API you can download a free copy of our Introduction to the Google Maps API e-learning course.  I will point out that we are reading in the mile markers for the marathon from an XML file as seen in the code example below.  For more information on reading XML files from Google Maps please review a previous article on the subject.

We follow a similar process for adding the marathon route wherein we create a new instance of GPolyline by feeding in an array of GLatLng objects that define the route.

ArcGIS JavaScript Extension for Google Maps
Next, to display a terrain profile for the marathon route we are going to use the ProfileService which is a task published by ESRI.  To take advantage of this task we need to import a reference to the ArcGIS JavaScript Extension for Google Maps which allows you to plot the results of a geoprocessing task like the ProfileService on top of a Google Map.  Below you will see the reference to this API.

Next, we need a reference to the ProfileService.

The ‘Get Elevation Profile’ button triggers a call to the ‘generateProfile()’ function seen below.

I will call your attention to a few lines of code in generateProfile().  The first line creates a new instance of the Google Maps API object GPolyline by calling a JavaScript function which loads the points of inflection for the marathon route.

The next few lines below that create ArcGIS Server JavaScript API objects for FeatureSet and Feature.  The instance of FeatureSet is created by referencing the GPolyline object that we initially created in the function.  Finally, we create various task parameters that will then be used as input when we execute the task against ProfileService.

Task parameters include the instance of FeatureSet that we created from our GPolyline object along with parameters to define the output image width and height of the profile and a boolean value indicating whether or not we want the segments of the route to be displayed in the elevation profile.  We do not in this case because the large number of points that define the route will simply clutter the output terrain profile.  Our last line of code in this function calls the execute() method against profile task.  Note that we feed in our task parameters, a second parameter that indicates whether or not we want the results to be returned as KML in the form of a GGeoXml object, and finally a callback function that will execute when the task has finished.  ProfileService is a synchronous task meaning that the application will wait until the results have been returned to continue functioning.  In this case, the function profileCallback() will be run against the results of the service.

A FeatureSet object is returned from the task.  In this case, the FeatureSet contains a Feature which represents the marathon route.  A Feature can contain both the geometry of the feature as well as attribute information.  In this case we aren’t concerned with the geometry since we already know the marathon route.  The attributes though contain the terrain profile information including a path to the URL where the output terrain profile image was placed along with some additional information that describes the profile.  Finally, as is indicated in the highlighted section of the profileCallback function above we define an HTML snippet in the form of a <div> tag that contains a pointer to the URL of the terrain profile image along with the profile description.  This HTML is then placed inside a Google Maps API info window and displayed at the center point of the route.

USGS Elevation Query Service
Clicking a mile marker or any point along the route triggers a call to the USGS Elevation Query Service and displays the results just above the map.  To access the USGS service we are going to use the dojo.io.script.get() method which is part of the Dojo JavaScript framework.  We’ve written extensively about the Dojo framework on this site and provide a general overview here.  Take a look at the code below and then we’ll discuss how this is accomplished below.

We are going to wrap everything inside a Google Maps event listener which ‘listens’ for a click on the map.  You can see this in the first line of code above.   Events in Google Maps are registered with the GEvent object and the addListener() method.  The addListener() method takes three parameters.  The first is the object (an instance of GMap2 in this case), the second is the event to listen for on the object, and the final parameter is a function that will run in response to the event.  So in general terms we are setting up a function that will execute anytime the user clicks the map.  We need this event listener to detect when the user clicks on a mile marker or a point along the route.  Inside the function is where all the work takes place to respond to the event.  I’ll draw your attention to a few pertinent lines.  We need a reference to the USGS Elevation Query and we provide that in the first line that I have highlighted above.  However, this provides only the base URL.  We also need to append the latitude and longitude where the user clicked to the URL and this is accomplished in the second line that I have highlighted above.  Now, in this case we are only providing the elevation for a mile marker or a point along the route rather than any point the user clicks on the map.  The ‘click‘ event on GMap2  passes different arguments based on the context of the click, and whether or not the click occurred on a clickable overlay.  You can see this in the event listener below.

If the click does not occur on a clickable overlay (this would be GMarker, GPolygon, GPolyline, or GInfoWindow), the overlay argument is null and the latlng argument contains the geographical coordinates of the point that was clicked. If the user clicks on an overlay that is clickable (GMarker or GPolyline in our case), the overlay argument contains the overlay object, while the overlaylatlng argument contains the coordinates of the clicked overlay.

So for our application we only want to call the USGS Elevation Query if the use has clicked on a mile marker (GMarker) or a point along the route (GPolyline).  That accounts for our ‘if’ statements on ‘overlay’ and ‘overlayLatLng’ as seen in the code example above.

That was a bit of a lengthy description about a small subject in the overall scheme of the application, but it was necessary to fully describe the GMap2.click event.

Now we get to the heart of the matter which is calling the USGS Elevation Query Service with the latitude, longitude coordinate pair of either a mile marker or a point along the route.  Here is where we are going to make use of Dojo and its capability of making cross-domain requests with JSONP.  JavaScript’s XmlHttpRequest object does not allow you to load data from outside of the page’s current domain because of the same origin policy.  However, it turns out that <script> tags are not subject to the “same origin” policy.  JSONP is an informal standard that that has been developed to allow data to be take advantage of cross-domain loading.  Dojo provides the dojo.io.script.get() method to handle JSONP functionality.  Refer again to the code above and pay particular attention to the final area that I have highlighted in the listener function.  The get() method takes a single object literal parameter that can contain various properties including the url that will be called (http://ws.geonames.org/srtm3JSON?lat=<lat coordinate>&lng=<lng coordinate>).  Other properties of note include  ‘load’ and ‘error’ functions.  The ‘load’ function is passed a response object which in our case will contain the elevation of the point that was clicked.  The ‘error’ function would, as its name implies, be called in the event of an error.  Our ‘load’ function takes the elevation value passed in the response object and places it inside our web page as seen below.

So there you have it.  A simple, but useful mashup for obtaining elevation information related to the upcoming Austin marathon.

More Information
If you’d like more information about using Google Maps with ArcGIS Server you may wish to consider our upcoming Internet based, instructor guided course, Building Web 2.0 Mapping Applications with ArcGIS Server and Google Maps. You’ll learn how to build applications that integrate these technologies to display your existing GIS data in Google Maps.  We also offer a similar class (Mastering the ArcGIS Server JavaScript API), but more focused on developing web mapping applications with the ArcGIS Server JavaScript API.  Both classes begin January 11th, 2010.

Make a Comment

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

One Response to “Austin Marathon Mashup with Google Maps, USGS Elevation Data, and ESRI Elevation Service”

RSS Feed for GeoChalkboard Comments RSS Feed

This is a great example and walk thru – Thanks! Been looking for something like this for awhile now. I was wondering – is there an easy way to convert that to MILES instead of KM?


Where's The Comment Form?

Liked it here?
Why not try sites on the blogroll...

%d bloggers like this: