diff --git a/bifurcation.js b/bifurcation.js new file mode 100644 index 0000000..b9a2784 --- /dev/null +++ b/bifurcation.js @@ -0,0 +1,108 @@ +var bifurcationDiagram = { + rangeX: [0, 5], // values limiting X axis in the screen + rangeY: [0, 5], // same thing + originLocation: [0, 0], // where the plot origin will be in the canvas coordinate systen + canvasLimits: [0, 0], + + maxIterations: 100, + initialPopulation: 0.5, + + + create: function (rangeX, rangeY, canvasLimits, maxIterations){ + var obj = Object.create(this); + obj.rangeX = rangeX; + obj.rangeY = rangeY; + obj.canvasLimits = canvasLimits; + obj.maxIterations = maxIterations; + return obj; + }, + + drawAxis: function(context) + { + var zero = [0,0]; + var xAxisBegin = [rangeX[0],0]; + var xAxisEnd = [rangeX[1],0]; + var yAxisBegin = [0, rangeY[0]]; + var yAxisEnd = [0, rangeY[1]]; + + + this.renderLine(context, xAxisBegin, xAxisEnd, 'rgba(255,255,255,1)'); + this.renderLine(context, yAxisBegin, yAxisEnd, 'rgba(255,255,255,1)'); + }, + + // Paint function in that range + runDiagram: function(context, itRangeX){ + + var itrX = itRangeX; + + var width = this.canvasLimits[0]; + var height = this.canvasLimits[1]; + + // translated to canvas coordinates + var itrXPixels = [Math.floor((itRangeX[0] - this.rangeX[0])*width/(this.rangeX[1] - this.rangeX[0])), Math.floor((itRangeX[1] - this.rangeX[0])*width/(this.rangeX[1] - this.rangeX[0]))]; + + for (var x = itrXPixels[0]; x < itrXPixels[1]; x++) { + pixelToPointX = x*(this.rangeX[1] - this.rangeX[0])/(this.canvasLimits[0]-1) + this.rangeX[0]; + + var x1 = this.initialPopulation; + + // iterate equation with growth ration fixed + for(var it = 0; it < this.maxIterations; it++){ + + x1 = this.iterate(x1, pixelToPointX); + + if(it > this.maxIterations/3) + { + var point = [pixelToPointX, x1]; + this.renderPoint(context, point, 'hsla(' + x*100/(itrXPixels[1]-itrXPixels[0]) + + ',100%,50%,' + it/this.maxIterations + ')'); + } + } + + // console.log("Pixel: " + i + " Coord: " + pixelToPointX); + } + }, + + iterate: function(xn, ratio){ + return (ratio*xn*(1-xn)); + }, + + renderPoint: function(context, p, fillStyle){ + + var width = this.canvasLimits[0]; + var height = this.canvasLimits[1]; + + transformedP = [(p[0] - this.rangeX[0])*width/(this.rangeX[1] - this.rangeX[0]), + (p[1] - this.rangeY[0])*height/(this.rangeY[1] - this.rangeY[0])]; + + context.beginPath(); + context.fillStyle = fillStyle; + context.fillRect(transformedP[0], transformedP[1], 1, 1); + context.fill(); + }, + + // renders line with points in bf diagram coordinates (scaled to fit rangex and rangey) + renderLine: function(context, p1, p2, strokeStyle){ + + var width = this.canvasLimits[0]; + var height = this.canvasLimits[1]; + + transformedP1 = [(p1[0] - this.rangeX[0])*width/(this.rangeX[1] - this.rangeX[0]), (p1[1] - this.rangeY[0])*height/(this.rangeY[1] - this.rangeY[0])]; + transformedP2 = [(p2[0] - this.rangeX[0])*width/(this.rangeX[1] - this.rangeX[0]), (p2[1] - this.rangeY[0])*height/(this.rangeY[1] - this.rangeY[0])]; + + context.beginPath(); + context.strokeStyle = strokeStyle; + context.moveTo(transformedP1[0],transformedP1[1]); + context.lineTo(transformedP2[0],transformedP2[1]); + context.stroke(); + + } + // // + // applyRule: function(rule){ + // // linear interpolation + // this.pointX = this.ruleDistance*this.pointX + (1 - this.ruleDistance)*this.verticesX[rule]; + // this.pointY = this.ruleDistance*this.pointY + (1 - this.ruleDistance)*this.verticesY[rule]; + // } + +}; + diff --git a/index.html b/index.html index 44d9564..14dd241 100755 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ Star Paint + diff --git a/main.js b/main.js index ede2f21..e69dea8 100755 --- a/main.js +++ b/main.js @@ -12,23 +12,62 @@ window.onload = function(){ context.translate(width / 2, height / 2); paintcontext.translate(width / 2, height / 2); - var mode = 1; + var mode = 2; + var params = InputHandle(canvas, particles, paintcontext).params; + + + /* + *MODES SETUP + */ + // mode 0 // initialing particles for(var i = 0; i < numParticles; i++) { particles.push(particle.create(0, 0, Math.random()*4 +1, Math.random() * Math.PI *2, 0, 1)); } - var params = InputHandle(canvas, particles, paintcontext).params; + // mode 1 var game = chaosGame.create(0, 0, 1); + + // mode 2 + rangeX = [1,4.00]; + rangeY = [0,1]; + + iterationWindowX = [rangeX[0],rangeX[0]]; + + canvasLimit = [width, height]; + var bd = bifurcationDiagram.create( + rangeX, // x interval visible in screen width + rangeY, // y interval visible in screen height + canvasLimit, // canvas limits + 100); // max iterations per row. + //clear paint canvas paintcontext.clearRect(-width / 2, -height / 2, width, height); + setup(); update(); - // compute star physics and stuff + // runs once + function setup(){ + switch(mode){ + case 2: + { + // translantes canvases to left bottom to facilitate + context.translate(- width/2, height/2); + paintcontext.translate(- width/2, height/2); + context.scale(1, -1); + paintcontext.scale(1, -1); + + bd.drawAxis(paintcontext); + } + } + } + + + // runs every frame function update(){ context.clearRect(-width / 2, -height / 2, width, height); @@ -81,8 +120,6 @@ window.onload = function(){ p.render(context); } - - } break; @@ -103,6 +140,23 @@ window.onload = function(){ } break; + case 2: + { + + // bd.drawAxis(paintcontext); + + if(params.mouseLBDown){ + var delta = (rangeX[1]-rangeX[0])/10; + if(iterationWindowX[1] + delta <= rangeX[1]){ + iterationWindowX = [iterationWindowX[1], iterationWindowX[1] + delta]; + } + } + + bd.runDiagram(paintcontext, iterationWindowX); + + } + break; + }; requestAnimationFrame(update);