JavaScript实现曼德勃罗(Mandelbrot)集合
运用知识: js线程、Mandelbrot
1. js线程
js线程简介:
在HTML5中的线程是这样一种机制,它允许在Web程序中并发执行多个JS脚本,
每一个脚本执行流都称为一个线程,彼此间相互独立,并且有浏览器中JS引擎
负责管理。
HTML5中的Web worker可以分为两种不同线程类型,一个是专用线程DedicatedWorker,
一个是共享线程SharedWorker.
worker用法很简单,它要求将要放在子线程运行的代码独立到一个js文件,通过
new Worker("worker.js")将这个js文件运行在worker线程,通过worker.postMessage()
实现主线程向worker线程发送消息。
web worker总结:
我们可以做什么:
1.可以加载一个JS进行大量的复杂计算而不挂起主进程,并通过postMessage,onmessage进行通信
2.可以在worker中通过importScripts(url)加载另外的脚本文件
3.可以使用 setTimeout(), clearTimeout(), setInterval(), and clearInterval()
4.可以使用XMLHttpRequest来发送请求
5.可以访问navigator的部分属性
有那些局限性:
1.不能跨域加载JS
2.worker内代码不能访问DOM
3.各个浏览器对Worker的实现不大一致,例如FF里允许worker中创建新的worker,而Chrome中就不行
4.不是每个浏览器都支持这个新特性(IE9不支持)
2. 曼德勃罗(Mandelbrot)集合
分形简介:
尽管类似于柯赫雪花这样的自相似图形早已经出现。但是真正把这些问题系统地发展成一门学问,则是在二十世纪下半页。数学家本华·曼德勃罗(Benoit B. Mandelbrot)把这些部分与整体以某种方式相似的形体称为分形(fractal)。1975年,他创立了分形几何学(Fractal Geometry)。在此基础上,形成了研究分形性质及其应用的科学,称为分形理论(Fractal Theory)。因此,曼德勃罗也被称为“分形学之父”。现在,分形理论已经发展成为一门十分风靡和活跃的新理论、新学科,特别是把分形理论和混沌理论结合之后,更是衍生出一大片广阔的研究天地。分形的世界与我们平常所研究的几何学中很多直观的常识之间具有巨大的冲突。例如,平常我们说一个几何图形的维度,那么这个维度一般都应该是整数。例如平面上一个矩形就是二维的,空间中一个球体就是三维的。但是在分析几何中,几何图形的维度都是不是整数而是分数。这个维度又称为豪斯多夫维或豪斯多夫-贝塞科维奇维(Hausdorff-Becikovich Dimesion),它是由数学家豪斯多夫于1918年引入的。通过豪斯多夫维可以给一个任意复杂的点集合比如分形赋予一个维度
曼德勃罗集合(Mandelbrot Set):
曼德勃罗集合(Mandelbrot Set)或曼德勃罗复数集合,是一种在复平面上组成分形的点的集合,因由曼德勃罗提出而得名。曼德博集合可以使复二次多项式 进行迭代来获得。其中,c是一个复参数。对于每一个c,从 z = 0 开始对fc(z)进行迭代。序列 的值或者延伸到无限大,或者只停留在有限半径的圆盘内(这与不同的参数c有关)。曼德布洛特集合就是使以上序列不延伸至无限大的所有c点的集合。
下面看程序效果:
下面看代码部分:
fractal.html
我们使用画布来显示图案canvas的putImageData()、getImageData()绘制
<!doctype html>
<html lang="en">
<head>
<title>Fractal Explorer</title>
<meta charset="utf-8">
<link rel="stylesheet" href="fractal.css">
<script src="mandellib.js"></script>
<script src="mandel.js"></script>
</head>
<body>
<canvas id="fractal" width="800" height="600"></canvas>
</body>
</html>
fractal.html简单的css
html, body, canvas {width: 100%;height: 100%;margin: 0px;padding: 0px;
}canvas {display: block;
}
mandellib.js
根据row行数创建任务、制作调色板、绘制一行像素、设置画布等。
/* * mandellib.js*** ------ Ready Bake Globals ---- */
var canvas;
var ctx;var i_max = 1.5;
var i_min = -1.5;
var r_min = -2.5;
var r_max = 1.5;var max_iter = 1024;
var escape = 100;
var palette = [];/* * ------- Ready Bake Code --------**///
// packages up the data we need to send to the worker
//
function createTask(row) {var task = {row: row, // row number we're working onwidth: rowData.width, // width of the ImageData object to fillgeneration: generation, // how far in we arer_min: r_min,r_max: r_max,i: i_max + (i_min - i_max) * row / canvas.height,max_iter: max_iter,escape: escape};return task;
}
//
// This function maps the numbers 0 to max_iter to
// 256 and then fills the palette with (r, g, b) values
// so that the colors next to each other in the array
// are relatively close to each other in color, and
// by increasing each of r, g, b at a different rate this
// works well to fill the spectrum for max_iter > 256.
//
//
function makePalette() {function wrap(x) {x = ((x + 256) & 0x1ff) - 256;if (x < 0) x = -x;return x;}for (i = 0; i <= this.max_iter; i++) {palette.push([wrap(7*i), wrap(5*i), wrap(11*i)]);}
}//
// drawRow gets maps the values in the array returned from a worker
// for one row to a color using the palette.
//
function drawRow(workerResults) {var values = workerResults.values; // The values array the worker sends backvar pixelData = rowData.data; // The actual pixels in the ImageData obj// The pixelData is a *reference* to the// rowData.data! so changing pixelData// changes the rowData.data!!!for (var i = 0; i < rowData.width; i++) { // for each pixel in the rowvar red = i * 4;var green = i * 4 + 1;var blue = i * 4 + 2;var alpha = i * 4 + 3;pixelData[alpha] = 255; // set alpha to opaque// if the values array has a neg number, set the color to blackif (values[i] < 0) {pixelData[red] = pixelData[green] = pixelData[blue] = 0;} else {//// map the number from the values array returned by the worker// to a color from the palette//var color = this.palette[values[i]];//// each color has an rgb component, so set the rgb of// the pixel we're working on to r,g,b.//pixelData[red] = color[0];pixelData[green] = color[1];pixelData[blue] = color[2];}}//// paint the row back into the canvas// workerData.row is the row number we're working on// rowData contains the data we just updated!// we start at column 0, so x, y = 0, row//ctx.putImageData(this.rowData, 0, workerResults.row);
}//
// setupGraphics sets up some of the initial values for the variables used in
// the Mandelbrot computation, and sets the canvas width and height
// to the width and height of the window.
//
function setupGraphics() {canvas = document.getElementById("fractal");ctx = canvas.getContext("2d");canvas.width = window.innerWidth;canvas.height = window.innerHeight;var width = ((i_max - i_min) * canvas.width / canvas.height);var r_mid = (r_max + r_min) / 2;r_min = r_mid - width/2;r_max = r_mid + width/2;rowData = ctx.createImageData(canvas.width, 1);makePalette();
}
workerlib.js 子线程使用的函数computeRow(),计算ImageData每行的像素对应的调色板值
//
// Computes a row of the fractal
// The values array returned to the manager code contains a
// number for each pixel in the row
//
function computeRow(task) {var iter = 0;var c_i = task.i;var max_iter = task.max_iter;var escape = task.escape * task.escape;task.values = [];for (var i = 0; i < task.width; i++) {var c_r = task.r_min + (task.r_max - task.r_min) * i / task.width;var z_r = 0, z_i = 0;for (iter = 0; z_r*z_r + z_i*z_i < escape && iter < max_iter; iter++) {// z -> z^2 + cvar tmp = z_r*z_r - z_i*z_i + c_r;z_i = 2 * z_r * z_i + c_i;z_r = tmp;}if (iter == max_iter) {iter = -1;}task.values.push(iter);}return task;
}
worker.js 后台子线程,我们创建八个,负责计算工作,返回给主线程
importScripts("workerlib.js");
onmessage = function(task) {var workerResult = computeRow(task.data);postMessage(workerResult);
}
mandel.js 主要是将画布中每行的任务分发给8个线程,监听canvas点击事件响应重新绘制等。
/* * mandel.js*/var numberOfWorkers = 8;
var workers = [];
var rowData;
var nextRow = 0;
var generation = 0;window.onload = init;function init() {setupGraphics();//// When you click on the canvas, the handler is called.// An event object is passed in that contains the// x, y position of the mouse click. We pass those// values to the click handler.//canvas.onclick = function(event) {handleClick(event.clientX, event.clientY);};//// When you resize the browser window, we need// to resize the canvas and restart the workers.//window.onresize = function() {resizeToWindow();};//// Create all the workers and set up the message handler. // Add each worker to the workers array.//for (var i = 0; i < numberOfWorkers; i++) {var worker = new Worker("worker.js");worker.onmessage = function(event) {processWork(event.target, event.data)}worker.idle = true;workers.push(worker);}//// Start the workers//startWorkers();}//
// startWorkers
// This function resets the workers to start them working
// at the top of the fractal (row 0). It loops through
// all the workers in the workers array and assigns
// each worker a task to compute a row.
// By posting a message with the task, we start the
// worker's computation.
//
function startWorkers() {generation++;nextRow = 0;for (var i = 0; i < workers.length; i++) {var worker = workers[i];if (worker.idle) {var task = createTask(nextRow);worker.idle = false;worker.postMessage(task);nextRow++;}}
} //
// processWork
// This is the function we call when the worker posts
// back a message with the results.
// If the worker is working on the current fractal
// generation, we draw the row of data, otherwise
// we just throw the data away.
// Once we've used the results, we assign the worker to
// start computing another row.
//
function processWork(worker, workerResults) {if (workerResults.generation == generation) {drawRow(workerResults);}reassignWorker(worker);
}//
// reassignWorker
// This function gives an idle worker its next task.
//
function reassignWorker(worker) {var row = nextRow++;if (row >= canvas.height) {worker.idle = true;} else {var task = createTask(row);worker.idle = false;worker.postMessage(task);}
}// handleClick
// This function takes the x, y position where the user
// clicked and sets the parameters for the new
// fractal. The zoom factor sets the new extent
// of the bounds of the Mandelbrot set to the
// zoomed in size. The new fractal maintains
// the aspect ratio of the current canvas size.
// We start the workers over on the new zoomed in
// fractal.
//
function handleClick(x, y) {var width = r_max - r_min;var height = i_min - i_max;var click_r = r_min + ((width * x) / canvas.width);var click_i = i_max + ((height * y) / canvas.height);var zoom = 8;r_min = click_r - width/zoom;r_max = click_r + width/zoom;i_max = click_i - height/zoom;i_min = click_i + height/zoom;startWorkers();
}//
// resizeToWindow
// When the user resizes the browser window,
// this function is called to resize the canvas,
// and reset the fractal parameters (changing the
// extent of the boundary and maintaining the new
// aspect ratio of the window).
// We restart the workers to compute the new fractal
// based on the new size.
//
function resizeToWindow() {canvas.width = window.innerWidth;canvas.height = window.innerHeight;var width = ((i_max - i_min) * canvas.width / canvas.height);var r_mid = (r_max + r_min) / 2;r_min = r_mid - width/2;r_max = r_mid + width/2;rowData = ctx.createImageData(canvas.width, 1);startWorkers();
}
JavaScript实现曼德勃罗(Mandelbrot)集合相关推荐
- matlab分形曼德勃罗,曼德勃罗集合分形图案
三.曼德勃罗集合(Mandelbrot Set) 曼德勃罗集合(Mandelbrot Set)或曼德勃罗复数集合,是一种在复平面上组成分形的点的集合,因由曼德勃罗提出而得名.曼德博集合可以使复二次多项 ...
- unity DOTS的学习总结之Job System应用——绘制曼德勃罗集合
接上回:DOTS的学习总结之Job System的介绍,这次就利用之前了解知识来做点效果. 上回在这:unity DOTS的学习总结之Job System 说到并行处理,那最适合拿来做实验的就是一些分 ...
- 浅析曼德勃罗集及C++实现图形绘制
在算法大作业中,认识到了曼德勃罗集(Mandelbrot Set)这一名词,经过网上资料的查阅,才对其思想和独特魅力略知皮毛.由于该集合的定义与分形有关,需要先介绍一下分形的概念. 什么是分形(Fra ...
- 基于MATLAB和python输出曼德勃罗集
上帝的指纹--曼德勃罗集 曼德勃罗集可称是人类有史以来做出的最奇异.最瑰丽的几何图形,被人称为"上帝的指纹"."魔鬼的聚合物". 这个点集均出自公式:Zn+1= ...
- python绘制分形图基础_Python 绘制分形图(曼德勃罗集、分形树叶、科赫曲线、分形龙、谢尔宾斯基三角等)附代码...
1. 曼德勃罗集 import numpy as np import pylab as pl import time from matplotlib import cm def iter_point( ...
- python生成曼德勃罗分形图形
来自https://blog.csdn.net/baimafujinji/article/details/50859174 c程序版生产那种格式的图像显然不利于咱们研究分析,于是写个py版本的以方便学 ...
- C++ AMP实战:绘制曼德勃罗特集图像
本文转自:http://www.cnblogs.com/Ninputer/archive/2012/01/03/2310945.html 之前我写了一篇用GPU绘制曼德勃罗特(Mandelbrot)集 ...
- C++ AMP 实战:绘制曼德勃罗特集图像
转自:http://www.oschina.net/question/54100_37584 之前我写了一篇用GPU绘制曼德勃罗特(Mandelbrot)集图像的文章,里面使用的技术是与DirectX ...
- 基于Python画曼德勃罗集
最近有点迷分型几何,看到"上帝指纹"曼德勃罗集,想用Python实现一下. 源码很简单20行不到. import matplotlib.pyplot as plt import n ...
最新文章
- MATLAB的imtransform()函数作图像线性平移时如果要体现效果要加上目标Size限制
- 常考数据结构和算法:设计LRU缓存结构
- 解决mysql插入数据时出现Incorrect string value: '\xF0\x9F...' 的异常
- Java消息队列--ActiveMq 初体验
- jQuery插件之ajaxFileUpload(异步上传图片并实时显示,并解决onchange后ajaxFileUpload失效问题)...
- kubernetes-dashboard(1.8.3)部署与踩坑
- Python数模笔记-NetworkX(1)图的操作
- kubernetes与web集群
- 以下()不是python的数值运算操作符_python运算符与数据类型
- jquery根据身份证号码计算出生日期、年龄、性别代码
- linux eof打印列表,Linux:结合cat和EOF输出到文本文件
- 2011年工作安排_计算机技术与软件专业技术资格考试
- 极域电子教室超级管理员密码
- Linux的网络基础
- android电话本导入iphone,如何将Android电话簿导入iPhone手机
- office2007怎么卸载干净?
- argis加载tpk离线包
- 科大讯飞语音识别SDK的ROS包修改
- oracle rman crosscheck,rman的crosscheck命令
- 函数的单调性与曲线的凹凸性
热门文章
- 电子信息工程技术就业方向有哪些?
- spider pi 智能视觉六足机器人 颜色识别功能 0603
- Flink Watermark 源码分析
- C/C++ 中memset()
- 语法分析——简单判断条件语句,赋值语句,循环语句
- 【电路理论】1-1 集总假设
- 极大似然函数求解_概率论中极大似然估计中的似然函数怎么确定 就是L(X;θ)...
- (一)linux系统用户管理、用户组管理
- 南京信息工程大学计算机科学与技术怎么样,作为全国重点的大学,南京信息工程大学是个怎么样的学校?...
- idea 2020 2021 maven不能下载jar包解决办法