The Open Source Implementation
This is a continuation of Mark Balwanz’s blog posts on his creation of web mapping sites using both ESRI and Geoserver. Today he will talk about his experience creating the site using open source technology.
After completing the ESRI version of my project (Web GIS Duel: Part 2), I turned my attention to the open source version of my project. I have some experience with Open Source GIS from previous graduate courses and have spent some time working with Leaflet in the past, but this project was definitely going to be a learning experience for me. Below you will find a list of all the technology I used to create this web mapping application.
Now unlike the ESRI implementation, choosing the stack for this open source version was a lot more involved. I knew I would use QGIS for the styling and publishing of the data, and had previously decided to use GeoServer for the serving of the data to the web, but should I use OpenLayers or Leaflet? To be honest, I planned on using Leaflet as I had heard many good things about it and it seemed to be the up and coming library. However, after starting to build out my application with Leaflet I decided to switch to OpenLayers 3 as I was able to find more information about it online. Moving to OpenLayers also brought the unforeseen issue of finding “useful” information that was from OpenLayers 2 and did not translate most of the time, but that is a conversation for another day.
GeoServer WMS
After downloading all the open source software I needed to complete this project, I started by loading the three shapefiles into QGIS. I had some brief experience with QGIS in the past, and was once again impressed by how easy it was to work with. I styled the layers to match the styling I used with my ESRI map service and then just had to publish the data to GeoServer. However, I had to first find a way make GeoServer available to anyone on the internet and that is where the Amazon EC2 service came into play. Using Amazon’s AWS free tier I was able to spin up a Windows Server 2012 R2 instance and install GeoServer on it. After updating the security settings for my Amazon instance and then opening up port 8080 to inbound traffic, I now had a GeoServer that I could publish my data to. So back in QGIS, I installed the GeoServer Manager plugin and connected to my new GeoServer running on Amazon EC2. After that, it was very easy to publish my data as a WMS and retain the styling I set in QGIS.
HTML Template
Since I already had designed my application while completing the ESRI version, all I had to do was make a copy of it and remove the ESRI based JavaScript. Since I wanted both applications to look identical, I stuck with the same color scheme and moved on to working on the JavaScript portion of the application.
OpenLayers 3
The information I will share throughout the rest of this blog will sound very familiar for those of you who read part 2 of this series, as I followed the same general workflow as I did with the ESRI version.
The first step to building my application with OpenLayers was to add a script tag for the hosted version of the library and then instantiate the map. Since I wanted these two applications to look identical I chose to use the light gray basemap provided by Mapbox within my OpenLayers map. After I had the map working, I had to add my three WMS layers (US Bank, Competitors, and Census Tracts) to the map. Thankfully the OpenLayers website contains many sample pages and I was able to find one for adding WMS layers to the map.
At this point I had an interactive map that depicted all of the data that I had published out to my GeoServer. However, I had to now build the code that would allow the user to click on a US Bank location and have the details window update. So the first thing I needed to do was build the initial call that would return information about the bank location that was clicked on. Just like with the ESRI version, I was able to listen for “clicks” on the map and fire some code when that happened. I used the API’s ‘getGetFeatureInfoURL’ function to create a url to my WMS and then sent it via a jQuery AJAX call. Since I wanted to receive jsonp data back from my request, I did have to tweak the GeoServers web.xml file to allow it to send jsonp (just had to uncomment the lines shown in the image). Once this call was working I was able to parse the response and update the details window with the name and address of the selected location. There is probably a better way to accomplish this task, but since I was familiar with AJAX calls and was able to get this working that was good enough for me.
I know had the details window partially updated and had a “selected location” to use for the rest of my analysis. I was able to use an OpenLayers function to create the five mile buffer using the latitude and longitude of the selected location (returned from the previous AJAX call) along with the radius (in meters). Once I added the resulting polygon to the map, I now had the buffer being visualized and could move on to the task of finding every feature within it.
To this point in my development of this open source application, I was pleasantly surprised how easily I was able to find information online and was cruising along nicely. After a little research, I settled on a solution of using a WFS get features call that included a CQL spatial filter (DWITHIN). It seemed like the perfect answer to my problem, all I had to do was create the URL to use within another AJAX call and include the center (selected location geometry) and the distance I wanted to find features from that center. Pretty straightforward, right? I got the call working and it was returning features however when I examined the results I noticed it was not returning everything within the five mile buffer. It turns out that GeoServer had a known bug that makes it so that the DWITHIN filter can only use degrees as the distance unit in the filter. I did not think that would be a big problem and went about converting my mileage requirement to degrees, but then there is the fact that the conversion from mile to degree changes based on how far you are from the equator. I spent many, many hours on this problem and have to admit that never was able to resolve it. However, while researching the DWITHIN problem I stumbled upon another CQL filter. The WITHIN filter takes the geometry of a polygon (coordinate pairs) and returns everything that is within or intersects with it. Once again there was a slight problem that the coordinate pairs had to be formatted in a very specific way in order for GeoServer to understand it and return information. So I wrote a JavaScript function that looped through the buffer polygons coordinates and formatted them into a single string that then was used to create a URL form my WFS AJAX request. I also chose to use an “Intersect” as I believed that would be closer to what the ESRI Identify task used in my ESRI version. So finally after many frustrated hours of “googling” I had a working WFS call that returned jsonp data that contained every US Bank location, competitor (Wells Fargo & TCF), and census tracts that intersected the five mile buffer around the selected location!
The last task I had to accomplish was taking the response from my AJAX call and using it to populate the remaining parts of the details window. Thanks to my experience with the ESRI version I had a pretty good idea of what I needed to do. I first broke the returned features into three arrays based on the WMS layer they were in. After that I used the “length” attributes of the US Bank array and the Competitors array to update those items in the details window. Then I used the same JavaScript function that I used in my ESRI version, to loop through all the Census Tracts and sum the population attributes and then update the details window with that number. Please refer to part 2 of this series for a code snippet of this function.
I will say that other than the GeoServer issue I ran into with DWITHIN, the OpenLayers library was pretty easy to work with. In addition, since I already knew the general workflow of the application (since I already built it with ESRI technology) I was able to jump right in without spending too much time planning it out.
Amazon Cloud Web Hosting
Just like I did for the ESRI version, I turned to Amazon S3 for the hosting of this application. I uploaded my html file along with the images I used, and updated the settings of my S3 bucket to match what I did with my ESRI version. Now as long as I have my Amazon EC2 instance running GeoServer turned on, the application will work for anyone who navigates to it. If you have any questions about the Amazon S3 web hosting, please feel free to post comments or refer back to part 2 of this blog series.
Thanks for reading another post and please stop back for the fourth and final blog, where I will give you my final thoughts about everything I experienced throughout this project.
Comments