SyntaxHighlighter

Monday, June 13, 2011

The Lonely WAIF Project

The lonely waif project is a animation library written entirely in F#.
I'll just take a brief moment to explain the name. If you look up waif
on Wikipedia you'll find  that it's more or less defined as such:
waif (from the Old French guaif, stray beast)[1] is a living creature removed,
by hardship, loss or other helpless circumstance, from his original surroundings.
I like to think of this projects original surroundings as the C# version
and well, its lonely because I'm currently the only contributor and user. :)

At this point you're probably wondering a few things...
a) Why an animation library in F#?
b) Why not just use the C# library from F#?

Well, I already use the library in my C#/F# polyglot project at work.
It's nice and all, but I'm trying to reduce my code footprint.
And unfortunately this mixed support is not helping very much.
Besides, I'm working on a really clean and simple visualization
component which will allow me to visualize time series, having a way
to animate the interactivity of that time series would be even nicer.
Which brings us to the main reason why I'm doing it in F#.
Trying off the shelf reporting controls is nice until you want that
extra level of sophistication only to find yourself stuck. I really
want that google charting level of sophistication but I know I will
not come close to getting it with componentone charting controls.
After all, google is not using off the shelf charting controls. :)

Now that we understand the name of this library and the
motivation behind it, let's take a look at it.








If you head over to google code where the project is hosted you'll
find two F# projects.
1) The animation library
2) WPF test application which uses the library

Let's take a look at one of the sample snippets.

- Say you have a window with a simple rectangle shape on it
and you want to animate the rotation of the angle.
- Or maybe you want to simply move it across the screen.

Here's what the code might look like :

let uri = new System.Uri("/AnimationTest;component/MainView.xaml",
                                           UriKind.Relative)
let window =  Application.LoadComponent(uri) :?> Window
let animator = new Animator() // animation time!
(* Grab UIElements *)
let rect = window.FindName("rectangle") :?> Rectangle


(* ===== Rotate Rectangle ===== *)
let rtf = castAs(rect.RenderTransform).Children.[2] :?> RotateTransform
 (* Angle *)
(* DependencyObject - rotate transform *)
animator.AnimateDouble(rtf,
(* DependencyProperty *)
    RotateTransform.AngleProperty,
(* EventHandler - callback function *)
    null,
(* Duration - in milliseconds *)
    250.0,
(* Acceleration *)
   None,
(* Deceleration *) 
   None,
(* From *)
   None,
(* To *) 
   Some(90.0)) |> ignore)

(* ===== Translate Rectangle ===== *)
let ttf = castAs(rect.RenderTransform).Children.[0] :?> TranslateTransform
(* Y Axis *)
animator.AnimateDouble(ttf,
   TranslateTransform.YProperty,
   null,250.0,None,None,None,Some(90.0)) |> ignore)

There are a few more samples in the sample application but that's really
all there is to it. I use the C# library all the time for creating custom
controls and widgets to use in my WPF applications.
Now I get to use it in F#! Over time I'll be adding more to the library
so it has total parity with the C# library.

Enjoy!

Tuesday, June 7, 2011

Simple Data Visualization using F# & WPF/Silverlight

For several weeks now I've been getting back into Data Visualization
projects (on the weekends). I've also gone back to basics by re-reading
Ben Fry's Visualizing Data while sketching in Processing. Re-gaining the
data visualization perspective has helped me out recently in my WPF
application that I'm working on (day job). The scenario was quite simple
and I could have used any standard WPF control to solve the problem
but I wanted to do something that convey'd the data in a more obvious
way. So I went looking around the web for inspiration and came across
the following flowing data post.

 














The visualization above is (in my opinion) a great way to compare two
values of information to one another with out using standard controls.
In the above situation the two values are likes vs dislikes. Straight
away we can get a sense (as a end user) of how many people like a
video vs dislike a video based on color. In my WPF application I
need to do something similar. I need to show how many 3D geometric
objects on a particular 3D Model are being used in other parts
of the system vs how many 3D objects are not being used at all in other
parts of the system. So I thought to myself, how might I be able to pull
off the above visualization in WPF? I fired up blend and started sketching.
After about thirty minutes I came up with a similar yet simpler visualization.


























You can probably tell from the blend screen shots above
that we can use a simple gradient color to represent the
two values that we need to visualize for the user to
compare. So I tried creating a border with a large corner
radius of about 90 to get a circle that I can apply a border
gradient color to. Unfortunately I wasn't able to get the
effect that I wanted so I tried something simpler below
the border. I created a simple rectangle and applied the
gradient color to the fill of the rectangle. This allowed me
to visually pull off the similar effect in the flowing data post!
Now that I have a visual way to do this I just need to apply
the data so that the rectangle gradient changes dynamically.

#I "path to assemblies below (here)"

#r "PresentationFramework.dll"
#r "WindowsBase.dll"
#r "PresentationCore.dll"

open System
open System.Windows
open System.Windows.Shapes
open System.Windows.Media
open System.Windows.Controls

let r = new Random()
let total_count_of_all_objects = 4556

(* Helper functions - remember the (: byte) & (: float)
   is just annotation for the return type of the function *)
let to_byte (v: int) : byte = Convert.ToByte(v)
let to_float (v: int) : float = Convert.ToDouble(v)

let to_color (r: int) (g: int) (b: int) : Color =
    Color.FromRgb(r |> to_byte, g |> to_byte, b |> to_byte)


(* Tuple to hold total number of objects used in the 3D Model
(random) and total number of objects in the 3D Model *)
let used_total = (r.Next(2000,4556),total_count_of_all_objects)

(* Calculate the number of objects used relative to the total *)
let simulation_result (used_total: int * int): float =
    let used,total = used_total
    used * 100 / total |> to_float



let construct_visualization (used_total: int * int): Grid =
    (* Get simulation result and convert to value between 0 and 1
       for the gradient stops to understand *)
    let v = simulation_result used_total / 100.0
    let actual_color =  to_color 3 129 51
    let total_color =  to_color 255 5 5
    let start_point = new Point(0.0, -0.925) //gradient start point
    let end_point = new Point(1.0, - 0.893) // gradient end point
    let brush = new LinearGradientBrush(actual_color, total_color, start_point, end_point)
    let gradientStopColor1 = new GradientStop(actual_color, v)
    let gradientStopColor2 = new GradientStop(total_color, v)
    brush.GradientStops.Add gradientStopColor1
    brush.GradientStops.Add gradientStopColor2
 
    let rect = new Rectangle(Fill=brush)
    let grd = new Grid(Width=260.0, Height=30.0,
                       HorizontalAlignment=HorizontalAlignment.Center,
                       VerticalAlignment=VerticalAlignment.Center)

    grd.Children.Add rect |> ignore
    grd
                     
let shell = new Window(Width=300.0,Height=300.0)
let viz = construct_visualization used_total
shell.Content <- viz

[] ignore <| (new Application()).Run shell


It's worth noting that even though this was shown as a WPF sample it
could easily be applied to Silverlight, which is why I included it in the title
of the post. =)


F# is great for prototyping and executing ideas! 
Just seeing something on the web and hopping right
into Blend/VS2010 to execute an idea in about an 
hour is why I love this language on top of this platform.


Until next time...
-Develop with passion