Monday, March 8, 2010

Zebras and stars

While thinking about how to best go about copying a triangular section of an image, I've realized just how much easier it would be to do this if the triangle had a couple of sides that are always parallel to the sides of the source image. This would also mean a much simpler algorithm for bouncing the wedge around the source image. On the downside, the bouncing would also be more likely to end up in a loop, where the wedge goes over the same areas of the source image over and over again. This seems like a small price to pay, but who knows, maybe it'll be annoying enough to go need fixing.

So, with everything nice and perpendicular, it seems easy enough to carve a wedge out of an image: just loop through the width of the wedge, copying a progressivly taller and taller 1px-wide strip of the source image. Doing this is much helped by this section of the canvas element's description.

...
triangle = function(kc,img,x,y){
 for(i=0;i<161;i++){
  kc.drawImage(img,       //Source
            x+i,y,        //Pos. in source
            1,(i*0.419),  //Size in source
            i,0,          //Pos. in destination
            1,(i*0.419)); //Size in destination
 }
}
I pass into this function a drawing context, the source image, and the x-y coordinates of where the wedge starts. The factor of 0.419 comes partially from basic trigonometry, to make the wedge have a nice 22.5 degree angle, and partially from experimentation, to make the wedges blend into a circle nicely. As it stands, this function, when called a few times on a translated and rotated canvas, will produce an image that looks like this:

It's pretty clear that while this is along the lines of what I want, it's not quite right. The problems are twofold: the white creases along where two wedges meet, and a striping of the wedges that aren't along the x or y axis.

The striping is caused by the fact that the little strips I am copying end up too skinny when distorted by the rotation of the wedge sections. A very simple solution to this is to simply make the strips wider than one pixel, so that they overlap, and stretching them apart a bit won't let the white-space underneath show through.

The white dot at the center is caused by the simple fact that anything multiplied by zero will be zero, and I start the for loop at zero. This too is easily solved by modifying the call to drawImage() to make the whole wedge shift slightly along the x-axis. This also happens to close up the white rays coming from the middle, in addition to the big hole.

The function, then, becomes this:

...
triangle = function(kc,img,x,y){
 for(i=0;i<161;i++){
  kc.drawImage(img,
            x+i,y,
            2,(i*0.419),
            i-1,0,
            2,(i*0.419));
 }
}
And the result looks more like this:

All that's left is some animation and an interface, but a combination of schoolwork and the time taken to write this post means I'll have to put all that off for a little later. Still, pretty good progress for a couple hours worth of work.

No comments:

Post a Comment