On the heels of Google IO – playing with HTML5 and F# web services
02 Jun 2009 04:18 PM UncategorizedI went to Google IO this past week, and they had a whole long spiel about the wonders of html5. Well... i've gotta admit - some of the stuff looked kinda cool, so i decided to play with it. I wrote a web serivice in bistro that returned a list of fibonacci numbers, and then a corresponding page that requested that list through jquery, and generated a tiling and then drew a fibonacci spiral over it:
The code for both was remarkably simple. On the service side, all i had to do was define a recursive function for generating fibonacci numbers (yes, it's not tail-recursive, i know, but i was lazy), and a simple controller for binding to the appropriate REST method:
if (rem = 0) then [a]
else [a] @ fibonacci b (a+b) (rem-1)
[<ReflectedDefinition>]
[<Bind("get /fib/{numbers}")>]
[<RenderWith(@"Templates\fibResult.django")>]
let fibCt (ctx: IExecutionContext) numbers =
let fibNbrs = fibonacci 0 1 numbers
fibNbrs
Prest-o change-o, we're done.
Now for the javascript. The majority of the code here is a rather weak attempt to figure out the tiling. My math skillZ are kinda rusty, and i know i should have defined objects for the squares, and dealt with alternating corners that way, but this did the trick:
var url = "/fib/" + $("input[name=iterations]").val();
$.get(url, function(data) { render(data); }, "xml");
}
function render(data) {
var drawFactor = parseInt($("input[name=magnification]").val());
var canvas = $("#golden").get(0);
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = "#CCCC99";
ctx.fillStyle = "#FFFFEE";
var x = canvas.width / 2;
var y = canvas.height / 2;
var offsetX = 0;
var offsetY = 0;
var arcX = x, arcY = y;
var elems = $(data).find("number");
if (drawFactor == 0)
drawFactor = Math.min(canvas.width, canvas.height) / (2 * (parseInt($(elems.get(elems.length - 1)).text()) + 1));
for (var i = 1; i < elems.length; i++) {
ctx.strokeStyle = "#CCCC99";
ctx.fillStyle = "#FFFFEE";
var last = elems.get(i - 1);
var current = elems.get(i);
var num = parseInt($(current).text()) * drawFactor;
var lastNum = parseInt($(last).text()) * drawFactor;
var idx = i-2;
var startAngle, endAngle = 0;
switch (idx % 4) {
case 0:
x += lastNum;
y += lastNum - num;
arcX = x, arcY = y;
startAngle = Math.PI / 2;
endAngle = Math.PI * 2;
break;
case 1:
x -= num - lastNum;
y -= num;
arcX = x, arcY = y + num;
startAngle = Math.PI * 2;
endAngle = Math.PI * 3 / 2;
break;
case 2:
x -= num;
arcX = x + num, arcY = y + num;
startAngle = Math.PI * 3 / 2;
endAngle = Math.PI;
break;
case 3:
y += lastNum;
arcX = x + num, arcY = y;
startAngle = Math.PI;
endAngle = Math.PI / 2;
break;
}
ctx.strokeRect(x, y, num, num);
ctx.fillRect(x, y, num, num);
if (idx < 0)
continue;
ctx.strokeStyle = "gray";
ctx.beginPath();
ctx.arc(arcX, arcY, num, startAngle, endAngle, true);
ctx.stroke();
}
}
Pretty straightforward, really. Notice the lack of work on getting the F# service up and running - just 4 lines of code and you're good.
I'm stoked.
I threw the whole "project" up under bistro samples - you can find the info here under the Examples tree.

Trying to convert this to C#, but my numbers arent quite right:
//
var x = canvas.ActualWidth / 2;
var y = canvas.ActualHeight / 2;
var arcX = x;
var arcY = y;
// just hard code them
int[] FibonacciValues = {0,1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233};
var drawFactor = Math.Min(canvas.ActualWidth, canvas.ActualHeight) / (2 * (FibonacciValues[FibonacciValues.Length -1])) + 1;
for (var i = 1; i < FibonacciValues.Length; i++)
{
var last = FibonacciValues[i - 1];
var current = FibonacciValues[i];
var num = current * drawFactor;
var lastNum = last * drawFactor;
var idx = i – 2;
var startAngle = 0.0;
var endAngle = 0.0;
switch (idx % 4)
{
case 0:
x += lastNum;
y += lastNum – num;
arcX = x;
arcY = y;
startAngle = Math.PI / 2;
endAngle = Math.PI * 2;
break;
case 1:
x -= num – lastNum;
y -= num;
arcX = x;
arcY = y + num;
startAngle = Math.PI * 2;
endAngle = Math.PI * 3 / 2;
break;
case 2:
x -= num;
arcX = x + num;
arcY = y + num;
startAngle = Math.PI * 3 / 2;
endAngle = Math.PI;
break;
case 3:
y += lastNum;
arcX = x + num;
arcY = y;
startAngle = Math.PI;
endAngle = Math.PI / 2;
break;
}
if (idx < 0)
continue;
}
any idea of where I went wrong?
what do you mean your numbers are wrong? the tilings? assuming you just copied the source (no reason not to – basic js should be the same as c#), then the only thing i can think of is maybe it’s expecting degrees instead of radians?
Thanks for the reply.
I’m not actually plotting the values on screen yet. I’m only drawing the tiles out by hand so see if my conversion is correct. The values will be plotted on a WPF canvas and I’m still searching for the correct method to do that. (Arcsegement seems to be a possiblity but it doesnt use degrees or radians.) The JS to C# conversion was not an issue except I wasnt exactly sure I got the drawFactor right or possibly some other rounding issue.
so what’s wrong then – the tile sizes, or their locations? you might get rounding errors in arcX/arcY – i think those will be integers based on how your code is written.