I just put the finishing touches on a web map of municipal solid waste facilities and closed landfills and I thought it made a good candidate for my first ever blog post. The Environment and Development (E&D) department here at NCTCOG wanted to give their previous application a facelift. The old way of doing things was to have a static map image for each landfill, but now we can take advantage of ArcGIS Server and web mapping APIs such as Google Maps to enhance the user experience.We have done several projects using ArcGIS Server with Microsoft's Bing Maps API (formerly Virtual Earth), but I chose Google Maps for this project for several reasons: 1) I wanted to see what it was like to develop with ESRI's ArcGIS Javascript Extension for Google Maps; 2) ESRI's Google Maps extender supports the display of dynamic ArcGIS services (Bing doesn't); and 3) I saw a post by Dave Bouwman that talked about displaying large datasets in Google Maps using the ESRI REST API which gave me a good start.
Before I talk about the front-end, let me provide some insight into the data that is driving it. These datasets fall into an area that historically has been tricky to deal with in that non-GIS staff are responsible for editing attributes for each landfill or facility while GIS staff are responsible for editing the corresponding points and polygons. So what I ended up doing is migrating old point and polygon shapefiles to SDE feature classes and migrating an old Access database with the non-spatial attributes to SQL Server. The feature classes essentially only contain one attribute value: the unique ID of each facility. In ArcMap, I can use this unique ID to join the SQL Server table to the SDE feature classes so we don't have to query multiple data sources to provide both spatial and tabular information to the end users. (Note that if we were dealing with a huge number of features this ArcMap join method would have serious performance implications but since we have less than a thousand, it works great.)
With my data symbolized and joined in ArcMap and saved into a .mxd file, I then created an ArcGIS Server dynamic map service that can be easily draped over the Google base map. I chose to keep the service dynamic because the database is likely to change often (at least in its early stages) and I didn't want to have to re-cache every time a change occurred. I also needed the ability to dynamically turn features on and off based on certain criteria without having to create a separate service for each.
E&D wanted to have the ability to separate the Closed Landfill
Inventory from the active landfills and solid waste facilities without losing the ability to view them together. To do this without creating a separate application for each, I allow the page to be called with different URLs (querystrings) that will cause the application to present 3 different modes: 1) active landfills and solid waste facilities, 2) Closed Landfill Inventory, and 3) all of the above. In javascript you can parse out querystring values from the location.search property. Depending on the mode, the javascript will change the default map view using the setLayerDefinitions() ESRI function for dynamic layers and ASP will render the appropriate form checkboxes used to toggle map features. You can check out the different modes using the 'Change Map Type' drop-down above the map.Due to the large potential number of points, rather than try to render each as an object (aka marker in the Google lingo) I chose to display the features in their PNG-tile form. The user can click on a point and which runs an ESRI identify task and presents the result in an info-window with the results. The nice thing about this is that the user can click in an area with a lot of overlapping (at least in appearance) points and be presented with a table list of all of the points that fall within a specified tolerance. The downside of not using markers is that the user does not get the nice little cursor change when they hover over a point that hints to the fact that they can click.
You can view the javascript code driving this app here. A few more noteworthy features of this application:
Zoom to polygon using ESRI FindTask. Selecting a county from the drop-down queries uses the esri.arcgis.gmaps.FindTask method to return the matching county. We can then use .getBounds(), .getCenter(), and .getBoundsZoomLevel() methods to get the appropriate values to feed into the .setCenter map method.
Use of cookies to save previous map extent and type. Originally, when users would view the details page for each site and then return to the main page, the map would reset to the default coordinates hard-coded into the initialize() function. To force the map to save its previous state, temporary cookies are used to save the map center point, zoom level, and map type (satellite, terrain, hybrid, etc).
Limiting displayed identify results to match the current layer definition. Unfortunately ESRI's identify task does not respect the current layer definition, so even if the user had toggled everything off with the exception of Active Landfills, the identify results that would populate the infowindow would include any features that fell within a certain tolerance of the user's mouse click. To solve this, I create the isIdentifyResultInCurrentMapFilter function to determine whether or not to display the results as we loop through each. This is a hack and I'm willing to bet there is a better approach out there (let me know if you have one).
No comments:
Post a Comment