5Features 5.1Maps
It was the project supervisor who first suggested adding maps into the application and that aspect of the project proved to be one of the most interesting. At first the Google “MapView” component was used [29]. To achieve this, the Google API library had to be downloaded (it was not installed by default) and the Android build target changed to “Google APIs”. The Google “MapView” component was well documented with plenty of support and examples making it a relatively easy task to get something up and running once an API key was generated from a Google account [30] (and then placed into an Android activities’ layout file).
Several experiments were performed to see how locally stored historic maps could be overlaid onto the MapView component. Initially, an overlay was added and its “draw” method overridden to display these maps while an additional overlay was created to place pin markers on it (so that a particular site could be selected on the map).
It was while this work was being done, however, that it was discovered from several web sites [30], [31] that Google’s Terms of Service (TOS) (section 8.2) prohibited the caching of their map data. It had been assumed it was acceptable to use cached copies of Google’s modern maps and that the “MapView” component would still work if there was no data connection. Although the latest release of their Google “maps for mobile” application (Version 5, July 2011) supported local caching of their map data, its TOS did not extend out to non-Google applications.
An alternative to using Google maps was then searched for and the open source project “osmdroid” [32] was discovered. This together with map data from OpenStreetMap [33] and OS Open Data [43] from Ordnance Survey allowed the historic maps to be cached locally. Subject to their license agreement, the OS open data maps were free (normally Ordnance Survey maps were protected by Crown Copyright until 50 years after the end of the year of their publication [47]).
There were several advantages in using the osmdroid code:
-
Locally stored georeferenced maps could then be used
-
Easier to customise the maps displayed (e.g. adding cross hairs to the map)
-
Experience of using open source code
And there were several disadvantages:
5.1.1Locally Caching Historic Maps
To compare the difference in loading times between using (historic) maps held locally and those held online, an experiment was done using the online historic maps available at the National Library of Scotland website [42]. One of the web pages on their site showed the 1765 William Edgar map overlaid onto a Google map of modern Edinburgh [46]. An Android activity was created with a “WebView” component being used to display the web page on the screen. The experiment showed that even on a Wi-Fi connection, the page took almost a minute to download and display.
5.1.2Osmdroid Maps
The project’s web site described itself as an “(almost) full/free replacement for Android’s “MapView” class” [32]. In the application, the “MapLocationActivity” activity class was created to implement the map page. Two map overlays (layers superimposed on top of the map) were used; one to hold the marker pins shown on the map and the other (handled by the osmdroid code) used to display the icon of a user. The Android “onSaveInstanceState” method was used to store the location that the user was currently looking at so that if the activity was re-started (for example if the device was rotated) then the same position could be displayed on the screen. To confirm to the user that they had touched an item on the map a click sound was played.
As mentioned in the Android documentation, some care had to be taken setting the update refresh values for the location code so the mobile device didn’t consume too much power by keeping the GPS on all the time [48]. A value of 60 seconds was chosen as values under this were not recommended [48].
During the development stage, it was thought that there was a bug in the osmdroid code as the map would sometimes “shoot off” when it was being scrolled. After some research it was believed to be the phone device itself that was causing the issue as it was eventually seen that other applications on the smartphone were prone to it as well. To reduce the problem, a bounding box was created round the maps to ensure a user could not scroll outside the area covered by the maps. It was discovered that somebody had already written code to achieve this in a patch file for the osmdroid code, so once the patch code was examined and understood it was applied to the source code and tested.
To reduce the number of map images fetched from memory and to lower the overall processing work, it was decided to avoid using an overlay to display the historic maps on (since this would involve showing two map tiles at different opacities for a given area displayed on the screen). This could then lead to delays on lower powered devices (which was seen in early experiments as missing tiles). Instead, when the user changed the map being displayed (by touching the title of the map), the tile source was changed.
Several modifications were made to the osmdroid project code for this application and are summarised below:
Feature
|
Change Made
|
Map cross-hair
|
File: views\overlay\TilesOverlay.java
A cross hair was added to the map display (this was useful as the map help window displayed the latitude and longitude of the centre of the map). It also showed the location a user would zoom into if they used the zoom control.
|
Compass code
|
File: views\overlay\MyLocationOverlay.java
A new method called “setCompassTopRight” was created to place the compass at the top right hand corner of the screen (instead of at the top left where the title of the map was).
|
Flyover Animation
|
File: views\MapController.java
A new method called “animateToSlow” was created to move the position of the map to a given location in a specified amount of time. This was needed so that if a point on the map flyover was far from the current location, then the map could be given a longer time to scroll there.
|
Bounding Box
|
File: views\MapView.java
The changes made here were made by the patch file used to limit the user to a particular area of the map.
|
Offline tiles.
|
File: tileprovider\tilesource\OfflineXYTileSource.java
This was a new file created to hold the “offlineXYTileSource” class, allowing the use of offline, locally cached map files.
|
Offline tiles.
|
File: tileprovider\modules\MapTileFilesystemProvider.java
A new method called “getBaseHGuideTileDirectory()” was created and the “loadTile” method was modified to allow offline tiles to be used.
|
5.1.3Georeferencing
An interesting aspect of this project occurred about one month into it when it was discovered that one of the available historical maps of Edinburgh (the 1647 James Gordon map) had not been georeferenced. Since many older maps were typically not geographically accurate, georeferencing these images meant adding accurate location information to them (specifying exact latitude/longitude values for specific points) to warp the image into its correct geographical shape. This was needed for the application since the user’s position was to be superimposed on; therefore an accurate map had to be used. The National Library of Scotland recommended an open source software package called “Quantum GIS” [40] to achieve this.
The screenshot from Quantum GIS in Figure 18. illustrates how control points (typically about a hundred) were used to match up an existing georeferenced map to a map you wanted to georeference. The map image shown in Figure 19. shows how georeferencing an old “incorrect” map distorts it into its correct shape. According to the NLS, no one had georeferenced this map before.
-
Georeferencing the 1647 James Gordon map
-
Georeferenced file before map tiling process
Once this was completed, another software package called MapTiler [41] was used to tile the map (to break it up into small image squares) ready for display. The principle behind map tiling was to store the same image of an area at different zoom levels (effectively creating many images of the map to improve the speed at which the maps were displayed). Two example map tiles are shown in Figure 20..
5.1.4Map Tiles
Google Maps, Microsoft Virtual Earth and Yahoo Maps as well as the open source “OpenStreetMap” used the same method for rendering map tiles meaning tiles generated for one were compatible with the others [58]. Each square tile was 256 pixels wide and each covered the same square area at any given zoom level. However, at the time of writing, there were three systems for indexing (or addressing) map tiles: the Google/ Slippy map system [49], [50], the TMS “Tile Map Service Specification” (a variant of Google tile addressing, which was used in open-source projects) [53] and Microsoft’s QuadTree [57].
Unfortunately, when the map tiles were generated and tested they did not appear on the smartphone’s screen. After some investigation it was discovered that although the osmdroid code used the Google/Slippy map format, the tile names generated by the MapTiler program followed the TMS specification and so were incorrect when they were used with the HGuide program (the tile contents were fine but their filenames were wrong).
That was because the Google and TMS system differed in their calculation of the map tile to use in the y-axis (the x-axis calculation remained the same).
-
OpenStreetMap tiles of Edinburgh
You can see from Figure 20. how the map tile names in Google maps and OpenStreetMap were sequenced from top to bottom since the tile origin was considered to be at the top-left of the tile grid.
In contrast to this, the TMS format sequenced the y-axis tiles from bottom to top (the tile origin was from the lower-left) as seen in Figure 21.. To get round this issue, the method “convertFromTMSValue” was created in the “OfflineXYTileSource” java file to convert the file name requested from the Google system to the TMS system. Thankfully, other developers had needed to convert between these two systems and the code to achieve this was straightforward and freely available [55], [56].
-
TMS numbered tiled images.
Another issue that was encountered was the fact that the Android media scanner service was slowing down the device when it found the map tiles on the SD card. The Android media scanner was part of the photo gallery and was used to search for media content on the device that could be displayed. Since the map images were made up of lots of small image files, the media scanner was creating thumbnails of them and this was badly affecting performance. Fortunately the Android user groups supplied the solution of creating a “.nomedia” file so that the service would ignore any files in that directory (and subdirectories).
To create a (modern) map of Edinburgh that could be stored on the device, a program called “Mobile Atlas Creator” was used (as seen in Figure 22.) [59]. This program allowed the user to create offline maps from several online sources. Once a data source was selected (OpenStreetMap was used), the user could zoom into and select an area to download. It would build maps tiles to several zoom levels and create a directory structure that could then be copied to the mobile device. The size of the data produced using this method was 6Mbytes.
An alternative method that was tried but ultimately not used was to create map files from the Ordnance Survey “OpenData” CDs. At the time of writing, these files were freely available from the Ordnance Survey via an order form from their website [43]. This data was used at first but the file sizes generated were much larger and so were not used (to keep the application installation size to a minimum). Further work could be done to reduce their size if required in the future. It was interesting to note that the historical map tiles were generally much larger than the tiles used by Google and others, since they were highly detailed (and possibly too highly detailed for the needs of this application).
-
Mobile Atlas Creator
5.1.5The Map Flyover
This feature was added to show the user interesting aspects of the historic maps and describe them with references to the content stored in the guidebooks. To achieve this, an asynchronous task was created and the information on each flyover was stored in the XML file. Originally this feature was going to have an audio commentary but to save time it was decided to simply play some music while the flyover was in progress.
It was decided to store the details of each flyover in the guidebook XML file. This was done for several reasons; it would make it easier to edit the points if they were stored in a file rather than embedded in the code and it would be easier to store multiple flyovers per guidebook (if the flyover details were embedded in the source code then it would have been messier and less flexible). A description of a flyover held in the XML file (including the points on the map to visit) is shown in Figure 23.. Attributes such as “HoldTime” and “JourneyTimeToHere” were used to better control how the flyover moved between the points on the map. Although the XML could store multiple flyovers only one was used in the submitted application.
-
Flyover information held in the XML guidebook file
It was important not to update the user interface in the run method of the background thread (called “doInBackground”) [60]. Instead, to ensure proper synchronisation, the method "onProgressUpdate" was called so the screen could be updated safely (as in many other development environments, updating a graphical user interface from a background thread is dangerous unless care is taken to avoid race conditions on shared resources).
The flyover activity extended the existing “MapLocationActivity” that was used for the normal viewing of the maps. However, several changes were made if it was running in this mode, for example the pin markers on the map were set to be hidden. To ensure the user couldn’t interact with the map during a flyover, a transparent “ImageView” component was added to the layout file to intercept all the screen touches. In addition to this, a method was created to ensure the display didn’t dim (due to a screen timeout) when the map flyover was in progress. Several changes had to be made to the osmdroid code to correctly achieve the scrolling maps; a new method called “animateToSlow” was added since the equivalent osmdroid method did not actually work.
To help the user align the maps when they were being used at a location, a compass was displayed in the upper right hand corner of the screen. This was a simple change to make in the code as it was an existing component of the osmdroid code. The only caveat was to ensure that when the activity was sent into the background (when the “OnPause()” method was called), that the compass was disabled (this was for both battery conservation and program stability reasons) and that it was then enabled when the activity was brought to the foreground.
5.1.7Map Options
Several features were added to the maps to make them more useable. These included adding a map legend, a screen displaying information about the maps and an option to show or hide the pin markers.
During development it was noticed that the historical maps had many numbers written on them which referred to the names of the streets. To allow the user to easily read these street names, it was decided to create a dialog box to display them, as shown in Figure 24.. This street list was stored in a Unicode text file and the “HGuideInformationBox” dialog box class was used to display it. A straightforward change that could be made in the future would be to reverse this and allow the user to select a street from the list and then display it on the map.
Another option that was added was to allow the user to choose whether the pin markers should be hidden or displayed (to let them see the maps unobscured).
-
The application map options and map legend
Share with your friends: |