UNPKG

js-2dmath

Version:

Fast 2d geometry math: Vector2, Rectangle, Circle, Matrix2x3 (2D transformation), Circle, BoundingBox, Line2, Segment2, Intersections, Distances, Transitions (animation/tween), Random numbers, Noise

304 lines (239 loc) 7.59 kB
var object = require("object-enhancements"), Xorshift = require("./xorshift.js"), GRAD3 = [ [1, 1, 0], [-1, 1, 0], [1, -1, 0], [-1, -1, 0], [1, 0, 1], [-1, 0, 1], [1, 0, -1], [-1, 0, -1], [0, 1, 1], [0, -1, 1], [0, 1, -1], [0, -1, -1] ], GRAD4 = [ [0, 1, 1, 1], [0, 1, 1, -1], [0, 1, -1, 1], [0, 1, -1, -1], [0, -1, 1, 1], [0, -1, 1, -1], [0, -1, -1, 1], [0, -1, -1, -1], [1, 0, 1, 1], [1, 0, 1, -1], [1, 0, -1, 1], [1, 0, -1, -1], [-1, 0, 1, 1], [-1, 0, 1, -1], [-1, 0, -1, 1], [-1, 0, -1, -1], [1, 1, 0, 1], [1, 1, 0, -1], [1, -1, 0, 1], [1, -1, 0, -1], [-1, 1, 0, 1], [-1, 1, 0, -1], [-1, -1, 0, 1], [-1, -1, 0, -1], [1, 1, 1, 0], [1, 1, -1, 0], [1, -1, 1, 0], [1, -1, -1, 0], [-1, 1, 1, 0], [-1, 1, -1, 0], [-1, -1, 1, 0], [-1, -1, -1, 0] ], SIMPLEX = [ [0, 1, 2, 3], [0, 1, 3, 2], [0, 0, 0, 0], [0, 2, 3, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 3, 0], [0, 2, 1, 3], [0, 0, 0, 0], [0, 3, 1, 2], [0, 3, 2, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 3, 2, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 0, 3], [0, 0, 0, 0], [1, 3, 0, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 3, 0, 1], [2, 3, 1, 0], [1, 0, 2, 3], [1, 0, 3, 2], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 0, 3, 1], [0, 0, 0, 0], [2, 1, 3, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [2, 0, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 0, 1, 2], [3, 0, 2, 1], [0, 0, 0, 0], [3, 1, 2, 0], [2, 1, 0, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [3, 1, 0, 2], [0, 0, 0, 0], [3, 2, 0, 1], [3, 2, 1, 0] ], sqrt = Math.sqrt, floor = Math.floor, random = Math.random, sqrt_of_3 = sqrt(3), Noise = {}; // from: http://jsdo.it/akm2/fhMC/js // don't know the author, if you are contact me. // I just lint the code (a little)... and adapt it to the lib philosophy (that means remove 3d noises) //@TODO optimize, there is performance gain everywhere! // Common helpers function _dot2d(g, x, y) { return g[0] * x + g[1] * y; } function _dot3d(g, x, y, z) { return g[0] * x + g[1] * y + g[2] * z; } // Simplex helper function _dot4d(g, x, y, z, w) { return g[0] * x + g[1] * y + g[2] * z + g[3] * w; } // Classic helpers function _mix(a, b, t) { return (1 - t) * a + t * b; } function _fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); } /* * @reference http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf * * Tiling Example (heavy...) * * var perlinNoise = new PerlinNoise(); * * function tilingNoise2d(x, y, w, h) { * return (perlinNoise.noise(x, y) * (w - x) * (h - y) + * perlinNoise.noise(x - w, y) * x * (h - y) + * perlinNoise.noise(x - w, y - h) * x * y + * perlinNoise.noise(x, y - h) * (w - x) * y) / (w * h); */ /** * @class ClassicNoise * @param {Number} seed */ function ClassicNoise(seed) { this.seed(seed); } ClassicNoise.prototype = { _octaves: 4, _fallout: 0.5, seed: function (seed) { var random = Xorshift.create(seed || new Date().getTime()).random, i, p = [], perm = []; for (i = 0; i < 256; i++) { p[i] = floor(random() * 256); } for (i = 0; i < 512; i++) { perm[i] = p[i & 255]; } this._perm = perm; }, octaves: function (octaves) { if (!arguments.length) { return this._octaves; } return this._octaves = octaves; }, fallout: function (fallout) { if (!arguments.length) { return this._fallout; } return this._fallout = fallout; }, noise: function (x, y) { var result = 0, noise, f = 1, oct = this._octaves, amp = 0.5, fallout = this._fallout, i; for (i = 0; i < oct; ++i) { result += (1 + this.noise2d(x * f, y * f)) * amp * 0.5; amp *= fallout; f *= 2; } return result; }, noise2d: function (x, y) { var X = floor(x), Y = floor(y), perm = this._perm; x = x - X; y = y - Y; X = X & 255; Y = Y & 255; var gi00 = perm[X + perm[Y]] % 12, gi01 = perm[X + perm[Y + 1]] % 12, gi10 = perm[X + 1 + perm[Y]] % 12, gi11 = perm[X + 1 + perm[Y + 1]] % 12, n00 = _dot2d(GRAD3[gi00], x, y), n10 = _dot2d(GRAD3[gi10], x - 1, y), n01 = _dot2d(GRAD3[gi01], x, y - 1), n11 = _dot2d(GRAD3[gi11], x - 1, y - 1), u = _fade(x), v = _fade(y), nx0 = _mix(n00, n10, u), nx1 = _mix(n01, n11, u), nxy = _mix(nx0, nx1, v); return nxy; } }; /** * SimplexNoise * * @super ClassicNoise * @param {Number} seed */ function SimplexNoise(seed) { this.seed(seed); } SimplexNoise.prototype = object.extend({}, ClassicNoise.prototype, { noise: function (x, y, z, w) { var result = 0, noise, f = 1, oct = this._octaves, amp = 0.5, fallout = this._fallout, i; for (i = 0; i < oct; ++i) { result += (1 + this.noise2d(x * f, y * f)) * amp * 0.5; amp *= fallout; f *= 2; } return result; }, noise2d: function (x, y) { var n0, n1, n2, F2 = 0.5 * (sqrt_of_3 - 1), s = (x + y) * F2, i = floor(x + s), j = floor(y + s), G2 = (3 - sqrt_of_3) / 6, t = (i + j) * G2, X0 = i - t, Y0 = j - t, x0 = x - X0, y0 = y - Y0, i1, j1, perm = this._perm; if (x0 > y0) { i1 = 1; j1 = 0; } else { i1 = 0; j1 = 1; } var x1 = x0 - i1 + G2, y1 = y0 - j1 + G2, x2 = x0 - 1 + 2 * G2, y2 = y0 - 1 + 2 * G2, ii = i & 255, jj = j & 255, gi0 = perm[ii + perm[jj]] % 12, gi1 = perm[ii + i1 + perm[jj + j1]] % 12, gi2 = perm[ii + 1 + perm[jj + 1]] % 12, t0 = 0.5 - x0 * x0 - y0 * y0; if (t0 < 0) { n0 = 0; } else { t0 *= t0; n0 = t0 * t0 * _dot2d(GRAD3[gi0], x0, y0); } var t1 = 0.5 - x1 * x1 - y1 * y1; if (t1 < 0) { n1 = 0; } else { t1 *= t1; n1 = t1 * t1 * _dot2d(GRAD3[gi1], x1, y1); } var t2 = 0.5 - x2 * x2 - y2 * y2; if (t2 < 0) { n2 = 0; } else { t2 *= t2; n2 = t2 * t2 * _dot2d(GRAD3[gi2], x2, y2); } return 70 * (n0 + n1 + n2); } }); function createClassic(seed) { return new ClassicNoise(seed); } function createSimpleX(seed) { return new SimplexNoise(seed); } Noise = { GRAD3: GRAD3, GRAD4: GRAD4, SIMPLEX: SIMPLEX, ClassicNoise: ClassicNoise, SimplexNoise: SimplexNoise, createClassic: createClassic, createSimpleX: createSimpleX }; module.exports = Noise;