23 July 2011

Speed and distance calculation extension methods for Windows Phone 7

Upgrading stuff to from Windows Phone 7 to “Mango” is sometimes like cleaning your desk drawer before going on a holiday – you stumble upon stuff you forgot it was even there. For the ‘game engine’ I made for Catch’em Birds I created a few very handy extension methods for calculating speed and distance, which I would like to share with the rest of the community:

using System;
#if WINDOWS_PHONE
using System.Windows;
#else
using System.Drawing;
using System.Windows;
#endif


namespace Wp7nl.Utilities
{
  public static class PointExtensions
  {
    /// <summary>
    /// Distances from point 1 to point 2
    /// </summary>
    /// <param name="p1">The first point.</param>
    /// <param name="p2">The second point.</param>
    /// <returns></returns>
    public static double DistanceFrom(this Point p1, Point p2)
    {
      var dX = p2.X - p1.X;
      var dY = p2.Y - p1.Y;
      return Math.Sqrt(dX * dX + dY * dY);
    }

    /// <summary>
    /// Calculates the speed in pixels per second
    /// </summary>
    /// <param name="p1">The first point.</param>
    /// <param name="p2">The second point.</param>
    /// <param name="duration">The duration</param>
    /// <returns>Speed in pixels per second</returns>
    public static double CalculateSpeed(this Point p1, Point p2, Duration duration)
    {
      return p1.DistanceFrom(p2) / duration.TimeSpan.TotalSeconds;
    }

    /// <summary>
    /// Calculates the duration given a distance and a speed.
    /// </summary>
    /// <param name="p1">The first point.</param>
    /// <param name="p2">The second point.</param>
    /// <param name="speed">The speed in pixels per second.</param>
    /// <returns>Time it takes to get from p1 to p2</returns>
    public static Duration CalculateDuration(this Point p1, Point p2, double speed)
    {
      return new Duration(TimeSpan.FromSeconds(p1.DistanceFrom(p2) / speed));
    }
  }
}

I will discuss these in a not quite logical order:

  • The first method is of course good ole' Pythagoras caught in an extension method, basically there as a helper method for the other two.
  • The third method is the one I used most: given that my object needs to move from p1 to p2 with a given speed in pixels per second, what’s the Duration I need to apply to my Storyboard?
  • The second one is the inverse – given the fact that on object was moving from p1 to p2 in duration “duration”, calculate its speed in pixels per second.

As you can see at the #if on top it also work on System.Drawing.Points under full .NET 4.0. Maybe these methods are useful there as well, I put that only there to facilitate some unit tests.

All these methods are part of the wp7nl CodePlex library – or at least the will so at the upcoming Mango release.

Update: thanks to Rene Schulte for pointing out to me that my original DistanceFrom method using Math.Pow is very slow compared to simple multiplications. Rene is a Silverlight MVP from Dresden, Germany and has some very nice Point extension methods on his blog “Kodierer” as well - in English, don’t worry ;-)

No comments: