+
1
|
list
|
skin
|
login
|
editor
α-wwwiki
::
mandel
user:none
(7114 bytes)
{canvas {@ id="mycanvas" width="420"; height="420" style="background:#ffe; border:1px dashed black; box-shadow:0 0 24px black;"}} {div {@ style="position:relative; top:0px; left:0px; width:130px; display:inline-block; vertical-align:top; white-space:pre-wrap; font:normal 0.8em courier;" } iterations [1,.[ {input {@ id="iter" type="text" value="10" style="background:#ccc; width:100px; text-align:center;"}} zoom [1..1.e-11] {input {@ id="zoom" type="text" value="4" style="background:#ccc; width:150px; text-align:center;"}} {span {@ id="info"}time :} x0 : {span {@ id="x0"}0} y0 : {span {@ id="y0"}0} {input {@ id="code" type="submit" value="load code" onclick="°° var MANDEL = (function () { // the only one global var var ctx, // global 2D context iter, // can be edited by field zoom, // can be edited by field and by mouse x0, y0; // modified by mouse function init () { var canvas = getId( 'mycanvas' ); ctx = canvas.getContext( '2d' ); getId('reset').addEventListener( 'click', this.reset ); getId('update').addEventListener( 'click', this.update ); add_zoom_to_mouse( canvas ); getId('iter').value = iter = 10; getId('zoom').value = zoom = 4; x0 = 0; y0 = 0; compute_imageData(); } function reset () { getId('iter').value = iter = 10; getId('zoom').value = zoom = 4; getId('x0').innerHTML = x0 = 0; getId('y0').innerHTML = y0 = 0; compute_imageData(); } function update () { // called by the update button iter = getId('iter').value; zoom = getId('zoom').value; compute_imageData(); } ///////////////////////////// // ADD ZOOM TO MOUSE ///////////////////////////// function add_zoom_to_mouse ( can ) { var context = can.getContext( '2d' ); var flag = false, coords, z, zmin = 50; can.getMouse = function (event) { var totalOffsetX = 0, totalOffsetY = 0, canvasX = 0, canvasY = 0; var currentElement = this; // recursive search do { totalOffsetX += currentElement.offsetLeft; totalOffsetY += currentElement.offsetTop; } while(currentElement = currentElement.offsetParent) canvasX = event.pageX - totalOffsetX; canvasY = event.pageY - totalOffsetY; return {x:canvasX, y:canvasY}; }; can.onmouseover = function(e) { this.style.cursor = 'crosshair'; }; can.onmouseout = function(e) { this.style.cursor = 'default'; }; can.onmousedown = function (e) { iter = parseInt(getId('iter').value); var zoom_prev = zoom; zoom = parseFloat(getId('zoom').value); x0 = x0*zoom_prev/zoom; y0 = y0*zoom_prev/zoom; coords = this.getMouse( e ); x0 = coords.x/this.width - 0.5 + x0; y0 = -(coords.y/this.height - 0.5) + y0; getId('x0').innerHTML = x0; getId('y0').innerHTML = y0; context.strokeStyle = '#888'; context.lineWidth = 1; // context.globalCompositeOperation = 'xor'; z = zmin; flag = true; }; can.onmousemove = function (e) { if (!flag) return; var coords_2 = this.getMouse( e ); var w = Math.abs( coords_2.x - coords.x ); var h = Math.abs( coords_2.y - coords.y ); z = Math.max( w, h ); context.strokeRect( coords.x - z/2, coords.y - z/2, z, z ); }; can.onmouseup = function (e) { var zoom_prev = zoom; z = (z< zmin)? zmin : z; zoom = zoom*z/this.width; getId('zoom').value = zoom; x0 = x0*zoom_prev/zoom; y0 = y0*zoom_prev/zoom; flag = false; compute_imageData(); }; } // end add_mouse_zoom_to ( canvas ) ///////////////////////////// // MANDEL ///////////////////////////// function compute_imageData() { var width = ctx.canvas.width, height = ctx.canvas.height, imageData = ctx.createImageData( width, height ), data = imageData.data, rgba = {r:0, g:0, b:0, a:255}, index; var t0 = new Date().getTime(); for (var i=0; i< width; i++) { var x = zoom*( i/width - 0.5 + x0); for (var j=0; j< height; j++) { var y = zoom*(-j/height + 0.5 + y0); mandel_geo( x, y ); // compute count and norme; mandel_col( rgba ); index = (i + j * width) * 4; data[index] = rgba.r; data[index+1] = rgba.g; data[index+2] = rgba.b; data[index+3] = rgba.a; } } var t1 = new Date().getTime(); getId( 'info' ).innerHTML = 'time: ' + (t1-t0) + 'ms'; ctx.putImageData( imageData, 0, 0 ); } var count, norme; // shared by mandel_geo and mandel_col function mandel_geo( cx, cy ) { // compute k at point C var x = 0.0, y = 0.0; // initialyze z = x + iy = 0 for (count = 0; count < iter; count++) { var X = x*x - y*y + cx; // compute z = z^2 + c var Y = 2*x*y + cy; norme = X*X + Y*Y; if ( norme > 4.0 ) break; // exit if norme > 2 x = X; // update z = x +iy y = Y; } } function mandel_col( rgba ) { var u = 255*(norme*0.25 - 1); if ( count < iter ) { rgba.r = u; rgba.g = u; rgba.b = u; } else { rgba.r = -u; rgba.g = 0; rgba.b = 0; } } /* function _mandel_col( rgba ) { if ( count < iter ) { rgba.r = ( count%2 == 0 )? 255 : 0; rgba.g = ( count%2 == 0 )? 0 : 255; rgba.b = 0; } else { rgba.r = 0; rgba.g = 255; rgba.b = 255; // Math.random() * 256 | 0; } } */ return {init:init, update:update, reset:reset}; })().init(); // MANDEL is created then inited °°"}} {input {@ id="update" type="submit" value="update"}} {input {@ id="reset" type="submit" value="reset"}} } _h3 Using mandel _ul {b 1)} First, click on "load code" to init the code, _ul {b 2)} edit the fields "iterations" and "zoom", then click on "update", _ul {b 3)} you can mouse-draw a rect around any point in the canvas to define a zoom around it, or click any point to get a predefined zoom in, _ul {b 4)} click on "reset" to re-initialize mandel. _h3 links _ul [[maelstrom|http://www.youtube.com/watch?v=I9FTyXnq5z8]], Kalles Fractaler with bigInts, _ul [[http://www.syti.net/Fractals.html|http://www.syti.net/Fractals.html]] _h3 note _p L'étonnant ensemble de [[Mandelbrot|../alphawiki/?view=mandel]] est construit sur une expression simplissime : {b z=z{sup 2}+c}, où z et c sont des nombres "dits" complexes (de la forme : {b x+iy}). Pour le cas où {b c=-1}, cette expression se réduit à : {b z=z{sup 2}-1} qui peut s'écrire : {b z{sup 2}-z-1=0}. Une équation du second degré dont les deux racines réelles (voir [[equation]]) sont les deux valeurs du nombre d'OR : {b 1.618 et 0.618}. _p The golden ratio is in the mandel set ! _h3 links _ul [[Fractals-in-theory-and-practice|http://www.codeproject.com/Articles/650821/Fractals-in-theory-and-practice]] _ul [[The Fibonacci Sequence|http://www.youtube.com/watch?feature=player_embedded&v=P0tLbl5LrJ8]] _ul [[Vortex Based Math & the 360˚ Circle|http://www.youtube.com/watch?v=-Rrsm4aMUgE&feature=youtube_gdata_player]]