robjtede
robjtede

Reputation: 746

Javascript: Barnsley Fern Fractal

Can someone look over this code and point out why the resulting barnsley fern fractal doesn't look right?

function barnsley (ctx) {

ctx.fillStyle = 'green';
ctx.translate(ctx.canvas.width/2,ctx.canvas.height/2);
var self = this;

this.itts = 100000;
this.ittsCount = 0;
this.x = 0;
this.y = 0;

this.main = function () {
    for (var i=0;i<itts;i++) {
        var rand = Math.random()*100;
        if (rand < 1) {
            self.one();
        } else if (rand < 86) {
            self.two();
        } else if (rand < 94) {
            self.three();
        } else {
            self.four();
        }
    }
}

this.one = function () {
    var xn = self.x;
    var yn = self.y;
    var zx = 0;
    var zy = 0.16 * yn;
    self.drawPoint(zx,zy);
}

this.two = function () {
    var xn = self.x;
    var yn = self.y;
    var zx = 0.85 * xn + 0.4 * yn;
    var zy = -0.04 * xn + 0.85 * yn + 1.6;
    self.drawPoint(zx,zy);
}

this.three = function () {
    var xn = self.x;
    var yn = self.y;
    var zx = 0.2 * xn - 0.26 * yn;
    var zy = 0.23 * xn + 0.22 * yn + 1.6;
    self.drawPoint(zx,zy);
}

this.four = function () {
    var xn = self.x;
    var yn = self.y;
    var zx = -0.15 * xn + 0.28 * yn;
    var zy = 0.26 * xn + 0.24 * yn + 0.44;
    self.drawPoint(zx,zy);
}

this.drawPoint = function (xn,yn) {
    self.x = xn;
    self.y = yn;
    ctx.fillRect(xn*20,-yn*20,1,1);
}

this.main();
}

It has the right general shape but I must be missing something, I've checked the algorithms and such but to no avail. Any help is greatly appreciated.

Upvotes: 1

Views: 1429

Answers (2)

marctrem
marctrem

Reputation: 850

There are millions of way to do it but I think you might like this one .

Updates/steps are handled by the JS scheduler/timers. It's non-blocking and won't have your CPU go crazy with a heavy for loop.

The fractal data is also handled a different way. You could put any fractal made with affine transforms just by changing the parameters at one place. You also don't have to sum the probabilities as it does it for you.

ex: (StackOverflow won't let me post a JSFiddle link without a code exemple)

var probability_transforms =  [
    {
        "probability": 0.01, 
        "item": function(point){ return affine_transform(point, 0, 0, 0, 0.16, 0, 0) }
    },
    {
        "probability": 0.85, 
        "item": function(point){ return affine_transform(point, 0.85, 0.04, -0.04, 0.85, 0, 1.6) }
    },
    {
        "probability": 0.07,
        "item": function(point){ return affine_transform(point, 0.2, -0.26, 0.23, 0.22, 0, 1.6) }
    },
    {
        "probability": 0.07, 
        "item": function(point){ return affine_transform(point, -0.15, 0.28, 0.26, 0.24, 0, 0.44) }
    }
];

Have fun :)

Upvotes: 0

Peter Olson
Peter Olson

Reputation: 142939

There was just a small error while typing the numbers. (I checked against this source, it looks like it uses the same numbers you are using).

In this this.two functions, you need to change

var zx = 0.85 * xn + 0.4 * yn;

to

var zx = 0.85 * xn + 0.04 * yn;

You can see this fix in action on jsFiddle.

Upvotes: 4

Related Questions