Showing posts with label geolocation. Show all posts
Showing posts with label geolocation. Show all posts

Monday, 21 July 2014

Maps for Windows Phone 8


Introduction



Hi Everybody, 

Today I am gonna tell you some basics of Maps control and its implementation in Windows Phone. It is very easy to use Maps in windows phone application.

Objective

In this blog post I will show you

  • To add Map Control in Windows Phone App.
  • To add Image as Pushpin on Map on current location.
  • To use different cartographic modes of map.
  • To add set the view and center point of map.
  • To set the zoom level and water mark mode of map.

Requirements 

1- To add maps we only need to add a namespace Microsoft.Phone.Maps.Controls in MainPage.xaml and MainPage.xaml.cs 
and We need to check for the Map Capability as well in WMAppManifest.xml file in properties of application to allow the application to access the Maps

2- To get current location we need to add a namespace System.Device.Location in MainPage.xaml.cs to use GeoCoordinateWatcher to get the current location of user. And for accessing user location we also need to check the Location capability in WMAppManifest.xml 

3- An Image which we has to put as a pushpin on maps. 

Implementation

1- Create new project and name it. 
2- Go to solution explorer > open properties > open WMAppManifest.xml > Go to Capabilities tab and check both Maps and Location Capabilities. 

You WMAppManifest.xml file will look like this 



















3-Now Open MainPage.xaml > open toolbox > open common window controls.
4-Find Map control and drag it into your designer or place it in your Grid. 

Note: When you drag Map control in your designer it will automatically add Microsoft.Phone.Maps.Controls namespace at the top of MainPage.xaml.


Now your MainPage.xaml will look like this





5- Rename the map control and add some radio buttons normal buttons name them properly and set their content and their events to perform different tasks.

Now your MainPage.xaml designer will look like this 




















6- Now Open MainPage.xaml.cs 

You will see that all events handlers which you have created will be shown to you there. like in my MainPage.xaml.cs



















7- Now we have to add two namespaces which we have discussed in our requirements section. 



1- Microsoft.Phone.Maps.Controls (to access Map and its child controls)
2- System.Device.Location (to get current location using device GPS or location API)

Below is the snapshot of namespaces added 





















8-Now we have to add an image in our projects asset to use it as pushpin on map.
9- After adding Image again open MainPage.xaml.cs

10- Now we have to use add some code to get current location paste the code below before constructor in MainPage Class.

GeoCoordinateWatcher watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);

11- We have to provide mode of map initially and check its radio button by default to present it as selected mode

so for doing that copy the code below in constructor to assign mode of map initially.

Road.IsChecked = true;

myMap.CartographicMode = MapCartographicMode.Road;

Now your code will look like in snapshot shown below




















12- The next thing is to change mode of map using radio button so to do that just copy a single line in each radio button checked event. 

For Road

myMap.CartographicMode = MapCartographicMode.Road;

For Aerial

myMap.CartographicMode = MapCartographicMode.Aerial;

For Hybird

myMap.CartographicMode = MapCartographicMode.Hybrid;

For Terrian

myMap.CartographicMode = MapCartographicMode.Terrain;

Now your code will look like this 





















13- Now clean the solution and build it from build menu and you will see Road option will be selected by default and you can use different mode by selecting different radio buttons. 

14- Now its time to implement zoom in and zoom out functionality. It is very simple to implement zoom in and zoom out functionality for maps.

Note: Map controls is also able to zoom in, zoom out map using gestures like pinching.

15- Paste the code below in zoom in button click event

            if (myMap.ZoomLevel < 18)
            {
                myMap.ZoomLevel++;
            }

and this in zoom out button click event 

            if (myMap.ZoomLevel > 1)
            {
                myMap.ZoomLevel--;

            }


Now your MainPage.xaml.cs page will look like this 




















16- Clean the solution and build it from build menu again and Run it on you emulator or device.

17- Click the zoom in and zoom out button to change the zoom level of you map control. 

18- Now its time to get current location and add a pushpin to that location so to do that paste the code written below in add pin button click event to add image as pushpin at current location on map.


if(!watcher.Position.Location.IsUnknown)
{
       Image img = new Image()
       {
           Source = new BitmapImage(new Uri("pushpin.png", UriKind.Relative)),
           Width = 50,
           Height = 50,
           HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
           VerticalAlignment = System.Windows.VerticalAlignment.Top,
           Stretch = System.Windows.Media.Stretch.Uniform
        };
                
        MapOverlay overlay = new MapOverlay()
        {
           GeoCoordinate = new GeoCoordinate(watcher.Position.Location.Latitude, watcher.Position.Location.Longitude),
           PositionOrigin = new Point(0, 0),
           Content =  img,
               
         };
                
          MapLayer layer = new MapLayer();
          layer.Add(overlay);
          myMap.Layers.Add(layer);
            
 }
            
else
{
     MessageBox.Show("Unable to Find Current Location");

}

Your addpin_Click Event will look like this 





















19- Clean the solution and build it from Build menu and run it on emulator or device. 

20- After app launching click add pin and you will see that image will be appear on you map. Continuous tapping on image will continuous zoom the map and will take you towards your exact location. 

21-Now our next and objective is to set view and center point of map when pin is added by pressing add pin button.

22-To implement that we just need to add two lines of code at the end of click event 

myMap.SetView(new GeoCoordinate(watcher.Position.Location.Latitude, watcher.Position.Location.Longitude), 18);

Now your addpin button Click event will look like this 

















23- Now Clean the solution again, rebuild it from build menu and run it. 

24- When you application will launch, click the add pin button and map will automatically move towards you exact current location. 


Note: Use the exception handler to handle the exception in the code as I haven't but it is good practice. 

Conclusion


So here we go, we have implemented maps in phone and added image as pushpin by getting current location using Geo Coordinate Watcher, Control zoom of map and change mode of map.

The sample project is available below



Windows Mobile Professional

Tuesday, 3 June 2014

[Solved] Easiest way to Draw Route on Bing Map in Windows Store Application




INTRODUCTION



Hi everybody, 

Today I am going to show you the easiest way to draw route between two location points using Bing Maps Route API. It might be little bit lengthy for you but I am pretty sure that you will feel easy to implement it. 

But before starting let me explain the things which you need to have with you.

1- Visual Studio 2012 or later. (2013 Recommended)
2- Bing Map SDK for Windows 8 or Windows 8.1 

If you don't have download it from given link below

For Windows 8 Visual Studio 2012

For Windows 8.1 Visual Studio 2013
  

3- Bing Map Key (Credential Key)

To access Bing Map you need to create a Bing Map Credential Key. If you already have its good but if you don't have then click the given link below, login to Bing portal with your Microsoft, Hotmail or Outlook account and generate credential key by putting some information they required. 

Note: Don't tell your credential key to anybody as it is important to keep it private. 

If you have all above mentioned things you are easily able to implement Bing Maps in your windows store application. 

Now lets move toward implementing. 

1- Run the Bing Map SDK installer by doing double click on it. 
2- It will take couple of seconds to install. 
3- After installation restart your visual studio if it is already running otherwise run visual studio 2013.
4- Create new windows store (Blank App) Project and name it. 
5- In Solution Explorer right click to reference and add 

1- "Bing Maps for C#, C++ or Visual Basic"  
2- "Microsoft Visual C++ 2013 Runtime Package for windows" 

references as shown in picture below. 























6- After adding you will see a yellow warning sign on both references in solution explorer as shown in picture below. 




















7- Don't worry it is just due to addition of Visual C++ Runtime reference because some reference only allows to debug or build solution only for one architecture, either it is ARM, x86 or x64. 

So to eliminate this warning change platform from "AnyCPU" to "x86" from Build Configuration Manager and see references after closing it as shown in picture below.





















So we have added references successfully. 

8- Now open MainPage.xaml and add Map Control from toolbox and name it "map" or "myMap".





Note: The controls in Bing Map SDK will be automatically added in toolbox. So you can use them directly as explained. 

9- In above picture you see that I have left blank space at right side. It is just to add some additional controls like button to perform actions. So add button from tool box set its content to "Draw Route" and name to "drawroute" 
and create its "Click Event"

10- Now copy your Bing Map Credential Key as its the time to provide it to Bing Map control. 

So open MainPage.xaml.cs and paste the code below in its constructor

// Replace your key with it. 

map.Credentials = "<Your-Bing-Map-Key>";

Now your constructor will look like this.

 public MainPage()
 {
   
     this.InitializeComponent();

     // Replace your key with it.

     map.Credentials = "samplekeyforblog123123123";


 }

11- Build the solution and run it. You will see maps with a button on right side. 

12- Now its time to use Bing Map Route API to draw route between two points. Below is the given link of Bing Map Restful API which takes the latitude,longitude of both locations and credential key as parameter and return data in form of XML or JSON at end point. 

http://dev.virtualearth.net/REST/V1/Routes?wp.0=latitude1,longitude1&wp.1=latitude2,longitude2&key=Your_Bing_Maps_Key

13 - Now we have send request to above URL using HttpClient and get response from it.

So for that purpose I am going to create a method or function in which I will write code and at the end will call it on Button Click Event which we have created already. It is your choice to make function or not. 


First to make request we need points of two different locations so I am taking points of two different location in New York 

Paste the code given below in your MainPage.xaml.cs class and resolve HttpClient object by right clicking on it. 


string point1 = "40.782946,-73.965369";
string point2 = "40.727586,-73.992433";


public async void TraceRoute()
{

   try
   {
        string reqURL = "http://dev.virtualearth.net/REST/V1/Routes?wp.0=" + point1   + "&wp.1=" + point2 +"&key=Your_Bing_Maps_Key";


        HttpClient client = new HttpClient( );

        HttpResponseMessage response = await client.GetAsync(reqURL);

        var jsonResponse = await response.Content.ReadAsStringAsync( );
   }
   catch(Exception ex) 
   {
        Debug.WriteLine(ex.ToString());
   }
  
   finally
   {


   }


}



Now we need to add JSON parser to parse the JSON in response. You can use any parser but I would suggest you to use Newtonsoft JSON library. 

So open Nuget Package manager by right clicking on project in solution explorer and selecting Manage Nuget Packages... 

Select JSON and install it. You will see reference of Netwonsoft.Json will be added to reference automatically. as show in picture below



Now you can parse JSON using Parser but we need classes of C# against the classes of JSON so we can convert them and store them in C# classes.

So instead of writing code for classes manually we will use JSON to C# classes generator. Below is the link of online generator. 

http://www.json2csharp.com 

Just paste the link with proper parameters and click generate as shown in picture below. 


 As I already told you that credential key is private so I have erased it using blue ink. So enter the proper link and click generate. It will generate classes of C# with respect to JSON classes coming in response. But it will be uneditable .

So here is the picture of generated classes. 



Now click copy button and you will see that you will be able to copy all code. 








Now add new class named "RootObject.cs" by right clicking on project in solution explorer and add new class. 

After creating class paste all the code in it.

Now your RootObject Class will look like the code below. 


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BingMapRouteSample
{
    public class ActualEnd
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
    }

    public class ActualStart
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
    }

    public class Detail
    {
        public int compassDegrees { get; set; }
        public List<int> endPathIndices { get; set; }
        public List<string> locationCodes { get; set; }
        public string maneuverType { get; set; }
        public string mode { get; set; }
        public List<string> names { get; set; }
        public string roadType { get; set; }
        public List<int> startPathIndices { get; set; }
    }

    public class Instruction
    {
        public object formattedText { get; set; }
        public string maneuverType { get; set; }
        public string text { get; set; }
    }

    public class ManeuverPoint
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
    }

    public class Warning
    {
        public string origin { get; set; }
        public string severity { get; set; }
        public string text { get; set; }
        public string to { get; set; }
        public string warningType { get; set; }
    }

    public class Hint
    {
        public object hintType { get; set; }
        public string text { get; set; }
    }

    public class ItineraryItem
    {
        public string compassDirection { get; set; }
        public List<Detail> details { get; set; }
        public string exit { get; set; }
        public string iconType { get; set; }
        public Instruction instruction { get; set; }
        public ManeuverPoint maneuverPoint { get; set; }
        public string sideOfStreet { get; set; }
        public string tollZone { get; set; }
        public string towardsRoadName { get; set; }
        public string transitTerminus { get; set; }
        public double travelDistance { get; set; }
        public int travelDuration { get; set; }
        public string travelMode { get; set; }
        public List<string> signs { get; set; }
        public List<Warning> warnings { get; set; }
        public List<Hint> hints { get; set; }
    }

    public class EndWaypoint
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
        public string description { get; set; }
        public bool isVia { get; set; }
        public string locationIdentifier { get; set; }
        public int routePathIndex { get; set; }
    }

    public class StartWaypoint
    {
        public string type { get; set; }
        public List<double> coordinates { get; set; }
        public string description { get; set; }
        public bool isVia { get; set; }
        public string locationIdentifier { get; set; }
        public int routePathIndex { get; set; }
    }

    public class RouteSubLeg
    {
        public EndWaypoint endWaypoint { get; set; }
        public StartWaypoint startWaypoint { get; set; }
        public double travelDistance { get; set; }
        public int travelDuration { get; set; }
    }

    public class RouteLeg
    {
        public ActualEnd actualEnd { get; set; }
        public ActualStart actualStart { get; set; }
        public List<object> alternateVias { get; set; }
        public int cost { get; set; }
        public string description { get; set; }
        public List<ItineraryItem> itineraryItems { get; set; }
        public string routeRegion { get; set; }
        public List<RouteSubLeg> routeSubLegs { get; set; }
        public double travelDistance { get; set; }
        public int travelDuration { get; set; }
    }

    public class Resource
    {
        public string __type { get; set; }
        public List<double> bbox { get; set; }
        public string id { get; set; }
        public string distanceUnit { get; set; }
        public string durationUnit { get; set; }
        public List<RouteLeg> routeLegs { get; set; }
        public double travelDistance { get; set; }
        public int travelDuration { get; set; }
        public int travelDurationTraffic { get; set; }
    }

    public class ResourceSet
    {
        public int estimatedTotal { get; set; }
        public List<Resource> resources { get; set; }
    }

    public class RootObject
    {
        public string authenticationResultCode { get; set; }
        public string brandLogoUri { get; set; }
        public string copyright { get; set; }
        public List<ResourceSet> resourceSets { get; set; }
        public int statusCode { get; set; }
        public string statusDescription { get; set; }
        public string traceId { get; set; }
    }

}





















So now your RootObject Class is ready to get data coming in the form of JSON from Bing Maps Route API.

Now come again in MainPage.xaml.cs and after this line declare and Initialize the List of ResourceSet  and ItineraryItem Class present in RootObject.cs before the constructor of MainPage

List<ResourceSet> resourceSet = new List<ResourceSet>( );

List<ItineraryItem> items = new List<ItineraryItem>( );
       
Declare List of Location Class which will hold the location points 

List<Location> loc = new List<Location>( );

Reslove "Location" it by right clicking on it. 

Declare the Object or Resource class

Resource resource;

Now come to TraceRoute Method/Function and paste given code below 

// Parsing JSON Response


 var rootObject = JsonConvert.DeserializeObject<RootObject>(jsonResponse);


 foreach (ResourceSet set in rootObject.resourceSets)
 {
        resourceSet.Add(set);

                
 }

loc.Clear();
            
resource = resourceSet[0].resources[0];
            
items = resource.routeLegs[0].itineraryItems;
            
// Colleting location points to draw route got in response. 

 foreach(ItineraryItem item in items)
            
 {

     loc.Add(new Location() { Latitude = item.maneuverPoint.coordinates[0],        Longitude = item.maneuverPoint.coordinates[1] });
                
            
 }

// Declaring Object of MapPolyline to Draw Route

            MapPolyline line;
            line = new MapPolyline();

// Defining color to Polyline that is Red you can give any color to it. 


            line.Color = Colors.Red;

// Defining width of Polyline so it can easily be visible to naked eye. 
            
            line.Width = 5;

// Giving Collection of location points to Map Polyline     

            foreach(Location l in loc)

            {
                line.Locations.Add(l);
            }
            
// Defining Map Shape layer Object to add Polyline shape to it. 

            MapShapeLayer shapeLayer = new MapShapeLayer();

// Adding line to Shape Layer 

            shapeLayer.Shapes.Add(line);

// Adding Shape Layer to Map

            map.ShapeLayers.Add(shapeLayer);

// Calculating Mid between both location to set center of Map
            int mid;
            
            if(loc.Count%2==0)
            {
                mid = loc.Count / 2;
            }
            else
            {
                mid = (loc.Count + 1) / 2; 
            }

            map.Center = loc[mid];

            map.ZoomLevel = 14;

//------------------------------------------------------------------------------------------------------

Now your MainPage.xaml Class will look like this.  

using Bing.Maps;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace BingMapRouteSample
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {

        List<ResourceSet> resourceSet = new List<ResourceSet>();
        Resource resource;
        List<ItineraryItem> items = new List<ItineraryItem>();
        List<Location> loc = new List<Location>();
        public MainPage()
        {
            this.InitializeComponent();
            map.Credentials = "Your_Bing_Maps_Key";
            progress.Visibility = Visibility.Collapsed;
            
        }

        string point1 = "40.782946,-73.965369";
        string point2 = "40.727586,-73.992433";
       

        public async void TraceRoute()
        {
            try
            {

           
            string reqURL = "http://dev.virtualearth.net/REST/V1/Routes?wp.0=" + point1 + "&wp.1=" + point2 + "&key=Your_Bing_Maps_Key";


            HttpClient client = new HttpClient();

            HttpResponseMessage response = await client.GetAsync(reqURL);

            var jsonResponse = await response.Content.ReadAsStringAsync();

            // Parsing JSON Response

            var rootObject = JsonConvert.DeserializeObject<RootObject>(jsonResponse);


            foreach (ResourceSet set in rootObject.resourceSets)
           {
                   resourceSet.Add(set);

                
           }

            loc.Clear();

            resource = resourceSet[0].resources[0];

            items = resource.routeLegs[0].itineraryItems;

            // Colleting location points to draw route got in response. 

            foreach (ItineraryItem item in items)
            {

                loc.Add(new Location() { Latitude = item.maneuverPoint.coordinates[0], Longitude = item.maneuverPoint.coordinates[1] });


            }

            // Declaring Object of MapPolyline to Draw Route

            MapPolyline line;
            line = new MapPolyline();

            // Defining color to Polyline that is Red you can give any color to it. 


            line.Color = Colors.Red;

            // Defining width of Polyline so it can easily be visible to naked eye. 

            line.Width = 5;

            // Giving Collection of location points to Map Polyline     

            foreach (Location l in loc)
            {
                line.Locations.Add(l);
            }

            // Defining Map Shape layer Object to add Polyline shape to it. 

            MapShapeLayer shapeLayer = new MapShapeLayer();

            // Adding line to Shape Layer 

            shapeLayer.Shapes.Add(line);

            // Adding Shape Layer to Map

            map.ShapeLayers.Add(shapeLayer);

            // Calculating Mid between both location to set center of Map
            int mid;

            if (loc.Count % 2 == 0)
            {
                mid = loc.Count / 2;
            }
            else
            {
                mid = (loc.Count + 1) / 2;
            }

            map.Center = loc[mid];
            map.ZoomLevel = 14;


            }
            catch (Exception)
            {

                Debug.WriteLine(ex.ToString( ));
               
            }
            finally
            {

                drawroute.isEnabled = true;
                progress.Visibility = Visibility.Collapsed;

            }
        }


        private void drawroute_Click(object sender, RoutedEventArgs e)
        {

                drawroute.isEnabled = false;
                progress.Visibility = Visibility.Visible;

               TraceRoute( );

        }
    }
}

Now there is only one thing remaining. You need to add progress ring to check response (Its Optional) and call TraceRoute method/function in drawroute button click event.

Now rebuild the solution and run it. 

You will see the screen like this. 























Click the Draw Route button it will take couple of seconds and draw route between two location points which you we have assigned to it. 

The location points in this sample are of New York Central Park and Merchant House Museum respectively.

After getting response from ROUTE API you will see the result like this. 























So now you are done with drawing driving route path on Bing Maps from one location to another. 

There are many other things which can easily be done via Bing Map ROUTE API, Location API, and etc etc. 

Some of the key features are below 

1- You can easily put your current location by using GeoLocation Class.
2- You can easily add push pins to starting and ending points. 
3- You can easily find the alternative route if there is traffic on suggested route. 
4- You can easily find the distance and estimated time to reach between two location points.

All above mentioned features will be covered in depth from beginner to advance level in future.

If there is any query you can simply email me or write comment I will follow up with you. 

Download sample from here  

Thanks

BR, 
Mudassir






Windows Mobile Professional