💡 Performance: only calculate points once

This commit is contained in:
Mattéo Delabre 2015-12-23 19:01:47 +01:00
parent 41c3ce8b17
commit 7019b4c40a
3 changed files with 70 additions and 46 deletions

View File

@ -491,18 +491,18 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
};
/**
* Apply the chaos game: starting from `start`, we plot
* the next `n` points. To get to the next point, we apply
* a random transformation among given ones
* Starting from the last point in `points`, add
* `iterations` number of point generated by applying
* transformations chosen at random among `transforms`
*
* @param {Array} start Starting point
* @param {Array} points Initial set of points
* @param {number} iterations Number of points to plot
* @param {Array} transforms List of available transforms
* @param {Array} weights Probability weights for each transform
* @return {null}
*/
var applyChaos = exports.applyChaos = function applyChaos(start, iterations, transforms, weights, cb) {
var point = start;
var applyChaos = exports.applyChaos = function applyChaos(points, iterations, transforms, weights) {
var point = points[points.length - 1];
if (weights === undefined) {
weights = Array.apply(null, Array(transforms.length)).map(function () {
@ -513,8 +513,7 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
while (iterations--) {
var index = chooseIndex(weights);
point = transforms[index](point);
cb(point);
points.push(point);
}
};
}, {}], 7: [function (require, module, exports) {
@ -571,6 +570,8 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
var width = undefined,
height = undefined;
var points = [[0, 0]];
/**
* Re-render the scene from scratch
*
@ -587,24 +588,22 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
// do the chaos game
var image = ctx.getImageData(0, 0, width, height);
var length = points.length;
var color = [0, 0, 0];
var skip = 50;
_chaos.applyChaos.apply(undefined, [[0, 0], 200000].concat(_toConsumableArray(_ifs.barnsley), [function (point) {
var x = Math.floor(point[0] * zoom + center[0]);
var y = height - Math.floor(point[1] * zoom + center[1]);
for (var i = 50; i < length; i += 1) {
var x = Math.floor(points[i][0] * zoom + center[0]);
var y = height - Math.floor(points[i][1] * zoom + center[1]);
if (x >= 0 && x < width && y >= 0 && y < height && skip <= 0) {
var i = (y * width + x) * 4;
if (x >= 0 && x < width && y >= 0 && y < height) {
var index = (y * width + x) * 4;
image.data[i] = color[0];
image.data[i + 1] = color[1];
image.data[i + 2] = color[2];
image.data[i + 3] = 255;
image.data[index] = color[0];
image.data[index + 1] = color[1];
image.data[index + 2] = color[2];
image.data[index + 3] = 255;
}
skip -= 1;
}]));
}
ctx.putImageData(image, 0, 0);
};
@ -627,7 +626,7 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
*/
content.on('wheel', function (event) {
var delta = event.deltaMode === 0 ? event.deltaY / 53 : event.deltaY;
var newZoom = zoom * (1 - delta * .035);
var newZoom = zoom * Math.max(0, 1 - delta * .035);
// which (unprojected) point does the mouse point on?
var mouse = [(event.offsetX - center[0]) / zoom, (height - event.offsetY - center[1]) / zoom];
@ -638,9 +637,33 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
// => newCenter = mouse * zoom - mouse * newZoom + center
center = [mouse[0] * zoom - mouse[0] * newZoom + center[0], mouse[1] * zoom - mouse[1] * newZoom + center[1]];
zoom = newZoom;
render();
if (newZoom > zoom) {
_chaos.applyChaos.apply(undefined, [points, Math.floor((newZoom - zoom) * 1000)].concat(_toConsumableArray(_ifs.sierpinski)));
} else {
// points = points.slice(0, points.length + Math.floor((newZoom - zoom) * 1000));
}
zoom = newZoom;
// time for some GC
if (points.length > 1000000) {
var length = points.length;
var newPoints = [];
var i = 0;
for (i = 0; i < length; i += 1) {
var x = Math.floor(points[i][0] * zoom + center[0]);
var y = height - Math.floor(points[i][1] * zoom + center[1]);
if (x >= 0 && x < width && y >= 0 && y < height) {
newPoints.push(points[i]);
}
}
points = newPoints;
}
render();
event.preventDefault();
});
@ -668,6 +691,7 @@ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.const
}
});
_chaos.applyChaos.apply(undefined, [points, 200000].concat(_toConsumableArray(_ifs.sierpinski)));
window.onresize = resize;
resize();
}, { "./chaos": 6, "./ifs": 7, "the-dom": 1 }] }, {}, [8]);

View File

@ -20,18 +20,18 @@ const chooseIndex = weights => {
};
/**
* Apply the chaos game: starting from `start`, we plot
* the next `n` points. To get to the next point, we apply
* a random transformation among given ones
* Starting from the last point in `points`, add
* `iterations` number of point generated by applying
* transformations chosen at random among `transforms`
*
* @param {Array} start Starting point
* @param {Array} points Initial set of points
* @param {number} iterations Number of points to plot
* @param {Array} transforms List of available transforms
* @param {Array} weights Probability weights for each transform
* @return {null}
*/
export const applyChaos = (start, iterations, transforms, weights, cb) => {
let point = start;
export const applyChaos = (points, iterations, transforms, weights) => {
let point = points[points.length - 1];
if (weights === undefined) {
weights = Array.apply(null, Array(transforms.length)).map(
@ -42,7 +42,6 @@ export const applyChaos = (start, iterations, transforms, weights, cb) => {
while (iterations--) {
const index = chooseIndex(weights);
point = transforms[index](point);
cb(point);
points.push(point);
}
};

View File

@ -14,6 +14,8 @@ let dragging = false;
let center, zoom = 200;
let width, height;
let points = [[0, 0]];
/**
* Re-render the scene from scratch
*
@ -30,24 +32,22 @@ const render = () => {
// do the chaos game
const image = ctx.getImageData(0, 0, width, height);
const length = points.length;
const color = [0, 0, 0];
let skip = 50;
applyChaos([0, 0], 200000, ...barnsley, point => {
const x = Math.floor(point[0] * zoom + center[0]);
const y = height - Math.floor(point[1] * zoom + center[1]);
for (let i = 50; i < length; i += 1) {
const x = Math.floor(points[i][0] * zoom + center[0]);
const y = height - Math.floor(points[i][1] * zoom + center[1]);
if (x >= 0 && x < width && y >= 0 && y < height && skip <= 0) {
const i = (y * width + x) * 4;
if (x >= 0 && x < width && y >= 0 && y < height) {
const index = (y * width + x) * 4;
image.data[i] = color[0];
image.data[i + 1] = color[1];
image.data[i + 2] = color[2];
image.data[i + 3] = 255;
image.data[index] = color[0];
image.data[index + 1] = color[1];
image.data[index + 2] = color[2];
image.data[index + 3] = 255;
}
skip -= 1;
});
}
ctx.putImageData(image, 0, 0);
};
@ -70,7 +70,7 @@ const resize = () => {
*/
content.on('wheel', event => {
const delta = event.deltaMode === 0 ? event.deltaY / 53 : event.deltaY;
const newZoom = zoom * (1 - delta * .035);
const newZoom = zoom * Math.max(0, 1 - delta * .035);
// which (unprojected) point does the mouse point on?
const mouse = [
@ -113,5 +113,6 @@ content.on('mousemove', event => {
}
});
applyChaos(points, 200000, ...barnsley);
window.onresize = resize;
resize();