Silver Splines

In order to pass the last exam left and graduate from the University of Plovdiv I had to create a small program that draws some splines. I picked Bézier curves as they seemed to be one of the simplest kind of parametric curves.

My friend Stoiko researched the algorithms for drawing Bézier curves and implemented one of them in C and OpenGL. After a lot of explanations I was able to understand it and port it to .NET. As it seems this algorithm is an implementation of the de Casteljau's algorithm used in conjuction with linear interpolation to draw the curve.

At first I implemented it as a Windows Forms application but in order to make it more useful to my professor I decided to port the program to Silverlight so it can be used from the course website without downloading any executables. The first step was to separate the algorithm from the drawing and user interface code. This is why I created the class Bezier which has a single public method that looks like this:

public static IEnumerable<Point> GetCurvePoints(List<Point> controlPoints, double step)
{
//make sure the spline goes through the first point
yield return controlPoints[0];

for (double t = step; t <= 1; t += step)
{
yield return LerpSpline(controlPoints, t);
}

//make sure the spline goes through the last point
yield return controlPoints[controlPoints.Count - 1];
}

Just pass in the control points and you will get the points for the spline. The problem is that the LerpSpline method (which is private) does not return the first and the last point which are in fact the first and last control points. I believe that if we need to be mathematically correct the first and the last points are not considered control points but the beginning and the end of the curve. However in order to draw the curve correctly I needed this points. Here you can see how elegantly the yield statement fits in the implementation. There are no checks like:

if(firstCall)
{
firstCall = false;
return controlPoints[0];
}

There is just one logical flow as if we were building a list. This implementation is also lazy and will generate points on demand although my client code does not make use of this. Another cool thing is that the algorithm is highly parallelizable so if we replace the for loop with the Parallel.For from the Task Parallel Library it will make use of multicore processors without any other changes.

This is my first Silverlight application and it caught me by surprise several times. At first I was developing a WPF browser application thinking that it was a Silverlight application. How was I to know that an application that uses XAML, matches the Silverlight documentation and runs in a browser is not Silverlight? Go ahead, laugh at me! Then I had to deal with the lack of double click and right click events in Silverlight. I believe that Microsoft went a bit over the top with the portability aspect here. The explanation is that some platforms (phones?) may not have easy way to right click. There are hacks to implement both double click and right click. Come on Microsoft why do you make us do it? If we do not take care of different clients they will be screwed anyway. Just give us some property telling us if the platform supports right click!

Unlike desktop applications drawing in Silverlight is not done using a Graphics object. Instead you define elements which are added to a control tree much like the HTML DOM. There are elements for curves, shapes, etc. I used the Polyline shape to draw the curve as a series of small lines. If you create a long enough curve (or edit the value of the step in the code) you can actually see the lines. I had to define several brushes for the different colors because the Silverlight runtime does not contain the predefined ones that you can use in the full .NET Framework. Many method overloads are also missing because the size of the runtime download is important for the end users so only the most important things are in.

So here is the actual application. You can use Shift + click to add a control point, Ctrl + click to remove a control point and drag points around. By the way Silverlight 3.0 was released today so I quickly ported the application and although it does not use any of the new features you need to have the latest Silverlight runtime. It is fast and painless download and install experience which takes less than a minute and does not require browser restart.

I hope that I will find the time to extend the application with features or someone else will contribute something. If you are interested in contributing or just looking at the code you can download it here. From mathematical point of view one can contribute by adding other kinds of curves or features for splitting the curve. From the point of view of software development one can add GUI for controlling the step, features for drawing multiple curves in different colors, displaying coordinates of the control points, saving and loading from file, out of browser installation (Hooray for Silverlight 3.0!) and many more.

This application is a kind of proof of my theory about the strategic value of Silverlight. While Microsoft would undoubtedly be happy if Silverlight dethroned Flash in the RIA world I doubt they expect it. However Silverlight makes .NET more complete platform. If you are a .NET developer and you need RIA functionality you can just go ahead and use Silverlight using your current skill set. If I had to port this application to Flash in order to make a RIA version I would have stopped with the desktop version. Similarly if a company needs some RIA functionality in a .NET project it can use Silverlight. In the past it would need to hire a Flash developer just for a small part of the project which would cost more. Now that we have Silverlight we (.NET developers) are kind of self-sufficient. In my opinion the motivation behind JavaFX is pretty much the same.

Thanks a lot to Stoiko for figuring out how to draw Bézier curves programatically and to a guy known by the nickname dragonshed in the ##csharp channel on irc.freenode.org who helped me with some of the Silverlight issues.

Oh, in case anyone was wondering Bézier curves and splines in general are used in vector graphics tools to represent free-form smooth curves and more importantly for defining paths for animated objects in Flash and Silverlight itself.

Posted by:   Stilgar
04:15 11.07.2009

Posted by   wqw (Unregistered)   on   15:12 11.07.2009

No restart my ass! After install the setup advised me to refresh current page but then the browser *insisted* on being restarted. Go figure!

Posted by   Stilgar   on   15:22 11.07.2009

Hmm which browser?

Posted by   Stilgar   on   15:37 11.07.2009

As it seems Firefox actually requires a browser restart. Strange I thought I tested this once...

Posted by   Ubuntu (Unregistered)   on   11:31 14.07.2009

I'm not able to run your example because of the stupid silverlight. It has no linux version:

Install Silverlight

One moment, please, while the current Silverlight installation status is determined...
Microsoft Silverlight may not be supported on your computer's hardware or operating system.

Posted by   Stilgar   on   11:41 14.07.2009

No, it is not supported. It won't run on DOS either. Oh and btw you need a computer. Don't try to run it on your clock.

To be honest you can download the Moonlight source code and try to compile it. It may run or it may not.

Posted by   JOKe (Unregistered)   on   14:14 20.07.2009

Firefox 3.5 doesnt require restart.
Chrome 3.xxxx dev version require restart.

Posted by   jeffpang (Unregistered)   on   17:10 13.11.2009

Very nice. Saved me and my team days of development work. Thanks!

Posted by   Stilgar   on   17:42 13.11.2009

Nice. I didn't believe this could help anyone for anything but homework. What is your team working on if you don't mind me asking?

Post as: