'use strict'; import { getRandomNumber, getColor } from './utils'; /** * Calculate the position of a regular polygon's vertices * inside a 2 x 2 squared centered on the origin * * @param {number} count Vertices amount * @return {Array} Array of points representing the vertices */ export const createRegularVertices = count => { const step = 2 * Math.PI / count; const initial = -Math.atan(Math.sin(step) / (Math.cos(step) - 1)); const result = []; for (let i = 0; i < count; i += 1) { let current = step * i + initial; result.push([Math.cos(current), Math.sin(current)]); } return result; }; /** * Scale the vertices so that they fit in given bounding rectangle * * @param {number} width Bounding rectangle width * @param {number} height Bounding rectangle height * @param {Array} vertices Vertices to scale * @return {Array} Scaled vertices */ export const scaleVertices = (width, height, vertices) => { const centerX = Math.floor(width / 2); const centerY = Math.floor(height / 2); const radius = Math.min(centerX, centerY); return vertices.map(vertex => ([ vertex[0] * radius + centerX, vertex[1] * radius + centerY ])); }; /** * Apply the chaos game algorithm in a polygon * of given vertices, with given fraction * * @param {ImageData} image Image to write on Data to amend * @param {number} fraction Fraction to use * @param {Array} vertices List of vertices of the bounding polygon * @return {null} */ export const applyChaos = (image, fraction, vertices) => { const count = vertices.length, imageWidth = image.width; // now we apply the chaos algorithm: // for any point, the next point is a `fraction` of the // distance between it and a random vertex let point = vertices[0]; let iterations = Math.floor(500 * imageWidth * fraction); let drop = Math.floor(iterations / 200); while (iterations--) { const vertexNumber = getRandomNumber(0, count); const vertex = vertices[vertexNumber], color = getColor(vertexNumber); point = [ Math.floor((point[0] - vertex[0]) * fraction + vertex[0]), Math.floor((point[1] - vertex[1]) * fraction + vertex[1]) ]; // skip the first 1000 points if (drop === 0) { const i = (point[1] * imageWidth + point[0]) * 4; image.data[i] = color[0]; image.data[i + 1] = color[1]; image.data[i + 2] = color[2]; image.data[i + 3] = 255; } else { drop--; } } };