MapQuest has a whole range of useful and freely available
web services for geospatial queries. One of these is the
Open Elevation Service. I thought it would be interesting to try it out using
JEQL's capabilities of querying URLs and plotting datasets as images.
The Open Elevation Service is extremely simple to use. You just submit a URL containing the location:
http://open.mapquestapi.com/elevation/v1/getElevationProfile?callback=foo&shapeFormat=raw&latLngCollection=39.740112,-104.984856
and you get back a JSON (or XML) response with the elevation:
foo({
"shapePoints":[39.740112,-104.984856],
"elevationProfile":[{"distance":0,"height":1616}],
"info":{"copyright":{"text":"© 2011 MapQuest, Inc.","imageUrl":"http://tile21.mqcdn.com/res/mqlogo.gif","imageAltText":"© 2011 MapQuest, Inc."},
"statuscode":0,
"messages":[]}
});
JEQL doesn't (yet) do JSON parsing, but it's easy to pick out the height attribute with a simple RegEx:
height = RegEx.extract(elevJson, \'"height":(-?\d+)\}');
Querying over a grid of locations provides a dataset which is a gridded Digital Elevation Model (DEM). JEQL provides a function to generate a table which is a grid of integers, so it's easy to produce a grid of lat/long locations:
loc = select baseLat + i * cellSize lat, baseLon + j * cellSize lon
from Generate.grid(1, gridSize, 1, gridSize);
Once the elevations for all locations are retrieved, the locations are used to compute square cells (polygons) which cover the area, and the cells are symbolized with a fill value from a suitable color map based on elevation.
Here's the final result. It's slightly squashed in aspect ratio, since the data grid is in the lat/long coordinate system. The obvious data dropouts seem to be hard errors in the MapQuest service, which is slightly surprising. But's it's recognizably Mt. St. Helens - you can even see the
lava dome in the crater!
Not surprisingly, this isn't quick to generate - the service runs at about 10 queries per second. (Actually, that seems pretty reasonable for a free web service!). The service does support querying multiple points per request - I might try to see if this decreases the latency (although this might be a bit complex to express in JEQL).
Here's the whole script:
//--------------------------------------
//
// Plots a DEM generated using the MapQuest Elevation service
//
//--------------------------------------
baseLat = 46.16 ; baseLon = -122.25; // Mt St Helens
areaSize = 0.10;
gridSize = 100;
cellSize = areaSize / gridSize;
//---- Generate location grid
loc = select baseLat + i * cellSize lat,
baseLon + j * cellSize lon
from Generate.grid(1, gridSize, 1, gridSize);
//---- Query elevation service for each grid point
telev = select lat, lon, elevJson, elev
with {
url = $"http://open.mapquestapi.com/elevation/v1/getElevationProfile?callback=foo&shapeFormat=raw&latLngCollection=${lat},${lon}";
elevJson = Net.readURLnoEOL(url);
height = RegEx.extract(elevJson, \'"height":(-?\d+)\}');
elev = Val.toInt(height);
}
from loc;
Mem telev;
//---- Create raster cell boxes, symbolize with color map based on elevation, and plot
minElev = 800.0; maxElev = 2500.0;
tplot = select Geom.createBoxExtent(lon, lat, cellSize, cellSize) cell,
Color.interpolate("00a000", "ffb000", "aaaaaa", "ffffff", index) style_fillColor
with {
index = (elev - minElev) / (maxElev - minElev);
}
from telev;
textent = select geomExtent(cell) from tplot;
Plot extent: val(textent)
data: tplot
file: "dem.png";