Click here to Skip to main content
Click here to Skip to main content

Bézier Curves in Bing Silverlight Maps

, 30 Aug 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Connecting geographical locations on Bing Maps with Bézier curves

Introduction

Bing Maps Silverlight Control library has a MapPolyline class for showing connected points on the map. I wanted my points to be smoothly connected, but there wasn't out-of-the-box support so I developed a custom control deriving from MapShapeBase [^] class.

Bézier Curve on map.

Background

Every developer who messed with Expression Blend or Gimp long enough knows by experimentation how a Bézier curve behaves. Basically a cubic Bézier curve has an initial point (P1), two control points (B1, B2) and a final point (P2).

Bézier Curve

The formula that defines a cubic Bézier curve is:

P(t) = (1-t)<sup>3</sup>P<sub>1</sub> + 3(1-t)<sup>2</sup>tB<sub>1</sub> + 3(1-t)t<sup>2</sup>B<sub>2</sub> + t<sup>3</sup>P<sub>2</sub>

where t is in the interval [0,1]. Terms multiplying P1, B1, B2, P2 are called the basis functions for the cubic Bézier. Our points determine how much of these basis functions the curve contains.

Basis Functions for Cubic Bézier Curve

The thing is we need to calculate coordinates of the control points such that our points of interest are on the curve.

Polyline, Bézier, Catmull-Rom

So how can we calculate these control points? After researching (read Googling), I have landed on cardinal splines [^] and Catmull-Rom splines [^] . It appears that every control point of a Catmull-Rom spline is on the curve and it is also a Bézier curve which means we can use it as PathGeometry [^] with a Silverlight Path object.

Calculating Control Points

If we rewrite formulas from the cardinal splines [^] page as the following, we can easily calculate control points.

Derivative:

P'<sub>0</sub> = (P<sub>1</sub> - P<sub>0</sub>) / a
P'<sub>i</sub> = (P<sub>i+1</sub> - P<sub>i-1</sub>) / a   where  i in [1, n-1]
P'<sub>n</sub> = (P<sub>n</sub> - P<sub>n-1</sub>) / a

Control Points:

B1<sub>i</sub> = P<sub>i</sub> + P'<sub>i</sub> / 3
B2<sub>i</sub> = P<sub>i+1</sub> - P'<sub>i+1</sub> / 3
Fitted Bézier with Control Points Visible.

Using the Code

The method that calculates the Bézier Points is as follows. GetB1 and GetB2 are straight forward implementations of the aforementioned formulas.

    private PointCollection GetBezierPoints(PointCollection pts, double tension)
        {
            PointCollection ret = new PointCollection();

            for (int i = 0; i < pts.Count; i++)
            {
                // for first point append as is.
                if (i == 0)
                {
                    ret.Add(pts[0]);
                    continue;
                }

                // for each point except first and last get B1, B2. next point. 
                // Last point do not have a next point.
                ret.Add(GetB1(pts, i - 1, tension));
                ret.Add(GetB2(pts, i - 1, tension));
                ret.Add(pts[i]);
            }

            return ret;
        }

To use the PointCollection returned from GetBezierPoints method in Silverlight, we need to build a Path with BezierSegments in it.

private PathFigure GetBezierSegments(PointCollection pts, double tension)
    {
        PathFigure ret = new PathFigure();
        ret.Segments.Clear();
        ret.IsClosed = false;

        var bzPoints = GetBezierPoints(_projectedPoints, tension);

        // First point is the starting point.
        ret.StartPoint = bzPoints[0];

        for (int i = 1; i < bzPoints.Count; i += 3)
        {
            ret.Segments.Add(new BezierSegment()
            {
                Point1 = bzPoints[i],       // B1 control point.
                Point2 = bzPoints[i + 1],   // B2 control point.
                Point3 = bzPoints[i + 2]    // P2 start / end point.
            });
        }

        return ret;
    }

And use this PathFigure in the MapBezier as:

// Create a new PathGeometry.
var pGeo = new PathGeometry();

// Add the Bezier PathFigure to the PathGeometry.
pGeo.Figures.Add(GetBezierSegments(_projectedPoints, Tension));

// Set data of the Path to the created PathGeometry.
((Path)EncapsulatedShape).Data = pGeo;

You can use the MapBezier class just like MapPolyline and MapPolygon classes in your silverlight XAML file. See the attached sample for an example Silverlight application.

<m:Map x:Name="myMap" CredentialsProvider="***">
    <m:MapLayer x:Name="layerDurak" >
         <local:MapBezier Tension="2" x:Name="plDurakGidis" Stroke="Orange" 
    StrokeThickness="3" Opacity=".6" Locations="{Binding MyLocations, Mode=OneWay}" />
    </m:MapLayer>
</m:Map>

Note: Bing Maps Silverlight SDK [^] is needed for compiling the sample application.

Points of Interest

It was fun messing with the Bing Maps Silverlight Control toolkit and I hope MapBezier is what you are looking for.

History

  • Initial article. 30.08.2010 - This article is also available at my blog.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Kerem Kat
Software Developer
Turkey Turkey
No Biography provided
Follow on   LinkedIn

Comments and Discussions

 
GeneralFascinating but ... Pinmembervictorbos7-Sep-10 6:23 
As I enjoy maps and vector graphics, and given my new-found curiosity about Bing Maps, I was quite excited to discover your article. I downloaded (a) your project and (b) the Silverlight SDK you mentioned. BUT, when I open your project in VS2010 I get two errors:
 
1: The referenced component 'Microsoft.Maps.MapControl' could not be found.
2: The referenced component 'Microsoft.Maps.MapControl.Common' could not be found.
 
I tried locating the two controls but VS2010 (Add References | .Net | Filtered to: Silverlight 4) does not reveal any components with similar names. Not being the swifted guy in the world, I am a little confused!! Any suggestions where I missed something?
GeneralRe: Fascinating but ... PinmemberKerem Kat9-Sep-10 4:44 
GeneralGood Stuff PinmemberMember 45654332-Sep-10 9:12 
GeneralMy vote of 5 PinmemberMarcelo Ricardo de Oliveira31-Aug-10 9:27 
GeneralRe: My vote of 5 PinmemberKerem Kat3-Oct-10 6:00 
GeneralI like it and gave at 5 PinmvpSacha Barber31-Aug-10 5:03 
GeneralRe: I like it and gave at 5 PinmemberKerem Kat31-Aug-10 8:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141220.1 | Last Updated 30 Aug 2010
Article Copyright 2010 by Kerem Kat
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid