Quantcast
Channel: Bing Developer blog
Viewing all articles
Browse latest Browse all 30

Writing Your First Bing Map App

$
0
0

With the Bing Maps Apps SDK just released, it’s time to get started writing apps using the Bing Maps platform.  The first thing you need is something to map.  I wanted to do something a little more interesting than your typical “Hello World!” app, so I chose to map the locations of the planets relative to the earth.  The necessary calculations are taken care of by the CodePlex project AAPlus.  To get started, download the AAPlus code from CodePlex, and compile it against the Silverlight runtime, or use the DLL included in the attached source project.  After you have that ready, you should set up your solution by following the steps in this post. 

Now that you’re set up and ready to go, let’s get to coding!  We’ll start by making a class that extends Microsoft.Maps.Plugins.Plugin.  The Plugin class is used to import and export functionality needed, and it also acts as the entry point for your app.  We will need to use several contracts provided by the SDK.  To get a reference to those contracts, simple create public properties on your plugin class, and decorate them with an ImportSingleAttribute, and the name of the contact to import.  For this sample, we will add the following properties to import the desired functionality.

///<summary>

/// Import the LayerManagerContract so we can add the AstronomyLayer upon activation

///</summary>     

[ImportSingle("Microsoft/LayerManagerContract", ImportLoadPolicy.Synchronous)]

publicLayerManagerContract LayerManagerContract { get; set; }

 

///<summary>

/// Import the PushpinFactoryContract so we can add standard pushpins to the map

///</summary>

[ImportSingle("Microsoft/PushpinFactoryContract", ImportLoadPolicy.Synchronous)]

publicPushpinFactoryContract PushpinFactoryContract { get; set; }

 

///<summary>

/// Import the PopupContract so we can register each entity to show a popup on hover

///</summary>

[ImportSingle("Microsoft/PopupContract", ImportLoadPolicy.Synchronous)]

publicPopupContract PopupContract { get; set; }

 

///<summary>

/// Import the map contract so we can zoom out to world view upon activation

///</summary>

[ImportSingle("Microsoft/MapContract", ImportLoadPolicy.Synchronous)]

publicMapContract MapContract { get; set; }

 

These properties will automatically be set before Initialize is called.  In Initialize, we just want to set up our primary layer.  A layer is what allows you to add items to the map, and show UI in the left pane.  A plugin can have multiple layers, but it’s more common to just have one layer per plugin, which is the case here.  Since there will only ever be one layer, we set it up in our Initialize method.

// The singleton layer that contains each of the AstronomyEntities

privateAstronomyLayer _layer;

 

///<summary>

/// Called after all the imports are populated

///</summary>

publicoverridevoid Initialize()

{

       base.Initialize();

       _layer = newAstronomyLayer(this);

}

 

Activate can be thought of as one of the entry points to your application. The other entry point is layer deserialization via permalinks, but I won’t cover that in this post.  In the Activate method, we want to add our layer or bring it to the front.  This is done by using the LayerManagerContract which we previously imported.  We also set the map view using the MapContract to show the entire world.

 

///<summary>

/// Called when the user launches the application

/// Either add the AstronomyLayer or bring it to the front, then zoom out so the entire world is visible.

///</summary>

publicoverridevoid Activate(IDictionary<string, string> activationParameters)

{

       base.Activate(activationParameters);

       if (LayerManagerContract.ContainsLayer(_layer))

       {

              LayerManagerContract.BringToFront(_layer);

       }

       else

       {

              LayerManagerContract.AddLayer(_layer);

       }

       // The the view to show the whole world

       MapContract.SetView(newLocationRect(90, -180, -90, 180));

}

 

We now need to provide an implementation of AstronomyLayer which will add each planet to the layer, and update their positions based on the simulated time.

// Add each planet to the list of enties

// Each entity in this.Entites will be rendered by Entity.Primitive on the map.

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Mercury, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Venus, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Mars, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Jupiter, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Saturn, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Uranus, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Neptune, plugin.PushpinFactoryContract));

this.Entities.Add(newAstronomyEntity(Elliptical.EllipticalObject.Pluto, plugin.PushpinFactoryContract));

      

 

 

 

An entity on a layer is a point of interest, business, location, region or other item that you want to place on the map surface.  We create a custom entity class called AstronomyEntity which holds information about which planet the entity represents, and calls the AAPluss library to find the location of the planet at a given time.

 

///<summary>

/// Represents a planet we are tracking on the map

///</summary>

publicclassAstronomyEntity : Entity

{

       ///<summary>

       /// The planet enum value

       ///</summary>

       privateElliptical.EllipticalObject _ellipticalObject;

       ///<summary>

       /// Creates a new AstronomyEntity

       ///</summary>

       ///<param name="ellipticalObject">The planet to track</param>

       ///<param name="pushpinFactory">The PushpinFactoryContract used to create pushpins</param>

       public AstronomyEntity(Elliptical.EllipticalObject ellipticalObject, PushpinFactoryContract pushpinFactory)

       {

              _ellipticalObject = ellipticalObject;

              // Create a pushpin with the first letter of the planet name in it

              // Setting the primitive is what will give the entity a visual representation

              // We can use the default constructor on Location, because we just replace the location as soon as UpdateLocation is called.

              Primitive = pushpinFactory.CreateStandardPushpin(newLocation(), _ellipticalObject.ToString().Substring(0, 1));

              // Set the entity's name to show in the popup

              Name = _ellipticalObject.ToString();

       }

 

       ///<summary>

       /// Updates the location of the entity to match where the planet would be at a given julian day.

       ///</summary>

       ///<param name="julianDay">The julian day</param>

       publicvoid UpdateLocation(double julianDay)

       {

              EllipticalPlanetaryDetails details = Elliptical.Calculate(julianDay, _ellipticalObject);

              ((PointPrimitive)Primitive).Location = newLocation(details.ApparentGeocentricLatitude, details.ApparentGeocentricLongitude);

       }

 

       ///<summary>

       /// The name of the planet

       ///</summary>

       publicstring Name { get; privateset; }

}

 

In our AstronomyEntityClass we set the Primitive to a PointPrimitive which is generated using the PushpinFactoryContract we imported.  In UpdateLocation, we set the PointPrimitive’s location to the position of the planet at the given time.  Now we just need to call UpdateLocation to get the planets to their correct location.  We add the following line to the AstronomyLayer’s constructor:

// Initialize the planet locations to their position today

       DisplayDate = DateTime.Now;

 

Then add the display date property that converts the DateTime to a Julian day, and updates each AstronomyEntity’s location.

///<summary>

/// The current date that the planets are positioned to.

///</summary>

publicDateTime DisplayDate

{

       get { return _displayDate; }

       set

       {

              _displayDate = value;

 

              DateTime utcDate = _displayDate.ToUniversalTime();

 

              Date date = newDate(utcDate.Year, utcDate.Month, utcDate.Day, true);

              double julianDay = date.Julian();

 

              foreach (AstronomyEntity entity inthis.Entities)

              {

                     entity.UpdateLocation(julianDay);

              }

       }

}

 

We now have enough code to get some pins on the map.  Go ahead and try your plugin out and you’ll see the planets placed on the map surface near the equator! 

I’ve added a few more features (noted below) to the attached sample. Download it and try it out, then try extending it further or writing your own app.

·         Animating the DisplayDate so you can watch the planets follow their path over the earth

·         Showing popups over the pushpins so you can tell the difference between Mercury and Mars

·         Showing custom UI in the left panel

Ben Lemmon – Bing Maps Developer

 

 


Viewing all articles
Browse latest Browse all 30

Trending Articles