Quantcast
Channel: Maps Blog
Viewing all articles
Browse latest Browse all 102

How To Load Spatial Data From SQLite In A Windows Store App

$
0
0

Sometimes it can be helpful to hold geospatial data locally and to distribute it with the application. In this example, we will use SQLite to store geospatial information and visualize it as a layer in the Bing Maps Control for Windows Store Apps.

SQLite is a software library that implements a self-contained, server-less, zero-configuration, transactional SQL database engine.

Preparing the Data

For this example we will be using trails which we retrieved from the King County GIS Data Portal. This data is available in Esri Shapefile format with coordinates in the North American Datum 1983 (NAD83) system. I converted them into a SQLite database with coordinates described as latitudes and longitudes with decimal degrees in the World Geodetic System 1984 (GS84) using the ogr2ogr command-line tool from Geospatial Data Abstraction Library (GDAL). The command for this conversion is:

ogr2ogr.exe -f sqlite -lco FORMAT=WKT "D:\Downloads\GeoData\King County\trail_SHP\trail.db" 
"D:\Downloads\GeoData\King County\trail_SHP\trail.shp" -t_srs EPSG:4326

Prerequisites

Since we are developing a Windows Store App, we need access to a Windows 8 machine as well as Visual Studio 2012. A free version of Visual Studio Express 2012 for Windows 8 is available here.

For this project we require the “Bing Maps SDK for Windows Store Apps” as well as “SQLite for Windows Runtime” you can install both from Visual Studio 2012 by selecting “Extensions and Updates” from the menu “Tools” and searching for the respective SDKs in the online gallery.

We will also require a Bing Maps Key. If you don’t have one yet, you can follow the instructions to get a free trial or basic key.

Preparing the Project

Let’s start by creating a new project using the blank Visual C# template for Windows Store Apps.

BlankVisualCSharpTemplateWindowsStoreApps

Next we add references to the Bing Maps SDK, the Visual C++ Runtime and SQLite.

ReferenceManager-SQLite_Blog

The Bing Maps SDK requires that we compile separately for each processor architecture. So we need to open the “Configuration Manager” and change the platform from “Any CPU” to a specific one – here “x64”.

ConfigurationManager

We also require the “sqlite-net” library and we can add this from NuGet by opening the menu “Tools” “Library Package Manager” “Manage NuGet Packages for Solution” and searching for “sqlite-net”.

ManageNuGetPackages

Finally we add the SQLite database trail.db to the folder “Assets” of the project, set the property “Build Action” to “Content” and “Copy to Output Directory” to “Copy if Newer”.

SolutionExplorer

Adding the Application Markup

Now that our project is prepared, we open the MainPage.xaml add the namespace for the Bing Maps control and define the user interface. In the user interface, we load Bing Maps centered to a location in King County at zoom-level 13 and specify that we want to display the aerial imagery.

<Pagex:Class="SQLite_Blog.MainPage"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="using:SQLite_Blog"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:bm="using:Bing.Maps"mc:Ignorable="d">
<GridBackground="{StaticResourceApplicationPageBackgroundThemeBrush}"><Grid.RowDefinitions><RowDefinitionHeight="140"/><RowDefinitionHeight="*"/> <RowDefinitionHeight="Auto"/></Grid.RowDefinitions>
   <TextBlockx:Name="pageTitle"Text="WinRT and Spatial Data  from SQLite"IsHitTestVisible="false"Style="{StaticResourcePageHeaderTextStyle}"VerticalAlignment="Center"Margin="30,0,30,40"/>
   <bm:Mapx:Name="myMap"Grid.Row="1"MapType="Aerial"ZoomLevel="13"Credentials="Your_Bing_Maps_Key"><bm:Map.Center><bm:LocationLatitude="47.702894"Longitude="-122.054860" /></bm:Map.Center></bm:Map>
   <TextBlockx:Name="myAttribution"Text="Data provided by  permission of King County"Grid.Row="2"/></Grid></Page>

Adding the Code-Behind

In the code-file MainPage.xaml.cs we define a class that describes the SQLite table.

public class trail
{    public string OGC_FID { get; set; } public string WKT_GEOMETRY { get; set; }  public string kc_fac_fid {  get;  set; }public string trail_name {  get;  set; }public string trail_type {  get;  set; }public string surf_type {  get;  set; }public string sitefacfid {  get;  set; }public string sitename {  get;  set; }public string sitetype {  get;  set; }public string owner {  get;  set; }public string ownertype {  get;  set; }public string manager {  get;  set; }public string managertype {  get;  set; }public string maintd_by {  get;  set; }public string mainttype {  get;  set; } public string shape_len {  get;  set; }
 }

For the class that will actually read the data and display it on the map, we import three libraries:

using Bing.Maps;using Windows.Storage;using Windows.UI.Popups; 

The class that reads the trail-database copies it first in the local application directory. It creates a MapShapeLayer, reads through the table-records and adds the records for the trails to the layer before it adds the entire layer to the map.

One point to call out here is that the data is stored as Well Known Text (WKT) in SQLite. The WKT has the coordinates in the order Longitude and then Latitude while Bing Maps expects them in the order Latitude and then Longitude. So we have to swap the order of the coordinates.

public async void GetTrails()
{var uri = newUri("ms-appx:///Assets/trail.db"); var file = awaitStorageFile.GetFileFromApplicationUriAsync(uri);
   var destinationFolder = ApplicationData.Current.LocalFolder;//local appdata dir
   try 
   {await  file.CopyAsync(destinationFolder); //copied application local folder}}
   }catch { }var dbpath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "trail.db");var db = new SQLite.SQLiteConnection(dbpath);var trails = db.Table<trail>();
   MapShapeLayer  shapeLayer = newMapShapeLayer();int numLocs = 0;int numTrails = 0;
   foreach (trail thisTrail in trails)
   {var wkt =  thisTrail.WKT_GEOMETRY.Replace("LINESTRING  (" , "").Replace(")", "");string[] wktArray = wkt.Split(',');LocationCollection bmPolylineLocs = newLocationCollection();for (var i = 0; i <  wktArray.Length; i++)
   { var loc = wktArray[i];var locArray = loc.Split(' ');
   bmPolylineLocs.Add(new Location(Convert.ToDouble(locArray[1]), 
   Convert.ToDouble(locArray[0])));
   numLocs  = numLocs + 1;
   }
   MapPolyline bmPolyline = newMapPolyline();
   bmPolyline.Locations = bmPolylineLocs;
   bmPolyline.Color = Windows.UI.Colors.Red;
   bmPolyline.Width = 5;
   shapeLayer.Shapes.Add(bmPolyline);
   numTrails  = numTrails + 1;
  }
  myMap.ShapeLayers.Add(shapeLayer);
  var myMsg = newMessageDialog("Loaded " + numTrails.ToString() + " with " + numLocs.ToString() + " locations" );await myMsg.ShowAsync(); 
}

Finally we add a call to this new class right after we initialize the app.

public MainPage()
{this.InitializeComponent();
  GetTrails();
} 

And that’s it. Below you see a screenshot of the trails in King County on top of Bing Maps.

Happy Coding!

WinRTSpatialDataSQLite


Viewing all articles
Browse latest Browse all 102

Trending Articles