script.js
author Eugen Sawin <sawine@me73.com>
Thu, 05 Jan 2012 23:29:27 +0100
changeset 82 cb8897d7f508
parent 81 a76b2fb0f21f
child 83 228adcfd8f23
permissions -rw-r--r--
Fixed minor bug.
sawine@74
     1
var QUOTES_NUMBER = 39;
sawine@78
     2
var SERVER = "http://" + window.location.hostname + ":" + window.location.port;
sawine@78
     3
var simulation;
sawine@80
     4
var gameoflife;
sawine@74
     5
sawine@78
     6
$(document).ready(function() {   
sawine@82
     7
    simulation = new Simulation(document.getElementById("sim"), 
sawine@82
     8
                                670, 50, 4, green, background);  
sawine@74
     9
    var image = new Image();
sawine@74
    10
    image.onload = init_logo;
sawine@74
    11
    image.src = "images/logobase.png";
sawine@74
    12
    $("#logo").click(handle_click);   
sawine@74
    13
    $("#logo").hover(function() {
sawine@75
    14
        $(this).css("cursor", "pointer");        
sawine@74
    15
    }, function() {
sawine@74
    16
        $(this).css("cursor", "auto");
sawine@77
    17
    });
sawine@79
    18
    $("#sim").mousemove(function(event) { simulation.mouse_moved(mouse_pos(event, "#sim")); });
sawine@78
    19
    var onEachFrame;
sawine@78
    20
    if (window.webkitRequestAnimationFrame) {
sawine@78
    21
        onEachFrame = function(cb) {
sawine@78
    22
            var _cb = function() { cb(); webkitRequestAnimationFrame(_cb); }
sawine@78
    23
            _cb();
sawine@78
    24
        };
sawine@78
    25
    } else if (window.mozRequestAnimationFrame) {
sawine@78
    26
        onEachFrame = function(cb) {
sawine@78
    27
            var _cb = function() { cb(); mozRequestAnimationFrame(_cb); }
sawine@78
    28
            _cb();
sawine@78
    29
        };
sawine@78
    30
    } else {
sawine@78
    31
        onEachFrame = function(cb) {
sawine@78
    32
            setInterval(cb, 1000 / 30);
sawine@78
    33
        }
sawine@78
    34
    }    
sawine@78
    35
    window.onEachFrame = onEachFrame;   
sawine@81
    36
    window.onEachFrame(update);  
sawine@81
    37
    var pos = document.location.href.lastIndexOf("/") + 1; 
sawine@81
    38
    var page = document.location.href.substr(pos);
sawine@81
    39
    if (page == "experiments.html") {
sawine@81
    40
        draw(0, 0, 0, 0, 0);
sawine@81
    41
    } else if (page == "gameoflife.html") {
sawine@81
    42
        init_gameoflife();
sawine@81
    43
    }
sawine@74
    44
});
sawine@74
    45
sawine@78
    46
$(document).keypress(function(event) {
sawine@78
    47
    if (event.which == 13) {      
sawine@74
    48
	event.preventDefault();
sawine@74
    49
        update_logo();	    
sawine@74
    50
    }
sawine@74
    51
});
sawine@74
    52
sawine@74
    53
var menu_width = 670;
sawine@77
    54
var menu_height = 100;
sawine@77
    55
var menu_splits = new Array(180, 350, 505);
sawine@74
    56
sawine@74
    57
var click_events = new Array();
sawine@74
    58
click_events["logo"] = new Array();
sawine@74
    59
click_events["logo"][0] = new Object();
sawine@74
    60
click_events["logo"][0]["min_x"] = 0;
sawine@75
    61
click_events["logo"][0]["max_x"] = menu_splits[0];
sawine@74
    62
click_events["logo"][0]["min_y"] = 0;
sawine@74
    63
click_events["logo"][0]["max_y"] = menu_height;
sawine@74
    64
click_events["logo"][0]["func"] = switch_page;
sawine@74
    65
click_events["logo"][0]["args"] = new Array("personalwork.html");
sawine@74
    66
click_events["logo"][1] = new Object();
sawine@75
    67
click_events["logo"][1]["min_x"] = menu_splits[0] + 1;
sawine@75
    68
click_events["logo"][1]["max_x"] = menu_splits[1];
sawine@74
    69
click_events["logo"][1]["min_y"] = 0;
sawine@74
    70
click_events["logo"][1]["max_y"] = menu_height;
sawine@74
    71
click_events["logo"][1]["func"] = switch_page;
sawine@74
    72
click_events["logo"][1]["args"] = new Array("howiwork.html");
sawine@74
    73
click_events["logo"][2] = new Object();
sawine@75
    74
click_events["logo"][2]["min_x"] = menu_splits[1] + 1;
sawine@75
    75
click_events["logo"][2]["max_x"] = menu_splits[2];
sawine@74
    76
click_events["logo"][2]["min_y"] = 0;
sawine@74
    77
click_events["logo"][2]["max_y"] = menu_height;
sawine@74
    78
click_events["logo"][2]["func"] = switch_page;
sawine@74
    79
click_events["logo"][2]["args"] = new Array("books.html");
sawine@74
    80
click_events["logo"][3] = new Object();
sawine@75
    81
click_events["logo"][3]["min_x"] = menu_splits[2] + 1;
sawine@74
    82
click_events["logo"][3]["max_x"] = menu_width - 1;
sawine@74
    83
click_events["logo"][3]["min_y"] = 0;
sawine@74
    84
click_events["logo"][3]["max_y"] = menu_height;
sawine@74
    85
click_events["logo"][3]["func"] = switch_page;
sawine@74
    86
click_events["logo"][3]["args"] = new Array("links.html", "linksend.html");
sawine@74
    87
sawine@78
    88
function mouse_pos(event, id) { 
sawine@78
    89
    var offset = $(id).offset();   
sawine@77
    90
    return new Array(event.pageX - offset.left, 
sawine@77
    91
                     event.pageY - offset.top);
sawine@77
    92
}
sawine@77
    93
sawine@77
    94
function handle_click(event) {
sawine@78
    95
    var xy = mouse_pos(event, "#logo");
sawine@77
    96
    var x = xy[0];
sawine@77
    97
    var y = xy[1];
sawine@77
    98
    for (var i in click_events[event.target.id]) {
sawine@77
    99
        var ces = click_events[event.target.id][i];
sawine@74
   100
        if (ces && x >= ces["min_x"] && x <= ces["max_x"]
sawine@74
   101
            && y >= ces["min_y"] && y <= ces["max_y"]) {    
sawine@77
   102
            ces["func"](event.target.id, ces);
sawine@74
   103
            break;
sawine@74
   104
        }
sawine@74
   105
    }
sawine@74
   106
}
sawine@74
   107
sawine@74
   108
function switch_page(id, params) {
sawine@74
   109
    var page = params["args"][0];
sawine@74
   110
    $("body").load(page);
sawine@74
   111
    document.location.href = page;    
sawine@74
   112
}
sawine@74
   113
sawine@77
   114
function colour_area(image, min_x, max_x, min_y, max_y, colour) {   
sawine@74
   115
    var pixels = image.data;    
sawine@74
   116
    for (var y = min_y; y <= max_y; y += 1) {
sawine@74
   117
        for (var x = min_x; x <= max_x; x += 1) {
sawine@74
   118
            var pix_colour = getPixel(image, x, y);
sawine@74
   119
            if (pix_colour.a > 0) {
sawine@74
   120
                colour.a = pix_colour.a;
sawine@74
   121
                setPixel(image, x, y, colour);
sawine@74
   122
            }
sawine@74
   123
        }
sawine@77
   124
    }    
sawine@74
   125
}
sawine@74
   126
sawine@74
   127
function init_logo(event) {
sawine@74
   128
    var canvas = document.getElementById("logo");
sawine@77
   129
    var context = canvas.getContext("2d");    
sawine@74
   130
    canvas.width = menu_width;
sawine@74
   131
    canvas.height = menu_height;
sawine@74
   132
    context.drawImage(event.target, 0, 0);
sawine@78
   133
    var image = context.getImageData(0, 0, menu_width, menu_height);    
sawine@74
   134
    for (var i in click_events["logo"]) {
sawine@77
   135
        var p = click_events["logo"][i]; 
sawine@77
   136
        var min_x = p["min_x"];
sawine@77
   137
        var max_x = p["max_x"];
sawine@77
   138
        var min_y = p["min_y"];
sawine@77
   139
        var max_y = p["max_y"];
sawine@74
   140
        var pos = document.location.href.lastIndexOf("/") + 1; 
sawine@77
   141
        var page = document.location.href.substr(pos);        
sawine@74
   142
        for (var j in p["args"]) {
sawine@74
   143
            if (page == p["args"][j]) {         
sawine@78
   144
                colour_area(image, min_x, max_x, 0, 60, black);
sawine@78
   145
                colour_area(image, min_x, max_x, 60, max_y, white);
sawine@74
   146
                break;
sawine@74
   147
            }
sawine@78
   148
            else {
sawine@78
   149
                colour_area(image, min_x, max_x, 0, 60, white);
sawine@78
   150
                colour_area(image, min_x, max_x, 60, max_y,  orange);  
sawine@78
   151
            }
sawine@78
   152
        }       
sawine@77
   153
    } 
sawine@78
   154
    context.putImageData(image, 0, 0);      
sawine@77
   155
    // context.fillStyle = green.str();
sawine@77
   156
    // console.log((found["max_x"] - found["min_x"]) / 2 + found["min_x"] - 2);
sawine@77
   157
    // context.fillRect((found["max_x"]-found["min_x"])/2+found["min_x"]-1, 95, 2, 5);  
sawine@80
   158
    draw_menu_lines();   
sawine@75
   159
}
sawine@75
   160
sawine@80
   161
function draw_menu_lines() {
sawine@75
   162
    var canvas = document.getElementById("logo");
sawine@75
   163
    var context = canvas.getContext("2d");  
sawine@75
   164
    var image = context.getImageData(0, 0, menu_width, menu_height);
sawine@75
   165
    var pixels = image.data;
sawine@75
   166
    context.lineCap = "round";
sawine@75
   167
    context.lineWidth = 1;
sawine@75
   168
    var colour1a = new Colour(0, 0, 0, 0.1);
sawine@75
   169
    context.beginPath();   
sawine@75
   170
    context.moveTo(0, menu_height - 1);
sawine@75
   171
    context.lineTo(menu_width - 1, menu_height - 1);   
sawine@75
   172
    context.closePath();  
sawine@75
   173
    context.strokeStyle = colour1a.str();
sawine@76
   174
    context.stroke(); 
sawine@76
   175
    var colour1e = new Colour(0, 0, 0, 0.05);  
sawine@76
   176
    context.beginPath();   
sawine@76
   177
    context.moveTo(70, menu_height - 1);
sawine@76
   178
    context.lineTo(menu_width - 71, menu_height - 1);   
sawine@76
   179
    context.closePath();  
sawine@76
   180
    context.strokeStyle = colour1e.str();
sawine@76
   181
    context.stroke();  
sawine@76
   182
    var colour1b = new Colour(0, 0, 0, 0.05);  
sawine@75
   183
    context.beginPath();   
sawine@75
   184
    context.moveTo(50, menu_height - 1);
sawine@75
   185
    context.lineTo(menu_width - 51, menu_height - 1);   
sawine@75
   186
    context.closePath();  
sawine@75
   187
    context.strokeStyle = colour1b.str();
sawine@75
   188
    context.stroke();
sawine@75
   189
    var colour1c = new Colour(0, 0, 0, 0.05);  
sawine@75
   190
    context.beginPath();   
sawine@75
   191
    context.moveTo(25, menu_height - 1);
sawine@75
   192
    context.lineTo(menu_width - 26, menu_height - 1);   
sawine@75
   193
    context.closePath();  
sawine@75
   194
    context.strokeStyle = colour1c.str();
sawine@75
   195
    context.stroke();
sawine@75
   196
    var colour1d = new Colour(0, 0, 0, 0.05);  
sawine@75
   197
    context.beginPath();   
sawine@75
   198
    context.moveTo(10, menu_height - 1);
sawine@75
   199
    context.lineTo(menu_width - 11, menu_height - 1);   
sawine@75
   200
    context.closePath();  
sawine@75
   201
    context.strokeStyle = colour1d.str();
sawine@75
   202
    context.stroke();  
sawine@75
   203
    
sawine@75
   204
    var colour2 = new Colour(0, 0, 0, 0.2);
sawine@75
   205
    context.beginPath();  
sawine@75
   206
    context.moveTo(menu_splits[0], 0); 
sawine@75
   207
    context.lineTo(menu_splits[0], menu_height - 1);
sawine@75
   208
    context.moveTo(menu_splits[1], 0);
sawine@75
   209
    context.lineTo(menu_splits[1], menu_height - 1);
sawine@75
   210
    context.moveTo(menu_splits[2], 0);
sawine@75
   211
    context.lineTo(menu_splits[2], menu_height - 1);
sawine@75
   212
    context.closePath();
sawine@75
   213
    context.strokeStyle = colour2.str();
sawine@75
   214
    context.stroke();
sawine@75
   215
sawine@75
   216
    context.clearRect(menu_splits[0] - 1, menu_height - 1, 2, 2);
sawine@75
   217
    context.clearRect(menu_splits[1] - 1, menu_height - 1, 2, 2);
sawine@75
   218
    context.clearRect(menu_splits[2] - 1, menu_height - 1, 2, 2);
sawine@76
   219
sawine@76
   220
    context.clearRect(menu_splits[0] - 1, menu_height - 2, 1, 1);
sawine@76
   221
    context.clearRect(menu_splits[1] - 1, menu_height - 2, 1, 1);
sawine@76
   222
    context.clearRect(menu_splits[2] - 1, menu_height - 2, 1, 1);
sawine@75
   223
}
sawine@75
   224
sawine@75
   225
function clearMenuLines() {
sawine@75
   226
    var canvas = document.getElementById("logo");
sawine@75
   227
    var context = canvas.getContext("2d");  
sawine@75
   228
    var image = context.getImageData(0, 0, menu_width, menu_height);
sawine@75
   229
    var pixels = image.data;
sawine@75
   230
    context.clearRect(0, menu_height - 2, menu_width - 1, 2);
sawine@75
   231
    context.clearRect(menu_splits[0] - 1, 0, 2, menu_height - 1);
sawine@75
   232
    context.clearRect(menu_splits[1] - 1, 0, 2, menu_height - 1);
sawine@75
   233
    context.clearRect(menu_splits[2] - 1, 0, 2, menu_height - 1);
sawine@74
   234
}
sawine@74
   235
sawine@80
   236
function draw_sim_lines() {
sawine@80
   237
    var w = 670;
sawine@80
   238
    var h = 50;
sawine@80
   239
    var canvas = document.getElementById("sim");
sawine@80
   240
    var context = canvas.getContext("2d");  
sawine@80
   241
    var image = context.getImageData(0, 0, w, h);
sawine@80
   242
    var pixels = image.data;
sawine@80
   243
    context.lineCap = "round";
sawine@80
   244
    context.lineWidth = 1;
sawine@80
   245
    var colour1a = new Colour(0, 0, 0, 0.1);
sawine@80
   246
    context.beginPath();   
sawine@80
   247
    context.moveTo(0, h - 1);
sawine@80
   248
    context.lineTo(w - 1, h - 1);   
sawine@80
   249
    context.closePath();  
sawine@80
   250
    context.strokeStyle = colour1a.str();
sawine@80
   251
    context.stroke(); 
sawine@82
   252
    var colour1e = new Colour(0, 0, 0, 0.05);  
sawine@82
   253
    context.beginPath();   
sawine@82
   254
    context.moveTo(70, h - 1);
sawine@82
   255
    context.lineTo(w - 71, h - 1);   
sawine@82
   256
    context.closePath();  
sawine@82
   257
    context.strokeStyle = colour1e.str();
sawine@82
   258
    context.stroke();  
sawine@80
   259
    var colour1b = new Colour(0, 0, 0, 0.05);  
sawine@80
   260
    context.beginPath();   
sawine@80
   261
    context.moveTo(50, h - 1);
sawine@80
   262
    context.lineTo(w - 51, h - 1);   
sawine@80
   263
    context.closePath();  
sawine@80
   264
    context.strokeStyle = colour1b.str();
sawine@80
   265
    context.stroke();
sawine@82
   266
    var colour1c = new Colour(0, 0, 0, 0.05);  
sawine@82
   267
    context.beginPath();   
sawine@82
   268
    context.moveTo(25, h - 1);
sawine@82
   269
    context.lineTo(w - 26, h - 1);   
sawine@82
   270
    context.closePath();  
sawine@82
   271
    context.strokeStyle = colour1c.str();
sawine@82
   272
    context.stroke();
sawine@80
   273
    var colour1d = new Colour(0, 0, 0, 0.05);  
sawine@80
   274
    context.beginPath();   
sawine@80
   275
    context.moveTo(10, h - 1);
sawine@80
   276
    context.lineTo(w - 11, h - 1);   
sawine@80
   277
    context.closePath();  
sawine@80
   278
    context.strokeStyle = colour1d.str();
sawine@80
   279
    context.stroke();   
sawine@80
   280
}
sawine@80
   281
sawine@74
   282
function update_logo() {
sawine@74
   283
    var canvas = document.getElementById("logo");
sawine@74
   284
    var context = canvas.getContext("2d");  
sawine@74
   285
    var image = context.getImageData(0, 0, menu_width, menu_height);
sawine@74
   286
    var pixels = image.data;
sawine@74
   287
    var white = new Colour(255, 255, 255);
sawine@74
   288
    for (var y = 0; y < menu_height; y += 1) {
sawine@74
   289
        for (var x = 0; x < menu_width; x += 1) {
sawine@74
   290
            var pix_colour = getPixel(image, x, y);
sawine@74
   291
            if (pix_colour.a > 0) {
sawine@74
   292
                setPixel(image, x, y, new Colour(90, 215, 21, pix_colour.a));
sawine@74
   293
            }
sawine@74
   294
        }
sawine@74
   295
    }   
sawine@74
   296
    context.putImageData(image, 0, 0);
sawine@74
   297
}
sawine@74
   298
sawine@80
   299
function init_gameoflife() {
sawine@81
   300
    var canvas = document.getElementById("gameoflife");
sawine@81
   301
    if (canvas) {
sawine@82
   302
        gameoflife = new Simulation(canvas, 670, 670, 8,
sawine@82
   303
                                    green, black);
sawine@80
   304
        $("#gameoflife").mousemove(function(event) { 
sawine@80
   305
            gameoflife.mouse_moved(mouse_pos(event, "#gameoflife")); 
sawine@81
   306
        });       
sawine@80
   307
    }
sawine@80
   308
}
sawine@80
   309
sawine@74
   310
function Colour(r, g, b, a) {
sawine@74
   311
    this.r = r;
sawine@74
   312
    this.g = g;
sawine@74
   313
    this.b = b;
sawine@77
   314
    this.a = a == undefined ? 255 : a;
sawine@74
   315
}
sawine@74
   316
Colour.prototype.equals = function(rhs) {
sawine@74
   317
    for (p in this) {
sawine@74
   318
        if (typeof(rhs[p]) == undefined
sawine@74
   319
           || this[p] != rhs[p]) {           
sawine@74
   320
            return false;
sawine@74
   321
        }
sawine@74
   322
    }
sawine@74
   323
    return true;
sawine@74
   324
}
sawine@75
   325
Colour.prototype.str = function() {
sawine@75
   326
    return "rgba(" + this.r + "," + this.g + "," + this.b + "," + this.a + ")";
sawine@75
   327
}
sawine@74
   328
sawine@78
   329
var white = new Colour(255, 255, 255);
sawine@78
   330
var black = new Colour(0, 0, 0);
sawine@78
   331
var orange = new Colour(201, 87, 35);
sawine@78
   332
var green = new Colour(90, 215, 21);
sawine@78
   333
var background = new Colour(34, 34, 34);
sawine@78
   334
sawine@77
   335
function setPixel(image, x, y, colour) {
sawine@74
   336
    var index = 4 * (x + y * image.width);
sawine@77
   337
    image.data[index] = colour.r;
sawine@77
   338
    image.data[index + 1] = colour.g;
sawine@77
   339
    image.data[index + 2] = colour.b;
sawine@77
   340
    image.data[index + 3] = colour.a;
sawine@74
   341
}
sawine@74
   342
sawine@74
   343
function getPixel(image, x, y) {   
sawine@74
   344
    var index = 4 * (x + y * image.width);
sawine@74
   345
    var r = image.data[index];
sawine@74
   346
    var g = image.data[index + 1];
sawine@74
   347
    var b = image.data[index + 2];
sawine@74
   348
    var a = image.data[index + 3];
sawine@74
   349
    return new Colour(r, g, b, a);
sawine@74
   350
}
sawine@74
   351
sawine@74
   352
function load_random_quote() {
sawine@74
   353
    var file = "/quotes/quote" + Math.floor(Math.random() * QUOTES_NUMBER + 1) + ".html";
sawine@74
   354
    $.ajax({url: SERVER + file,
sawine@74
   355
            success: write_quote});
sawine@74
   356
}
sawine@74
   357
sawine@74
   358
function write_quote(data, status, xhr) {   
sawine@74
   359
    $("#random_quote").html(data);
sawine@74
   360
}
sawine@74
   361
sawine@74
   362
function load_footer()
sawine@74
   363
{
sawine@74
   364
	var file = "/footer.html";
sawine@74
   365
	var currentFile = self.location.hostname + self.location.pathname;		
sawine@74
   366
	var request = http_request_object();
sawine@74
   367
	var url  = "http://" + self.location.hostname + file;	
sawine@74
   368
	request.open("GET", url, false);
sawine@74
   369
	request.setRequestHeader("User-Agent", navigator.userAgent);
sawine@74
   370
	request.send(null)
sawine@74
   371
	// if (oRequest.status == 200) alert(oRequest.responseText);
sawine@74
   372
	// else alert("Error executing XMLHttpRequest call!");	
sawine@74
   373
	//document.write(url);
sawine@74
   374
	//document.write(request.responseText);
sawine@74
   375
    document.getElementById('footer').innerHTML = request.responseText;
sawine@74
   376
}
sawine@74
   377
sawine@74
   378
sawine@74
   379
sawine@74
   380
// Mandelbrot functions
sawine@74
   381
function Complex(real, imag) 
sawine@74
   382
{
sawine@74
   383
	this.real = real;
sawine@74
   384
	this.imag = imag;
sawine@74
   385
}
sawine@74
   386
sawine@74
   387
var MIN_C = new Complex(-2.2, -1.4);
sawine@74
   388
var MAX_C = new Complex(1.0, 1.4);
sawine@74
   389
var min_c = MIN_C;
sawine@74
   390
var max_c = MAX_C;
sawine@74
   391
var MIN_ITER = 100;
sawine@74
   392
var max_iter = MIN_ITER;
sawine@74
   393
var zoom = 1.0;
sawine@74
   394
var resolution = 3;
sawine@74
   395
var bailout = 4.0;
sawine@74
   396
sawine@74
   397
function Result(z, iter) 
sawine@74
   398
{
sawine@74
   399
	this.z = z;
sawine@74
   400
	this.iter = iter;
sawine@74
   401
}
sawine@74
   402
sawine@74
   403
function complex_quad(c)
sawine@74
   404
{
sawine@74
   405
	return new Complex(Math.pow(c.real, 2) - Math.pow(c.imag, 2), 
sawine@74
   406
		2.0 * c.real * c.imag);
sawine@74
   407
}
sawine@74
   408
sawine@74
   409
function complex_quad_value(c)
sawine@74
   410
{
sawine@74
   411
	return Math.pow(c.real, 2) + Math.pow(c.imag, 2);
sawine@74
   412
}
sawine@74
   413
sawine@74
   414
function complex_add(c1, c2)
sawine@74
   415
{
sawine@74
   416
	return new Complex(c1.real + c2.real, c1.imag + c2.imag);
sawine@74
   417
}
sawine@74
   418
sawine@74
   419
function complex_equal(c1, c2)
sawine@74
   420
{	
sawine@74
   421
	return (c1.real == c2.real) && (c1.imag == c2.imag);
sawine@74
   422
}
sawine@74
   423
sawine@74
   424
function iterate(z, c) 
sawine@74
   425
{
sawine@74
   426
	z_quad = complex_quad(z);
sawine@74
   427
	return new Complex(z_quad.real + c.real, z_quad.imag + c.imag);
sawine@74
   428
}
sawine@74
   429
sawine@74
   430
function test(c, max_iter) 
sawine@74
   431
{
sawine@74
   432
	var iter = 0;
sawine@74
   433
	var z = new Complex(0.0, 0.0);
sawine@74
   434
	var last_z = new Complex(-1.0, 0.0);
sawine@74
   435
	var quad_z = complex_quad_value(z);
sawine@74
   436
	
sawine@74
   437
	while (iter < max_iter
sawine@74
   438
		&& !complex_equal(z, last_z)
sawine@74
   439
		&& quad_z <= bailout)
sawine@74
   440
	{
sawine@74
   441
		last_z = z;
sawine@74
   442
		z = iterate(z, c);
sawine@74
   443
		quad_z = complex_quad_value(z);
sawine@74
   444
		iter++;
sawine@74
   445
	}
sawine@74
   446
	return new Result(quad_z, iter);
sawine@74
   447
}
sawine@74
   448
sawine@74
   449
function draw(diter, dx, dy, dz, dres)
sawine@74
   450
{  
sawine@74
   451
	var canvas = document.getElementById('mandelbrot'); 
sawine@74
   452
	
sawine@74
   453
	if (canvas.getContext)
sawine@74
   454
	{  
sawine@74
   455
		zoom += dz;
sawine@74
   456
		var ctx = canvas.getContext('2d');
sawine@74
   457
sawine@74
   458
		if (dres != 0)
sawine@74
   459
		{		
sawine@74
   460
			resolution = Math.max(1, resolution + dres);
sawine@74
   461
		}
sawine@74
   462
sawine@74
   463
		if (diter != 0)
sawine@74
   464
		{
sawine@74
   465
			max_iter = Math.max(MIN_ITER, max_iter + diter);
sawine@74
   466
		}
sawine@74
   467
		
sawine@74
   468
		var red = "rgb(255, 0, 0)";
sawine@74
   469
		var white = "rgb(255, 255, 255)";
sawine@74
   470
		var width = canvas.width;
sawine@74
   471
		var height = canvas.height;
sawine@74
   472
		var dim = Math.max(width, height);
sawine@74
   473
		var dim_ratio = Math.round(width / height);	
sawine@74
   474
		var diff_c = new Complex(max_c.real - min_c.real,
sawine@74
   475
			max_c.imag - min_c.imag);
sawine@74
   476
		dx_min = diff_c.real / 100 * (dx + dz);
sawine@74
   477
		dx_max = diff_c.real / 100 * (dx - dz);
sawine@74
   478
sawine@74
   479
		dy_min = diff_c.imag / 100 * (dy + dz);
sawine@74
   480
		dy_max = diff_c.imag / 100 * (dy - dz);
sawine@74
   481
sawine@74
   482
		var min_inc = new Complex(dx_min * dim_ratio / 2.0, dy_min);
sawine@74
   483
		var max_inc = new Complex(dx_max * dim_ratio / 2.0, dy_max);
sawine@74
   484
		min_c = complex_add(min_c, min_inc);
sawine@74
   485
		max_c = complex_add(max_c, max_inc);
sawine@74
   486
		diff_c = new Complex(max_c.real - min_c.real,
sawine@74
   487
			max_c.imag - min_c.imag);
sawine@74
   488
		
sawine@74
   489
		for (var y = 0; y < height; y += resolution) 
sawine@74
   490
		{
sawine@74
   491
			for (var x = 0; x < width; x += resolution) 
sawine@74
   492
			{    			
sawine@74
   493
				var c = new Complex(min_c.real + diff_c.real / dim * x, 
sawine@74
   494
					min_c.imag + diff_c.imag / dim * y);  	
sawine@74
   495
			 	var result = test(c, max_iter);	
sawine@74
   496
		 		var r = Math.min(255, Math.pow(Math.max(0, 
sawine@74
   497
		 			(result.iter - max_iter / 20.0)), 2));
sawine@74
   498
				var g = Math.min(255, Math.pow(Math.max(0, 
sawine@74
   499
					(result.iter - max_iter / 25.0)), 2));			
sawine@74
   500
		 		var b = Math.min(255, Math.pow(Math.max(0, 
sawine@74
   501
					(result.iter - max_iter / 20.0)), 2));
sawine@74
   502
		 		var colour = "rgb(" + r + "," + g + "," + b + ")";
sawine@74
   503
		 		ctx.fillStyle = colour; 
sawine@74
   504
				ctx.fillRect(x, y, resolution, resolution);			
sawine@74
   505
			}
sawine@74
   506
  		}
sawine@74
   507
	}  
sawine@74
   508
} 
sawine@74
   509
sawine@74
   510
function getEventOffsetX(evt)
sawine@74
   511
{
sawine@74
   512
	if (evt.offsetX != null)
sawine@74
   513
		return evt.offsetX;
sawine@74
   514
 
sawine@74
   515
    var obj = evt.target || evt.srcElement;
sawine@74
   516
   	setPageTopLeft(obj);
sawine@74
   517
    return (evt.clientX - obj.pageLeft);
sawine@74
   518
}
sawine@74
   519
sawine@74
   520
function getEventOffsetY(evt)
sawine@74
   521
{
sawine@74
   522
	if (evt.offsetY != null)
sawine@74
   523
		return evt.offsetY;
sawine@74
   524
 
sawine@74
   525
    var obj = evt.target || evt.srcElement;
sawine@74
   526
   	setPageTopLeft(obj);
sawine@74
   527
    return (evt.clientY - obj.pageTop);
sawine@74
   528
}
sawine@74
   529
 
sawine@74
   530
function setPageTopLeft( o )
sawine@74
   531
{
sawine@74
   532
    var top = 0,
sawine@74
   533
    left = 0,
sawine@74
   534
    obj = o;
sawine@74
   535
 
sawine@74
   536
    while (o.offsetParent)
sawine@74
   537
     {
sawine@74
   538
         left += o.offsetLeft ;
sawine@74
   539
         top += o.offsetTop ;
sawine@74
   540
         o = o.offsetParent ;
sawine@74
   541
    };
sawine@74
   542
 
sawine@74
   543
    obj.pageTop = top;
sawine@74
   544
    obj.pageLeft = left; 
sawine@74
   545
}
sawine@74
   546
 
sawine@78
   547
function draw2(evt) {
sawine@78
   548
    var iter = 0;
sawine@78
   549
    var res = 0;
sawine@78
   550
    var x = (getEventOffsetX(evt) - 335) / 167.5;
sawine@74
   551
    var y = (getEventOffsetY(evt) - 140) / 70;
sawine@78
   552
    var z = 0;
sawine@78
   553
    draw(iter, x, y, z, res);
sawine@74
   554
}
sawine@74
   555
sawine@78
   556
function update() {
sawine@78
   557
    simulation.update();
sawine@78
   558
    simulation.draw();
sawine@80
   559
    if (gameoflife) {
sawine@80
   560
        gameoflife.update();
sawine@80
   561
        gameoflife.draw();
sawine@80
   562
    }
sawine@78
   563
}
sawine@74
   564
sawine@78
   565
function Grid(width, height, cell_size) {
sawine@82
   566
    this.width = parseInt(width / cell_size + 0.5);
sawine@82
   567
    this.height = parseInt(height / cell_size + 0.5);
sawine@78
   568
    this.canvas_width = width;
sawine@78
   569
    this.canvas_height = height;
sawine@78
   570
    this.cell_size = cell_size;  
sawine@78
   571
    this.cells = new Array();
sawine@78
   572
    for (var y = 0; y < this.height; ++y) { 
sawine@78
   573
        this.cells[y] = new Array();
sawine@78
   574
        for (var x = 0; x < this.width; ++x) {
sawine@78
   575
            this.cells[y][x] = new Cell(x, y, 0, this);
sawine@78
   576
        }
sawine@78
   577
    }
sawine@78
   578
}
sawine@78
   579
Grid.prototype.cell = function(x, y) {   
sawine@78
   580
    return this.cells[y][x];
sawine@78
   581
}
sawine@78
   582
Grid.prototype.pick_cell = function(x, y) {
sawine@80
   583
    var lx = parseInt(x / this.cell_size - 0.5);
sawine@80
   584
    var ly = parseInt(y / this.cell_size - 0.5);
sawine@78
   585
    return this.cells[ly][lx];
sawine@78
   586
}
sawine@78
   587
sawine@78
   588
function Cell(x, y, value, grid) {
sawine@78
   589
    this.x = x;
sawine@78
   590
    this.y = y;  
sawine@78
   591
    this.canvas_x = x * grid.cell_size;
sawine@78
   592
    this.canvas_y = y * grid.cell_size;
sawine@78
   593
    this.value = value;
sawine@78
   594
    this.grid = grid;
sawine@78
   595
    this._neighbours = new Array();
sawine@78
   596
    this.last_mod = 0;
sawine@78
   597
}
sawine@78
   598
Cell.prototype.hash = function() {
sawine@78
   599
    return this.x + ", " + this.y;
sawine@78
   600
}
sawine@78
   601
Cell.prototype.set_value = function(value) {
sawine@78
   602
    this.value = value;
sawine@78
   603
    this.last_mod = $.now();
sawine@78
   604
}
sawine@78
   605
Cell.prototype.neighbours = function() {
sawine@78
   606
    if (this._neighbours.length) {
sawine@78
   607
        return this._neighbours;
sawine@78
   608
    }
sawine@78
   609
    if (this.x > 0) {
sawine@78
   610
        this._neighbours.push(this.grid.cell(this.x-1, this.y));
sawine@78
   611
        if (this.y > 0) {
sawine@78
   612
            this._neighbours.push(this.grid.cell(this.x-1, this.y-1));
sawine@78
   613
            this._neighbours.push(this.grid.cell(this.x, this.y-1));
sawine@78
   614
        }
sawine@78
   615
        if (this.y + 1 < this.grid.height) {
sawine@78
   616
            this._neighbours.push(this.grid.cell(this.x-1, this.y+1));
sawine@78
   617
        }
sawine@82
   618
    } else {
sawine@82
   619
        this._neighbours.push(this.grid.cell(this.grid.width-1, this.y));
sawine@78
   620
    }
sawine@78
   621
    if (this.x + 1 < this.grid.width) {
sawine@78
   622
        this._neighbours.push(this.grid.cell(this.x+1, this.y));
sawine@78
   623
        if (this.y + 1 < this.grid.height) {
sawine@78
   624
            this._neighbours.push(this.grid.cell(this.x+1, this.y+1));
sawine@78
   625
            this._neighbours.push(this.grid.cell(this.x, this.y+1));
sawine@78
   626
        }
sawine@78
   627
        if (this.y > 0) {
sawine@78
   628
            this._neighbours.push(this.grid.cell(this.x+1, this.y-1));
sawine@78
   629
        }
sawine@82
   630
    } else {
sawine@82
   631
        this._neighbours.push(this.grid.cell(0, this.y));
sawine@78
   632
    }
sawine@78
   633
    return this._neighbours;
sawine@78
   634
}
sawine@78
   635
Cell.prototype.density = function() {
sawine@78
   636
    var d = 0;
sawine@78
   637
    var neighbours = this.neighbours();
sawine@78
   638
    for (var n in neighbours) {
sawine@78
   639
        d += neighbours[n].value;
sawine@78
   640
    }
sawine@78
   641
    return d;
sawine@78
   642
}
sawine@78
   643
sawine@82
   644
function Simulation(canvas, w, h, cell_size, life_colour, dead_colour) {
sawine@78
   645
    this.last_update = 0;
sawine@78
   646
    this.last_draw = 0;
sawine@78
   647
    this.last_mouse_moved = 0;
sawine@78
   648
    this.redraw = new Array();   
sawine@78
   649
    this.canvas = canvas;
sawine@80
   650
    this.canvas.width = w;
sawine@80
   651
    this.canvas.height = h;
sawine@78
   652
    this.context = canvas.getContext("2d");    
sawine@78
   653
    this.pos_queue = new Array();
sawine@78
   654
    this.cell_queue = new Array();  
sawine@81
   655
    this.cell_size = cell_size;
sawine@82
   656
    this.life_colour = life_colour;
sawine@82
   657
    this.dead_colour = dead_colour;
sawine@78
   658
    this.grid = new Grid(this.canvas.width, this.canvas.height, cell_size);
sawine@80
   659
    draw_sim_lines();
sawine@78
   660
}
sawine@78
   661
Simulation.prototype.draw = function() {
sawine@78
   662
    var now = $.now();
sawine@79
   663
    if (this.redraw.length) {
sawine@78
   664
        var cell = this.redraw.pop();
sawine@82
   665
        this.context.fillStyle = cell.value == 1 ? 
sawine@82
   666
            this.life_colour.str() : this.dead_colour.str();
sawine@78
   667
        this.context.fillRect(cell.canvas_x, cell.canvas_y, 
sawine@78
   668
                              this.grid.cell_size, this.grid.cell_size);
sawine@78
   669
        this.last_draw = $.now();
sawine@78
   670
    }
sawine@78
   671
}
sawine@78
   672
Simulation.prototype.update = function() {
sawine@78
   673
    var now = $.now();
sawine@78
   674
    if (this.pos_queue.length) {
sawine@78
   675
        var pos = this.pos_queue.pop();
sawine@78
   676
        if (pos[0] < this.canvas.width
sawine@78
   677
            && pos[1] < this.canvas.height) {
sawine@78
   678
            var cell = this.grid.pick_cell(pos[0], pos[1]);
sawine@78
   679
            cell.set_value(1);
sawine@78
   680
            this.cell_queue.push(cell);
sawine@78
   681
            this.cell_queue.concat(cell.neighbours()); 
sawine@78
   682
            this.redraw.push(cell);          
sawine@78
   683
        }
sawine@78
   684
    }
sawine@79
   685
    if (this.last_update + 1000 > now) {
sawine@78
   686
        return;
sawine@78
   687
    }
sawine@78
   688
    var changed = new Array();
sawine@79
   689
    var next_cell_queue = new Array();
sawine@79
   690
    while (this.cell_queue.length) {
sawine@78
   691
        var cell = this.cell_queue.pop();
sawine@79
   692
        if (changed[cell.hash()]) {           
sawine@79
   693
            continue;
sawine@78
   694
        }
sawine@78
   695
        var d = cell.density();
sawine@78
   696
        if (d == 3 && cell.value == 0) {           
sawine@79
   697
            changed[cell.hash()] = cell;            
sawine@79
   698
            next_cell_queue = next_cell_queue.concat(cell.neighbours());               
sawine@78
   699
        } else if (cell.value == 1) {
sawine@78
   700
            if (d < 2 || d > 3) {              
sawine@78
   701
                changed[cell.hash()] = cell;                
sawine@79
   702
                next_cell_queue = next_cell_queue.concat(cell.neighbours());               
sawine@78
   703
            }
sawine@78
   704
        }       
sawine@78
   705
    }
sawine@78
   706
    for (var pos in changed) {
sawine@78
   707
        var cell = changed[pos];      
sawine@78
   708
        cell.set_value(1 - cell.value);
sawine@78
   709
        this.redraw.push(cell);
sawine@78
   710
    }
sawine@79
   711
    this.cell_queue = this.cell_queue.concat(next_cell_queue);
sawine@78
   712
    this.last_update = now;  
sawine@78
   713
}
sawine@78
   714
Simulation.prototype.mouse_moved = function(pos) {
sawine@78
   715
    var now = $.now();    
sawine@78
   716
    if (this.last_mouse_moved + 50 < now) {
sawine@78
   717
        this.pos_queue.push(pos);
sawine@78
   718
        this.last_mouse_moved = now;       
sawine@78
   719
    }
sawine@78
   720
}
sawine@78
   721
sawine@78
   722