OpenLayers with Various Data Sets and Tiles
In my last post, I dived into OpenLayers and created a demo that uses different data sets, layers, and tooltips. Today, I am creating something very similar but serving a different purpose: visually comparing something with different data sets of geographical points. That sounds confusing, but I am referring to a concept like airports and grabbing data about airport locations from various sources and visualizing the differences between the sources. You can just look at the size of the data source and determine that it is larger and has more airports but plotting geo locations on a map and seeing it with your eyes can bring more insight.
I will get to airports in a second, but lets take a step back and just consider drawing the world on the browser screen. You have to make some choices like the geographical projection of the map, the size, zoom level, and other variables. One of these is tiles. Unlike my D3 examples, where I actually used geoJSON data to draw all the lines and points on a map, OpenLayers uses tile images to render the base layer that shows the map. Most of the OpenLayers examples leverage the OpenStreetMap tiles but you can implement OpenLayers to load any tile that you want.
There are many sources for map tiles, different types of Google and Bing tiles (physical, streets, hybrid, satelite, road, aerial, aerial with labels), MapQuest, ESRI, OpenStreetMap, and numerous tiles from MapBox (demo below only uses Natural Earth). I figured it would be cool to have a world map where you can just switch the tile source using a radio button and I wanted to show this using jsFiddle:
Ok, now back to airports. Where do you find data for all the airport locations in the world? Either someone out there provides this information in a good format or you have to start web scraping and converting. Some googling landed me on the The Global Airport Database which gives you a free text file of 9300 airports from around the world. OpenFlights data is another great source with 7411 airports around the globe in csv format. If you browse GitHub you will also find different airport data files in different repositories.
There are other websites that list airports of the world but if I was going to scrape this data, I would probably use some free APIs like flightstats, flyontime, or even this custom implementation. Either way, the data is out there, but it is presented in different formats, with different values, so representing this data on a map will take some tweaking.
I added headers to the csv file from openflights and looking at the examples and tags I figured that the OpenLayers.Layer.Text constructor would help me render the CSV file, but this constructor only works for special tab delimited format. So, I quickly converted the CSV to GeoJSON using the ogr2ogr web client and everything worked like a charm using the OpenLayers.Layer.Vector constructor and OpenLayers.Format.GeoJSON() format.
The text file from Global Airport Database comes with a lot more problems. It is not a CSV, the columns are separated, and geographical coordinates are presented using degrees, minutes, and seconds. But there is a larger issue, there are many airports without any geographical locations. When I removed those, there was only 4188 airports left (out of 9300) so I decided not to use this data set. I went back to GitHub and found two more JSON files with world airports.
These files are not GeoJSON so we can either turn them into GeoJSON so that OpenLayers knows how to find the coordinates and names or we can do the JSON parsing inside our code. I slightly modified the github file (removed the “posts” part and turned the “long” label for longitude into “lon”) so that they are both an array of objects with similar values (otherwise I would need more parsing logic). I also added a type property into my layer loading function (GeoJSON vs JSON) and I basically loop through the JSON file and extract the geo coordinates as well as the name of each airport.
Glancing at the data retrieval documentation, I used the OpenLayers.Request.GET method to grab the JSON file. Then, I create a vector feature (new OpenLayers.Feature.Vector) and point (OpenLayers.Geometry.Point) for each airport and translate the JSON geo-coordinates according to a specific map projection. I also add the name of the airport into attributes and include some opacity for each point so that we can visually detect overlayed points.
This processing definitely affects performance and world airports might not be a good example of visually comparing different data sets on a world map. However, this was a good exercise in plotting JSON in OpenLayers (as opposed to GeoJSON) and I think it will help me in my future OpenLayers examples and demos. Hopefully it is useful to someone out there.
Here is the OpenLayers Demo to compare different JSON airport data sets.
Related:
flyontime ORD airport
flyontime source
Panoraimo and OpenLayers
Using data from multiple divergent sources in OpenLayers
Server Side Clustering of Geo Points using ElasticSearch