Created
May 22, 2017 16:45
-
-
Save davidguttman/ed4ed18399995451cb6b4d3c06ce544b to your computer and use it in GitHub Desktop.
Revisions
-
davidguttman created this gist
May 22, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,149 @@ var Simplex = require('perlin-simplex') var Delaunator = require('delaunator') var getDistance = require('euclidean-distance') var simplex = new Simplex() var SPEED = 0.001 var N_POINTS = 200 document.body.style.background = 'rgb(20, 20, 20)' var stage = createStage() document.body.appendChild(stage) var points = createPoints(N_POINTS) var triangles = createTrianges(points) stage.appendChild(triangles.el) window.requestAnimationFrame(updateLoop) function updateLoop () { window.requestAnimationFrame(updateLoop) points.forEach(function (point) { point.update() }) triangles.update(points) } function createPoints (n) { var points = [] for (var i = 0; i < n; i++) { points.push({ x: Math.random(), y: Math.random(), theta: Math.random() * 2 * Math.PI, update: updatePoint }) } return points } function updatePoint () { var nx = this.x * 5 var ny = this.y * 10 var nz = Date.now() / 1000 var s = simplex.noise3d(nx, ny, nz) var theta = s * 2 * Math.PI this.theta = (0.01 * theta) + (0.99 * this.theta) this.x += SPEED * Math.cos(this.theta) this.y += SPEED * Math.sin(this.theta) this.x = mod(this.x, 1) this.y = mod(this.y, 1) } function createTrianges (points) { var viewBox = [0, 0, 1, 1].join(' ') var pathData = createPathData(points) var parent = document.createElement('div') parent.style.width = '100%' parent.style.height = '100%' parent.innerHTML = ` <svg xmlns='http://www.w3.org/svg/2000' viewBox='${viewBox}' width='100%' height='100%' stroke='none' fill='none'> ${pathData} </svg> ` var svg = parent.children[0] return { el: parent, update: function (points) { svg.innerHTML = createPathData(points) } } } function createPathData (points) { var coords = points.map(function (point) { return [point.x, point.y] }) var triangles = new Delaunator(coords).triangles var pathData = [] for (var i = 0; i < triangles.length; i += 3) { pathData.push(createTrianglePath( coords[triangles[i + 0]], coords[triangles[i + 1]], coords[triangles[i + 2]] )) } return pathData.join('\n') } function createTrianglePath (pa, pb, pc) { var x0 = pa[0] var y0 = pa[1] var x1 = pb[0] var y1 = pb[1] var x2 = pc[0] var y2 = pc[1] var d = [ 'M', x0, y0, 'L', x1, y1, 'L', x2, y2, 'L', x0, y0 ].join(' ') var eq = equalness(x0, y0, x1, y1, x2, y2) eq = eq * eq var b = Math.floor(30 + (eq * 130)) var fill = `rgb(${b}, ${b}, ${b})` return `<path d='${d}' fill='${fill}' stroke='none' />` } function equalness (x0, y0, x1, y1, x2, y2) { var a = getDistance([x0, y0], [x1, y1]) var b = getDistance([x0, y0], [x2, y2]) var c = getDistance([x2, y2], [x1, y1]) var diff = Math.abs(a - b) + Math.abs(a - c) + Math.abs(b - c) return 1 - (diff / (a + b + c)) } function createStage (w, h) { var stage = document.createElement('div') stage.style.position = 'absolute' stage.style.top = '10%' stage.style.left = '10%' stage.style.width = '80%' stage.style.height = '80%' return stage } function mod (a, n) { return ((a % n) + n) % n } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,810 @@ setTimeout(function(){ ;require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"perlin-simplex":[function(require,module,exports){ // https://gist.github.com/banksean/304522 // // Ported from Stefan Gustavson's java implementation // http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf // Read Stefan's excellent paper for details on how this code works. // // Sean McCullough banksean@gmail.com /** * You can pass in a random number generator object if you like. * It is assumed to have a random() method. */ module.exports = SimplexNoise = function(r) { if (r == undefined) r = Math; this.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]]; this.p = []; for (var i=0; i<256; i++) { this.p[i] = Math.floor(r.random()*256); } // To remove the need for index wrapping, double the permutation table length this.perm = []; for(var i=0; i<512; i++) { this.perm[i]=this.p[i & 255]; } // A lookup table to traverse the simplex around a given point in 4D. // Details can be found where this table is used, in the 4D noise method. this.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]]; }; SimplexNoise.prototype.dot = function(g, x, y) { return g[0]*x + g[1]*y; }; SimplexNoise.prototype.noise = function(xin, yin) { var n0, n1, n2; // Noise contributions from the three corners // Skew the input space to determine which simplex cell we're in var F2 = 0.5*(Math.sqrt(3.0)-1.0); var s = (xin+yin)*F2; // Hairy factor for 2D var i = Math.floor(xin+s); var j = Math.floor(yin+s); var G2 = (3.0-Math.sqrt(3.0))/6.0; var t = (i+j)*G2; var X0 = i-t; // Unskew the cell origin back to (x,y) space var Y0 = j-t; var x0 = xin-X0; // The x,y distances from the cell origin var y0 = yin-Y0; // For the 2D case, the simplex shape is an equilateral triangle. // Determine which simplex we are in. var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords if(x0>y0) {i1=1; j1=0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) else {i1=0; j1=1;} // upper triangle, YX order: (0,0)->(0,1)->(1,1) // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where // c = (3-sqrt(3))/6 var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords var y1 = y0 - j1 + G2; var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords var y2 = y0 - 1.0 + 2.0 * G2; // Work out the hashed gradient indices of the three simplex corners var ii = i & 255; var jj = j & 255; var gi0 = this.perm[ii+this.perm[jj]] % 12; var gi1 = this.perm[ii+i1+this.perm[jj+j1]] % 12; var gi2 = this.perm[ii+1+this.perm[jj+1]] % 12; // Calculate the contribution from the three corners var t0 = 0.5 - x0*x0-y0*y0; if(t0<0) n0 = 0.0; else { t0 *= t0; n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0); // (x,y) of grad3 used for 2D gradient } var t1 = 0.5 - x1*x1-y1*y1; if(t1<0) n1 = 0.0; else { t1 *= t1; n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1); } var t2 = 0.5 - x2*x2-y2*y2; if(t2<0) n2 = 0.0; else { t2 *= t2; n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2); } // Add contributions from each corner to get the final noise value. // The result is scaled to return values in the interval [-1,1]. return 70.0 * (n0 + n1 + n2); }; // 3D simplex noise SimplexNoise.prototype.noise3d = function(xin, yin, zin) { var n0, n1, n2, n3; // Noise contributions from the four corners // Skew the input space to determine which simplex cell we're in var F3 = 1.0/3.0; var s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D var i = Math.floor(xin+s); var j = Math.floor(yin+s); var k = Math.floor(zin+s); var G3 = 1.0/6.0; // Very nice and simple unskew factor, too var t = (i+j+k)*G3; var X0 = i-t; // Unskew the cell origin back to (x,y,z) space var Y0 = j-t; var Z0 = k-t; var x0 = xin-X0; // The x,y,z distances from the cell origin var y0 = yin-Y0; var z0 = zin-Z0; // For the 3D case, the simplex shape is a slightly irregular tetrahedron. // Determine which simplex we are in. var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords if(x0>=y0) { if(y0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order } else { // x0<y0 if(y0<z0) { i1=0; j1=0; k1=1; i2=0; j2=1; k2=1; } // Z Y X order else if(x0<z0) { i1=0; j1=1; k1=0; i2=0; j2=1; k2=1; } // Y Z X order else { i1=0; j1=1; k1=0; i2=1; j2=1; k2=0; } // Y X Z order } // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where // c = 1/6. var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords var y1 = y0 - j1 + G3; var z1 = z0 - k1 + G3; var x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords var y2 = y0 - j2 + 2.0*G3; var z2 = z0 - k2 + 2.0*G3; var x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords var y3 = y0 - 1.0 + 3.0*G3; var z3 = z0 - 1.0 + 3.0*G3; // Work out the hashed gradient indices of the four simplex corners var ii = i & 255; var jj = j & 255; var kk = k & 255; var gi0 = this.perm[ii+this.perm[jj+this.perm[kk]]] % 12; var gi1 = this.perm[ii+i1+this.perm[jj+j1+this.perm[kk+k1]]] % 12; var gi2 = this.perm[ii+i2+this.perm[jj+j2+this.perm[kk+k2]]] % 12; var gi3 = this.perm[ii+1+this.perm[jj+1+this.perm[kk+1]]] % 12; // Calculate the contribution from the four corners var t0 = 0.6 - x0*x0 - y0*y0 - z0*z0; if(t0<0) n0 = 0.0; else { t0 *= t0; n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0, z0); } var t1 = 0.6 - x1*x1 - y1*y1 - z1*z1; if(t1<0) n1 = 0.0; else { t1 *= t1; n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1, z1); } var t2 = 0.6 - x2*x2 - y2*y2 - z2*z2; if(t2<0) n2 = 0.0; else { t2 *= t2; n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2, z2); } var t3 = 0.6 - x3*x3 - y3*y3 - z3*z3; if(t3<0) n3 = 0.0; else { t3 *= t3; n3 = t3 * t3 * this.dot(this.grad3[gi3], x3, y3, z3); } // Add contributions from each corner to get the final noise value. // The result is scaled to stay just inside [-1,1] return 32.0*(n0 + n1 + n2 + n3); }; },{}]},{},[]) //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsInBlcmxpbi1zaW1wbGV4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vYmFua3NlYW4vMzA0NTIyXG4vL1xuLy8gUG9ydGVkIGZyb20gU3RlZmFuIEd1c3RhdnNvbidzIGphdmEgaW1wbGVtZW50YXRpb25cbi8vIGh0dHA6Ly9zdGFmZnd3dy5pdG4ubGl1LnNlL35zdGVndS9zaW1wbGV4bm9pc2Uvc2ltcGxleG5vaXNlLnBkZlxuLy8gUmVhZCBTdGVmYW4ncyBleGNlbGxlbnQgcGFwZXIgZm9yIGRldGFpbHMgb24gaG93IHRoaXMgY29kZSB3b3Jrcy5cbi8vXG4vLyBTZWFuIE1jQ3VsbG91Z2ggYmFua3NlYW5AZ21haWwuY29tXG5cbi8qKlxuICogWW91IGNhbiBwYXNzIGluIGEgcmFuZG9tIG51bWJlciBnZW5lcmF0b3Igb2JqZWN0IGlmIHlvdSBsaWtlLlxuICogSXQgaXMgYXNzdW1lZCB0byBoYXZlIGEgcmFuZG9tKCkgbWV0aG9kLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IFNpbXBsZXhOb2lzZSA9IGZ1bmN0aW9uKHIpIHtcbiAgaWYgKHIgPT0gdW5kZWZpbmVkKSByID0gTWF0aDtcbiAgdGhpcy5ncmFkMyA9IFtbMSwxLDBdLFstMSwxLDBdLFsxLC0xLDBdLFstMSwtMSwwXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMSwwLDFdLFstMSwwLDFdLFsxLDAsLTFdLFstMSwwLC0xXSwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbMCwxLDFdLFswLC0xLDFdLFswLDEsLTFdLFswLC0xLC0xXV07IFxuICB0aGlzLnAgPSBbXTtcbiAgZm9yICh2YXIgaT0wOyBpPDI1NjsgaSsrKSB7XG4gICAgdGhpcy5wW2ldID0gTWF0aC5mbG9vcihyLnJhbmRvbSgpKjI1Nik7XG4gIH1cbiAgLy8gVG8gcmVtb3ZlIHRoZSBuZWVkIGZvciBpbmRleCB3cmFwcGluZywgZG91YmxlIHRoZSBwZXJtdXRhdGlvbiB0YWJsZSBsZW5ndGggXG4gIHRoaXMucGVybSA9IFtdOyBcbiAgZm9yKHZhciBpPTA7IGk8NTEyOyBpKyspIHtcbiAgICB0aGlzLnBlcm1baV09dGhpcy5wW2kgJiAyNTVdO1xuICB9IFxuXG4gIC8vIEEgbG9va3VwIHRhYmxlIHRvIHRyYXZlcnNlIHRoZSBzaW1wbGV4IGFyb3VuZCBhIGdpdmVuIHBvaW50IGluIDRELiBcbiAgLy8gRGV0YWlscyBjYW4gYmUgZm91bmQgd2hlcmUgdGhpcyB0YWJsZSBpcyB1c2VkLCBpbiB0aGUgNEQgbm9pc2UgbWV0aG9kLiBcbiAgdGhpcy5zaW1wbGV4ID0gWyBcbiAgICBbMCwxLDIsM10sWzAsMSwzLDJdLFswLDAsMCwwXSxbMCwyLDMsMV0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzEsMiwzLDBdLCBcbiAgICBbMCwyLDEsM10sWzAsMCwwLDBdLFswLDMsMSwyXSxbMCwzLDIsMV0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzEsMywyLDBdLCBcbiAgICBbMCwwLDAsMF0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzAsMCwwLDBdLCBcbiAgICBbMSwyLDAsM10sWzAsMCwwLDBdLFsxLDMsMCwyXSxbMCwwLDAsMF0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMiwzLDAsMV0sWzIsMywxLDBdLCBcbiAgICBbMSwwLDIsM10sWzEsMCwzLDJdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzAsMCwwLDBdLFsyLDAsMywxXSxbMCwwLDAsMF0sWzIsMSwzLDBdLCBcbiAgICBbMCwwLDAsMF0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzAsMCwwLDBdLCBcbiAgICBbMiwwLDEsM10sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzMsMCwxLDJdLFszLDAsMiwxXSxbMCwwLDAsMF0sWzMsMSwyLDBdLCBcbiAgICBbMiwxLDAsM10sWzAsMCwwLDBdLFswLDAsMCwwXSxbMCwwLDAsMF0sWzMsMSwwLDJdLFswLDAsMCwwXSxbMywyLDAsMV0sWzMsMiwxLDBdXTsgXG59O1xuXG5TaW1wbGV4Tm9pc2UucHJvdG90eXBlLmRvdCA9IGZ1bmN0aW9uKGcsIHgsIHkpIHsgXG4gIHJldHVybiBnWzBdKnggKyBnWzFdKnk7XG59O1xuXG5TaW1wbGV4Tm9pc2UucHJvdG90eXBlLm5vaXNlID0gZnVuY3Rpb24oeGluLCB5aW4pIHsgXG4gIHZhciBuMCwgbjEsIG4yOyAvLyBOb2lzZSBjb250cmlidXRpb25zIGZyb20gdGhlIHRocmVlIGNvcm5lcnMgXG4gIC8vIFNrZXcgdGhlIGlucHV0IHNwYWNlIHRvIGRldGVybWluZSB3aGljaCBzaW1wbGV4IGNlbGwgd2UncmUgaW4gXG4gIHZhciBGMiA9IDAuNSooTWF0aC5zcXJ0KDMuMCktMS4wKTsgXG4gIHZhciBzID0gKHhpbit5aW4pKkYyOyAvLyBIYWlyeSBmYWN0b3IgZm9yIDJEIFxuICB2YXIgaSA9IE1hdGguZmxvb3IoeGluK3MpOyBcbiAgdmFyIGogPSBNYXRoLmZsb29yKHlpbitzKTsgXG4gIHZhciBHMiA9ICgzLjAtTWF0aC5zcXJ0KDMuMCkpLzYuMDsgXG4gIHZhciB0ID0gKGkraikqRzI7IFxuICB2YXIgWDAgPSBpLXQ7IC8vIFVuc2tldyB0aGUgY2VsbCBvcmlnaW4gYmFjayB0byAoeCx5KSBzcGFjZSBcbiAgdmFyIFkwID0gai10OyBcbiAgdmFyIHgwID0geGluLVgwOyAvLyBUaGUgeCx5IGRpc3RhbmNlcyBmcm9tIHRoZSBjZWxsIG9yaWdpbiBcbiAgdmFyIHkwID0geWluLVkwOyBcbiAgLy8gRm9yIHRoZSAyRCBjYXNlLCB0aGUgc2ltcGxleCBzaGFwZSBpcyBhbiBlcXVpbGF0ZXJhbCB0cmlhbmdsZS4gXG4gIC8vIERldGVybWluZSB3aGljaCBzaW1wbGV4IHdlIGFyZSBpbi4gXG4gIHZhciBpMSwgajE7IC8vIE9mZnNldHMgZm9yIHNlY29uZCAobWlkZGxlKSBjb3JuZXIgb2Ygc2ltcGxleCBpbiAoaSxqKSBjb29yZHMgXG4gIGlmKHgwPnkwKSB7aTE9MTsgajE9MDt9IC8vIGxvd2VyIHRyaWFuZ2xlLCBYWSBvcmRlcjogKDAsMCktPigxLDApLT4oMSwxKSBcbiAgZWxzZSB7aTE9MDsgajE9MTt9ICAgICAgLy8gdXBwZXIgdHJpYW5nbGUsIFlYIG9yZGVyOiAoMCwwKS0+KDAsMSktPigxLDEpIFxuICAvLyBBIHN0ZXAgb2YgKDEsMCkgaW4gKGksaikgbWVhbnMgYSBzdGVwIG9mICgxLWMsLWMpIGluICh4LHkpLCBhbmQgXG4gIC8vIGEgc3RlcCBvZiAoMCwxKSBpbiAoaSxqKSBtZWFucyBhIHN0ZXAgb2YgKC1jLDEtYykgaW4gKHgseSksIHdoZXJlIFxuICAvLyBjID0gKDMtc3FydCgzKSkvNiBcbiAgdmFyIHgxID0geDAgLSBpMSArIEcyOyAvLyBPZmZzZXRzIGZvciBtaWRkbGUgY29ybmVyIGluICh4LHkpIHVuc2tld2VkIGNvb3JkcyBcbiAgdmFyIHkxID0geTAgLSBqMSArIEcyOyBcbiAgdmFyIHgyID0geDAgLSAxLjAgKyAyLjAgKiBHMjsgLy8gT2Zmc2V0cyBmb3IgbGFzdCBjb3JuZXIgaW4gKHgseSkgdW5za2V3ZWQgY29vcmRzIFxuICB2YXIgeTIgPSB5MCAtIDEuMCArIDIuMCAqIEcyOyBcbiAgLy8gV29yayBvdXQgdGhlIGhhc2hlZCBncmFkaWVudCBpbmRpY2VzIG9mIHRoZSB0aHJlZSBzaW1wbGV4IGNvcm5lcnMgXG4gIHZhciBpaSA9IGkgJiAyNTU7IFxuICB2YXIgamogPSBqICYgMjU1OyBcbiAgdmFyIGdpMCA9IHRoaXMucGVybVtpaSt0aGlzLnBlcm1bampdXSAlIDEyOyBcbiAgdmFyIGdpMSA9IHRoaXMucGVybVtpaStpMSt0aGlzLnBlcm1bamorajFdXSAlIDEyOyBcbiAgdmFyIGdpMiA9IHRoaXMucGVybVtpaSsxK3RoaXMucGVybVtqaisxXV0gJSAxMjsgXG4gIC8vIENhbGN1bGF0ZSB0aGUgY29udHJpYnV0aW9uIGZyb20gdGhlIHRocmVlIGNvcm5lcnMgXG4gIHZhciB0MCA9IDAuNSAtIHgwKngwLXkwKnkwOyBcbiAgaWYodDA8MCkgbjAgPSAwLjA7IFxuICBlbHNlIHsgXG4gICAgdDAgKj0gdDA7IFxuICAgIG4wID0gdDAgKiB0MCAqIHRoaXMuZG90KHRoaXMuZ3JhZDNbZ2kwXSwgeDAsIHkwKTsgIC8vICh4LHkpIG9mIGdyYWQzIHVzZWQgZm9yIDJEIGdyYWRpZW50IFxuICB9IFxuICB2YXIgdDEgPSAwLjUgLSB4MSp4MS15MSp5MTsgXG4gIGlmKHQxPDApIG4xID0gMC4wOyBcbiAgZWxzZSB7IFxuICAgIHQxICo9IHQxOyBcbiAgICBuMSA9IHQxICogdDEgKiB0aGlzLmRvdCh0aGlzLmdyYWQzW2dpMV0sIHgxLCB5MSk7IFxuICB9XG4gIHZhciB0MiA9IDAuNSAtIHgyKngyLXkyKnkyOyBcbiAgaWYodDI8MCkgbjIgPSAwLjA7IFxuICBlbHNlIHsgXG4gICAgdDIgKj0gdDI7IFxuICAgIG4yID0gdDIgKiB0MiAqIHRoaXMuZG90KHRoaXMuZ3JhZDNbZ2kyXSwgeDIsIHkyKTsgXG4gIH0gXG4gIC8vIEFkZCBjb250cmlidXRpb25zIGZyb20gZWFjaCBjb3JuZXIgdG8gZ2V0IHRoZSBmaW5hbCBub2lzZSB2YWx1ZS4gXG4gIC8vIFRoZSByZXN1bHQgaXMgc2NhbGVkIHRvIHJldHVybiB2YWx1ZXMgaW4gdGhlIGludGVydmFsIFstMSwxXS4gXG4gIHJldHVybiA3MC4wICogKG4wICsgbjEgKyBuMik7IFxufTtcblxuLy8gM0Qgc2ltcGxleCBub2lzZSBcblNpbXBsZXhOb2lzZS5wcm90b3R5cGUubm9pc2UzZCA9IGZ1bmN0aW9uKHhpbiwgeWluLCB6aW4pIHsgXG4gIHZhciBuMCwgbjEsIG4yLCBuMzsgLy8gTm9pc2UgY29udHJpYnV0aW9ucyBmcm9tIHRoZSBmb3VyIGNvcm5lcnMgXG4gIC8vIFNrZXcgdGhlIGlucHV0IHNwYWNlIHRvIGRldGVybWluZSB3aGljaCBzaW1wbGV4IGNlbGwgd2UncmUgaW4gXG4gIHZhciBGMyA9IDEuMC8zLjA7IFxuICB2YXIgcyA9ICh4aW4reWluK3ppbikqRjM7IC8vIFZlcnkgbmljZSBhbmQgc2ltcGxlIHNrZXcgZmFjdG9yIGZvciAzRCBcbiAgdmFyIGkgPSBNYXRoLmZsb29yKHhpbitzKTsgXG4gIHZhciBqID0gTWF0aC5mbG9vcih5aW4rcyk7IFxuICB2YXIgayA9IE1hdGguZmxvb3IoemluK3MpOyBcbiAgdmFyIEczID0gMS4wLzYuMDsgLy8gVmVyeSBuaWNlIGFuZCBzaW1wbGUgdW5za2V3IGZhY3RvciwgdG9vIFxuICB2YXIgdCA9IChpK2oraykqRzM7IFxuICB2YXIgWDAgPSBpLXQ7IC8vIFVuc2tldyB0aGUgY2VsbCBvcmlnaW4gYmFjayB0byAoeCx5LHopIHNwYWNlIFxuICB2YXIgWTAgPSBqLXQ7IFxuICB2YXIgWjAgPSBrLXQ7IFxuICB2YXIgeDAgPSB4aW4tWDA7IC8vIFRoZSB4LHkseiBkaXN0YW5jZXMgZnJvbSB0aGUgY2VsbCBvcmlnaW4gXG4gIHZhciB5MCA9IHlpbi1ZMDsgXG4gIHZhciB6MCA9IHppbi1aMDsgXG4gIC8vIEZvciB0aGUgM0QgY2FzZSwgdGhlIHNpbXBsZXggc2hhcGUgaXMgYSBzbGlnaHRseSBpcnJlZ3VsYXIgdGV0cmFoZWRyb24uIFxuICAvLyBEZXRlcm1pbmUgd2hpY2ggc2ltcGxleCB3ZSBhcmUgaW4uIFxuICB2YXIgaTEsIGoxLCBrMTsgLy8gT2Zmc2V0cyBmb3Igc2Vjb25kIGNvcm5lciBvZiBzaW1wbGV4IGluIChpLGosaykgY29vcmRzIFxuICB2YXIgaTIsIGoyLCBrMjsgLy8gT2Zmc2V0cyBmb3IgdGhpcmQgY29ybmVyIG9mIHNpbXBsZXggaW4gKGksaixrKSBjb29yZHMgXG4gIGlmKHgwPj15MCkgeyBcbiAgICBpZih5MD49ejApIFxuICAgICAgeyBpMT0xOyBqMT0wOyBrMT0wOyBpMj0xOyBqMj0xOyBrMj0wOyB9IC8vIFggWSBaIG9yZGVyIFxuICAgICAgZWxzZSBpZih4MD49ejApIHsgaTE9MTsgajE9MDsgazE9MDsgaTI9MTsgajI9MDsgazI9MTsgfSAvLyBYIFogWSBvcmRlciBcbiAgICAgIGVsc2UgeyBpMT0wOyBqMT0wOyBrMT0xOyBpMj0xOyBqMj0wOyBrMj0xOyB9IC8vIFogWCBZIG9yZGVyIFxuICAgIH0gXG4gIGVsc2UgeyAvLyB4MDx5MCBcbiAgICBpZih5MDx6MCkgeyBpMT0wOyBqMT0wOyBrMT0xOyBpMj0wOyBqMj0xOyBrMj0xOyB9IC8vIFogWSBYIG9yZGVyIFxuICAgIGVsc2UgaWYoeDA8ejApIHsgaTE9MDsgajE9MTsgazE9MDsgaTI9MDsgajI9MTsgazI9MTsgfSAvLyBZIFogWCBvcmRlciBcbiAgICBlbHNlIHsgaTE9MDsgajE9MTsgazE9MDsgaTI9MTsgajI9MTsgazI9MDsgfSAvLyBZIFggWiBvcmRlciBcbiAgfSBcbiAgLy8gQSBzdGVwIG9mICgxLDAsMCkgaW4gKGksaixrKSBtZWFucyBhIHN0ZXAgb2YgKDEtYywtYywtYykgaW4gKHgseSx6KSwgXG4gIC8vIGEgc3RlcCBvZiAoMCwxLDApIGluIChpLGosaykgbWVhbnMgYSBzdGVwIG9mICgtYywxLWMsLWMpIGluICh4LHkseiksIGFuZCBcbiAgLy8gYSBzdGVwIG9mICgwLDAsMSkgaW4gKGksaixrKSBtZWFucyBhIHN0ZXAgb2YgKC1jLC1jLDEtYykgaW4gKHgseSx6KSwgd2hlcmUgXG4gIC8vIGMgPSAxLzYuXG4gIHZhciB4MSA9IHgwIC0gaTEgKyBHMzsgLy8gT2Zmc2V0cyBmb3Igc2Vjb25kIGNvcm5lciBpbiAoeCx5LHopIGNvb3JkcyBcbiAgdmFyIHkxID0geTAgLSBqMSArIEczOyBcbiAgdmFyIHoxID0gejAgLSBrMSArIEczOyBcbiAgdmFyIHgyID0geDAgLSBpMiArIDIuMCpHMzsgLy8gT2Zmc2V0cyBmb3IgdGhpcmQgY29ybmVyIGluICh4LHkseikgY29vcmRzIFxuICB2YXIgeTIgPSB5MCAtIGoyICsgMi4wKkczOyBcbiAgdmFyIHoyID0gejAgLSBrMiArIDIuMCpHMzsgXG4gIHZhciB4MyA9IHgwIC0gMS4wICsgMy4wKkczOyAvLyBPZmZzZXRzIGZvciBsYXN0IGNvcm5lciBpbiAoeCx5LHopIGNvb3JkcyBcbiAgdmFyIHkzID0geTAgLSAxLjAgKyAzLjAqRzM7IFxuICB2YXIgejMgPSB6MCAtIDEuMCArIDMuMCpHMzsgXG4gIC8vIFdvcmsgb3V0IHRoZSBoYXNoZWQgZ3JhZGllbnQgaW5kaWNlcyBvZiB0aGUgZm91ciBzaW1wbGV4IGNvcm5lcnMgXG4gIHZhciBpaSA9IGkgJiAyNTU7IFxuICB2YXIgamogPSBqICYgMjU1OyBcbiAgdmFyIGtrID0gayAmIDI1NTsgXG4gIHZhciBnaTAgPSB0aGlzLnBlcm1baWkrdGhpcy5wZXJtW2pqK3RoaXMucGVybVtra11dXSAlIDEyOyBcbiAgdmFyIGdpMSA9IHRoaXMucGVybVtpaStpMSt0aGlzLnBlcm1bamorajErdGhpcy5wZXJtW2trK2sxXV1dICUgMTI7IFxuICB2YXIgZ2kyID0gdGhpcy5wZXJtW2lpK2kyK3RoaXMucGVybVtqaitqMit0aGlzLnBlcm1ba2srazJdXV0gJSAxMjsgXG4gIHZhciBnaTMgPSB0aGlzLnBlcm1baWkrMSt0aGlzLnBlcm1bamorMSt0aGlzLnBlcm1ba2srMV1dXSAlIDEyOyBcbiAgLy8gQ2FsY3VsYXRlIHRoZSBjb250cmlidXRpb24gZnJvbSB0aGUgZm91ciBjb3JuZXJzIFxuICB2YXIgdDAgPSAwLjYgLSB4MCp4MCAtIHkwKnkwIC0gejAqejA7IFxuICBpZih0MDwwKSBuMCA9IDAuMDsgXG4gIGVsc2UgeyBcbiAgICB0MCAqPSB0MDsgXG4gICAgbjAgPSB0MCAqIHQwICogdGhpcy5kb3QodGhpcy5ncmFkM1tnaTBdLCB4MCwgeTAsIHowKTsgXG4gIH1cbiAgdmFyIHQxID0gMC42IC0geDEqeDEgLSB5MSp5MSAtIHoxKnoxOyBcbiAgaWYodDE8MCkgbjEgPSAwLjA7IFxuICBlbHNlIHsgXG4gICAgdDEgKj0gdDE7IFxuICAgIG4xID0gdDEgKiB0MSAqIHRoaXMuZG90KHRoaXMuZ3JhZDNbZ2kxXSwgeDEsIHkxLCB6MSk7IFxuICB9IFxuICB2YXIgdDIgPSAwLjYgLSB4Mip4MiAtIHkyKnkyIC0gejIqejI7IFxuICBpZih0MjwwKSBuMiA9IDAuMDsgXG4gIGVsc2UgeyBcbiAgICB0MiAqPSB0MjsgXG4gICAgbjIgPSB0MiAqIHQyICogdGhpcy5kb3QodGhpcy5ncmFkM1tnaTJdLCB4MiwgeTIsIHoyKTsgXG4gIH0gXG4gIHZhciB0MyA9IDAuNiAtIHgzKngzIC0geTMqeTMgLSB6Myp6MzsgXG4gIGlmKHQzPDApIG4zID0gMC4wOyBcbiAgZWxzZSB7IFxuICAgIHQzICo9IHQzOyBcbiAgICBuMyA9IHQzICogdDMgKiB0aGlzLmRvdCh0aGlzLmdyYWQzW2dpM10sIHgzLCB5MywgejMpOyBcbiAgfSBcbiAgLy8gQWRkIGNvbnRyaWJ1dGlvbnMgZnJvbSBlYWNoIGNvcm5lciB0byBnZXQgdGhlIGZpbmFsIG5vaXNlIHZhbHVlLiBcbiAgLy8gVGhlIHJlc3VsdCBpcyBzY2FsZWQgdG8gc3RheSBqdXN0IGluc2lkZSBbLTEsMV0gXG4gIHJldHVybiAzMi4wKihuMCArIG4xICsgbjIgKyBuMyk7IFxufTsiXX0= require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"delaunator":[function(require,module,exports){ 'use strict'; module.exports = Delaunator; function Delaunator(points, getX, getY) { if (!getX) getX = defaultGetX; if (!getY) getY = defaultGetY; var minX = Infinity; var minY = Infinity; var maxX = -Infinity; var maxY = -Infinity; var coords = this.coords = []; var ids = this.ids = new Uint32Array(points.length); for (var i = 0; i < points.length; i++) { var p = points[i]; var x = getX(p); var y = getY(p); ids[i] = i; coords[2 * i] = x; coords[2 * i + 1] = y; if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } var cx = (minX + maxX) / 2; var cy = (minY + maxY) / 2; var minDist = Infinity; var i0, i1, i2; // pick a seed point close to the centroid for (i = 0; i < points.length; i++) { var d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]); if (d < minDist) { i0 = i; minDist = d; } } minDist = Infinity; // find the point closest to the seed for (i = 0; i < points.length; i++) { if (i === i0) continue; d = dist(coords[2 * i0], coords[2 * i0 + 1], coords[2 * i], coords[2 * i + 1]); if (d < minDist && d > 0) { i1 = i; minDist = d; } } var minRadius = Infinity; // find the third point which forms the smallest circumcircle with the first two for (i = 0; i < points.length; i++) { if (i === i0 || i === i1) continue; var r = circumradius( coords[2 * i0], coords[2 * i0 + 1], coords[2 * i1], coords[2 * i1 + 1], coords[2 * i], coords[2 * i + 1]); if (r < minRadius) { i2 = i; minRadius = r; } } if (minRadius === Infinity) { throw new Error('No Delaunay triangulation exists for this input.'); } // swap the order of the seed points for counter-clockwise orientation if (area(coords[2 * i0], coords[2 * i0 + 1], coords[2 * i1], coords[2 * i1 + 1], coords[2 * i2], coords[2 * i2 + 1]) < 0) { var tmp = i1; i1 = i2; i2 = tmp; } var i0x = coords[2 * i0]; var i0y = coords[2 * i0 + 1]; var i1x = coords[2 * i1]; var i1y = coords[2 * i1 + 1]; var i2x = coords[2 * i2]; var i2y = coords[2 * i2 + 1]; var center = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y); this._cx = center.x; this._cy = center.y; // sort the points by distance from the seed triangle circumcenter quicksort(ids, coords, 0, ids.length - 1, center.x, center.y); // initialize a hash table for storing edges of the advancing convex hull this._hashSize = Math.ceil(Math.sqrt(points.length)); this._hash = []; for (i = 0; i < this._hashSize; i++) this._hash[i] = null; // initialize a circular doubly-linked list that will hold an advancing convex hull var e = this.hull = insertNode(coords, i0); this._hashEdge(e); e.t = 0; e = insertNode(coords, i1, e); this._hashEdge(e); e.t = 1; e = insertNode(coords, i2, e); this._hashEdge(e); e.t = 2; var maxTriangles = 2 * points.length - 5; var triangles = this.triangles = new Uint32Array(maxTriangles * 3); triangles[0] = i0; triangles[1] = i1; triangles[2] = i2; this.trianglesLen = 3; var adjacent = this.adjacent = new Int32Array(maxTriangles * 3); adjacent[0] = -1; adjacent[1] = -1; adjacent[2] = -1; var xp, yp; for (var k = 0; k < ids.length; k++) { i = ids[k]; x = coords[2 * i]; y = coords[2 * i + 1]; // skip duplicate points if (x === xp && y === yp) continue; xp = x; yp = y; // skip seed triangle points if ((x === i0x && y === i0y) || (x === i1x && y === i1y) || (x === i2x && y === i2y)) continue; // find a visible edge on the convex hull using edge hash var startKey = this._hashKey(x, y); var key = startKey; var start; do { start = this._hash[key]; key = (key + 1) % this._hashSize; } while ((!start || start.removed) && key !== startKey); e = start; while (area(x, y, e.x, e.y, e.next.x, e.next.y) >= 0) { e = e.next; if (e === start) { throw new Error('Something is wrong with the input points.'); } } var walkBack = e === start; // add the first triangle from the point var t = this._addTriangle(i, e); adjacent[t] = -1; adjacent[t + 1] = -1; this._link(t + 2, e.t); e.t = t; // keep track of boundary triangles on the hull e = insertNode(coords, i, e); // recursively flip triangles from the point until they satisfy the Delaunay condition e.t = this._legalize(t + 2); // walk forward through the hull, adding more triangles and flipping recursively var q = e.next; while (area(x, y, q.x, q.y, q.next.x, q.next.y) < 0) { t = this._addTriangle(i, q); this._link(t, q.prev.t); adjacent[t + 1] = -1; this._link(t + 2, q.t); q.prev.t = this._legalize(t + 2); this.hull = removeNode(q); q = q.next; } if (walkBack) { // walk backward from the other side, adding more triangles and flipping q = e.prev; while (area(x, y, q.prev.x, q.prev.y, q.x, q.y) < 0) { t = this._addTriangle(i, q.prev); adjacent[t] = -1; this._link(t + 1, q.t); this._link(t + 2, q.prev.t); this._legalize(t + 2); q.prev.t = t; this.hull = removeNode(q); q = q.prev; } } // save the two new edges in the hash table this._hashEdge(e); this._hashEdge(e.prev); } // trim typed triangle mesh arrays this.triangles = triangles.subarray(0, this.trianglesLen); this.adjacent = adjacent.subarray(0, this.trianglesLen); } Delaunator.prototype = { _hashEdge: function (e) { this._hash[this._hashKey(e.x, e.y)] = e; }, _hashKey: function (x, y) { var dx = x - this._cx; var dy = y - this._cy; // use pseudo-angle: a measure that monotonically increases // with real angle, but doesn't require expensive trigonometry var p = 1 - dx / (Math.abs(dx) + Math.abs(dy)); return Math.floor((2 + (dy < 0 ? -p : p)) * (this._hashSize / 4)); }, _legalize: function (a) { var triangles = this.triangles; var coords = this.coords; var adjacent = this.adjacent; var b = adjacent[a]; var a0 = a - a % 3; var b0 = b - b % 3; var al = a0 + (a + 1) % 3; var ar = a0 + (a + 2) % 3; var br = b0 + (b + 1) % 3; var bl = b0 + (b + 2) % 3; var p0 = triangles[ar]; var pr = triangles[a]; var pl = triangles[al]; var p1 = triangles[bl]; var illegal = inCircle( coords[2 * p0], coords[2 * p0 + 1], coords[2 * pr], coords[2 * pr + 1], coords[2 * pl], coords[2 * pl + 1], coords[2 * p1], coords[2 * p1 + 1]); if (illegal) { triangles[a] = p1; triangles[b] = p0; this._link(a, adjacent[bl]); this._link(b, adjacent[ar]); this._link(ar, bl); this._legalize(a); return this._legalize(br); } return ar; }, _link: function (a, b) { this.adjacent[a] = b; if (b !== -1) this.adjacent[b] = a; }, _addTriangle(i, e) { var t = this.trianglesLen; this.triangles[t] = e.i; this.triangles[t + 1] = i; this.triangles[t + 2] = e.next.i; this.trianglesLen += 3; return t; } }; function dist(ax, ay, bx, by) { var dx = ax - bx; var dy = ay - by; return dx * dx + dy * dy; } function area(px, py, qx, qy, rx, ry) { return (qy - py) * (rx - qx) - (qx - px) * (ry - qy); } function inCircle(ax, ay, bx, by, cx, cy, px, py) { ax -= px; ay -= py; bx -= px; by -= py; cx -= px; cy -= py; var ap = ax * ax + ay * ay; var bp = bx * bx + by * by; var cp = cx * cx + cy * cy; var det = ax * (by * cp - bp * cy) - ay * (bx * cp - bp * cx) + ap * (bx * cy - by * cx); return det < 0; } function circumradius(ax, ay, bx, by, cx, cy) { bx -= ax; by -= ay; cx -= ax; cy -= ay; var bl = bx * bx + by * by; var cl = cx * cx + cy * cy; if (bl === 0 || cl === 0) return Infinity; var d = bx * cy - by * cx; if (d === 0) return Infinity; var x = (cy * bl - by * cl) * 0.5 / d; var y = (bx * cl - cx * bl) * 0.5 / d; return x * x + y * y; } function circumcenter(ax, ay, bx, by, cx, cy) { bx -= ax; by -= ay; cx -= ax; cy -= ay; var bl = bx * bx + by * by; var cl = cx * cx + cy * cy; var d = bx * cy - by * cx; var x = (cy * bl - by * cl) * 0.5 / d; var y = (bx * cl - cx * bl) * 0.5 / d; return { x: ax + x, y: ay + y }; } // create a new node in a doubly linked list function insertNode(coords, i, prev) { var node = { i: i, x: coords[2 * i], y: coords[2 * i + 1], t: 0, prev: null, next: null, removed: false }; if (!prev) { node.prev = node; node.next = node; } else { node.next = prev.next; node.prev = prev; prev.next.prev = node; prev.next = node; } return node; } function removeNode(node) { node.prev.next = node.next; node.next.prev = node.prev; node.removed = true; return node.prev; } function quicksort(ids, coords, left, right, cx, cy) { var i, j, temp; if (right - left <= 20) { for (i = left + 1; i <= right; i++) { temp = ids[i]; j = i - 1; while (j >= left && compare(coords, ids[j], temp, cx, cy) > 0) ids[j + 1] = ids[j--]; ids[j + 1] = temp; } } else { var median = (left + right) >> 1; i = left + 1; j = right; swap(ids, median, i); if (compare(coords, ids[left], ids[right], cx, cy) > 0) swap(ids, left, right); if (compare(coords, ids[i], ids[right], cx, cy) > 0) swap(ids, i, right); if (compare(coords, ids[left], ids[i], cx, cy) > 0) swap(ids, left, i); temp = ids[i]; while (true) { do i++; while (compare(coords, ids[i], temp, cx, cy) < 0); do j--; while (compare(coords, ids[j], temp, cx, cy) > 0); if (j < i) break; swap(ids, i, j); } ids[left + 1] = ids[j]; ids[j] = temp; if (right - i + 1 >= j - left) { quicksort(ids, coords, i, right, cx, cy); quicksort(ids, coords, left, j - 1, cx, cy); } else { quicksort(ids, coords, left, j - 1, cx, cy); quicksort(ids, coords, i, right, cx, cy); } } } function compare(coords, i, j, cx, cy) { var d1 = dist(coords[2 * i], coords[2 * i + 1], cx, cy); var d2 = dist(coords[2 * j], coords[2 * j + 1], cx, cy); return (d1 - d2) || (coords[2 * i] - coords[2 * j]) || (coords[2 * i + 1] - coords[2 * j + 1]); } function swap(arr, i, j) { var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } function defaultGetX(p) { return p[0]; } function defaultGetY(p) { return p[1]; } },{}]},{},[]) //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImRlbGF1bmF0b3IiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IERlbGF1bmF0b3I7XG5cbmZ1bmN0aW9uIERlbGF1bmF0b3IocG9pbnRzLCBnZXRYLCBnZXRZKSB7XG5cbiAgICBpZiAoIWdldFgpIGdldFggPSBkZWZhdWx0R2V0WDtcbiAgICBpZiAoIWdldFkpIGdldFkgPSBkZWZhdWx0R2V0WTtcblxuICAgIHZhciBtaW5YID0gSW5maW5pdHk7XG4gICAgdmFyIG1pblkgPSBJbmZpbml0eTtcbiAgICB2YXIgbWF4WCA9IC1JbmZpbml0eTtcbiAgICB2YXIgbWF4WSA9IC1JbmZpbml0eTtcblxuICAgIHZhciBjb29yZHMgPSB0aGlzLmNvb3JkcyA9IFtdO1xuICAgIHZhciBpZHMgPSB0aGlzLmlkcyA9IG5ldyBVaW50MzJBcnJheShwb2ludHMubGVuZ3RoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBwID0gcG9pbnRzW2ldO1xuICAgICAgICB2YXIgeCA9IGdldFgocCk7XG4gICAgICAgIHZhciB5ID0gZ2V0WShwKTtcbiAgICAgICAgaWRzW2ldID0gaTtcbiAgICAgICAgY29vcmRzWzIgKiBpXSA9IHg7XG4gICAgICAgIGNvb3Jkc1syICogaSArIDFdID0geTtcbiAgICAgICAgaWYgKHggPCBtaW5YKSBtaW5YID0geDtcbiAgICAgICAgaWYgKHkgPCBtaW5ZKSBtaW5ZID0geTtcbiAgICAgICAgaWYgKHggPiBtYXhYKSBtYXhYID0geDtcbiAgICAgICAgaWYgKHkgPiBtYXhZKSBtYXhZID0geTtcbiAgICB9XG5cbiAgICB2YXIgY3ggPSAobWluWCArIG1heFgpIC8gMjtcbiAgICB2YXIgY3kgPSAobWluWSArIG1heFkpIC8gMjtcblxuICAgIHZhciBtaW5EaXN0ID0gSW5maW5pdHk7XG4gICAgdmFyIGkwLCBpMSwgaTI7XG5cbiAgICAvLyBwaWNrIGEgc2VlZCBwb2ludCBjbG9zZSB0byB0aGUgY2VudHJvaWRcbiAgICBmb3IgKGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBkID0gZGlzdChjeCwgY3ksIGNvb3Jkc1syICogaV0sIGNvb3Jkc1syICogaSArIDFdKTtcbiAgICAgICAgaWYgKGQgPCBtaW5EaXN0KSB7XG4gICAgICAgICAgICBpMCA9IGk7XG4gICAgICAgICAgICBtaW5EaXN0ID0gZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG1pbkRpc3QgPSBJbmZpbml0eTtcblxuICAgIC8vIGZpbmQgdGhlIHBvaW50IGNsb3Nlc3QgdG8gdGhlIHNlZWRcbiAgICBmb3IgKGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpID09PSBpMCkgY29udGludWU7XG4gICAgICAgIGQgPSBkaXN0KGNvb3Jkc1syICogaTBdLCBjb29yZHNbMiAqIGkwICsgMV0sIGNvb3Jkc1syICogaV0sIGNvb3Jkc1syICogaSArIDFdKTtcbiAgICAgICAgaWYgKGQgPCBtaW5EaXN0ICYmIGQgPiAwKSB7XG4gICAgICAgICAgICBpMSA9IGk7XG4gICAgICAgICAgICBtaW5EaXN0ID0gZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBtaW5SYWRpdXMgPSBJbmZpbml0eTtcblxuICAgIC8vIGZpbmQgdGhlIHRoaXJkIHBvaW50IHdoaWNoIGZvcm1zIHRoZSBzbWFsbGVzdCBjaXJjdW1jaXJjbGUgd2l0aCB0aGUgZmlyc3QgdHdvXG4gICAgZm9yIChpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaSA9PT0gaTAgfHwgaSA9PT0gaTEpIGNvbnRpbnVlO1xuXG4gICAgICAgIHZhciByID0gY2lyY3VtcmFkaXVzKFxuICAgICAgICAgICAgY29vcmRzWzIgKiBpMF0sIGNvb3Jkc1syICogaTAgKyAxXSxcbiAgICAgICAgICAgIGNvb3Jkc1syICogaTFdLCBjb29yZHNbMiAqIGkxICsgMV0sXG4gICAgICAgICAgICBjb29yZHNbMiAqIGldLCBjb29yZHNbMiAqIGkgKyAxXSk7XG5cbiAgICAgICAgaWYgKHIgPCBtaW5SYWRpdXMpIHtcbiAgICAgICAgICAgIGkyID0gaTtcbiAgICAgICAgICAgIG1pblJhZGl1cyA9IHI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWluUmFkaXVzID09PSBJbmZpbml0eSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIERlbGF1bmF5IHRyaWFuZ3VsYXRpb24gZXhpc3RzIGZvciB0aGlzIGlucHV0LicpO1xuICAgIH1cblxuICAgIC8vIHN3YXAgdGhlIG9yZGVyIG9mIHRoZSBzZWVkIHBvaW50cyBmb3IgY291bnRlci1jbG9ja3dpc2Ugb3JpZW50YXRpb25cbiAgICBpZiAoYXJlYShjb29yZHNbMiAqIGkwXSwgY29vcmRzWzIgKiBpMCArIDFdLFxuICAgICAgICAgICAgIGNvb3Jkc1syICogaTFdLCBjb29yZHNbMiAqIGkxICsgMV0sXG4gICAgICAgICAgICAgY29vcmRzWzIgKiBpMl0sIGNvb3Jkc1syICogaTIgKyAxXSkgPCAwKSB7XG5cbiAgICAgICAgdmFyIHRtcCA9IGkxO1xuICAgICAgICBpMSA9IGkyO1xuICAgICAgICBpMiA9IHRtcDtcbiAgICB9XG5cbiAgICB2YXIgaTB4ID0gY29vcmRzWzIgKiBpMF07XG4gICAgdmFyIGkweSA9IGNvb3Jkc1syICogaTAgKyAxXTtcbiAgICB2YXIgaTF4ID0gY29vcmRzWzIgKiBpMV07XG4gICAgdmFyIGkxeSA9IGNvb3Jkc1syICogaTEgKyAxXTtcbiAgICB2YXIgaTJ4ID0gY29vcmRzWzIgKiBpMl07XG4gICAgdmFyIGkyeSA9IGNvb3Jkc1syICogaTIgKyAxXTtcblxuICAgIHZhciBjZW50ZXIgPSBjaXJjdW1jZW50ZXIoaTB4LCBpMHksIGkxeCwgaTF5LCBpMngsIGkyeSk7XG4gICAgdGhpcy5fY3ggPSBjZW50ZXIueDtcbiAgICB0aGlzLl9jeSA9IGNlbnRlci55O1xuXG4gICAgLy8gc29ydCB0aGUgcG9pbnRzIGJ5IGRpc3RhbmNlIGZyb20gdGhlIHNlZWQgdHJpYW5nbGUgY2lyY3VtY2VudGVyXG4gICAgcXVpY2tzb3J0KGlkcywgY29vcmRzLCAwLCBpZHMubGVuZ3RoIC0gMSwgY2VudGVyLngsIGNlbnRlci55KTtcblxuICAgIC8vIGluaXRpYWxpemUgYSBoYXNoIHRhYmxlIGZvciBzdG9yaW5nIGVkZ2VzIG9mIHRoZSBhZHZhbmNpbmcgY29udmV4IGh1bGxcbiAgICB0aGlzLl9oYXNoU2l6ZSA9IE1hdGguY2VpbChNYXRoLnNxcnQocG9pbnRzLmxlbmd0aCkpO1xuICAgIHRoaXMuX2hhc2ggPSBbXTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5faGFzaFNpemU7IGkrKykgdGhpcy5faGFzaFtpXSA9IG51bGw7XG5cbiAgICAvLyBpbml0aWFsaXplIGEgY2lyY3VsYXIgZG91Ymx5LWxpbmtlZCBsaXN0IHRoYXQgd2lsbCBob2xkIGFuIGFkdmFuY2luZyBjb252ZXggaHVsbFxuICAgIHZhciBlID0gdGhpcy5odWxsID0gaW5zZXJ0Tm9kZShjb29yZHMsIGkwKTtcbiAgICB0aGlzLl9oYXNoRWRnZShlKTtcbiAgICBlLnQgPSAwO1xuICAgIGUgPSBpbnNlcnROb2RlKGNvb3JkcywgaTEsIGUpO1xuICAgIHRoaXMuX2hhc2hFZGdlKGUpO1xuICAgIGUudCA9IDE7XG4gICAgZSA9IGluc2VydE5vZGUoY29vcmRzLCBpMiwgZSk7XG4gICAgdGhpcy5faGFzaEVkZ2UoZSk7XG4gICAgZS50ID0gMjtcblxuICAgIHZhciBtYXhUcmlhbmdsZXMgPSAyICogcG9pbnRzLmxlbmd0aCAtIDU7XG4gICAgdmFyIHRyaWFuZ2xlcyA9IHRoaXMudHJpYW5nbGVzID0gbmV3IFVpbnQzMkFycmF5KG1heFRyaWFuZ2xlcyAqIDMpO1xuICAgIHRyaWFuZ2xlc1swXSA9IGkwO1xuICAgIHRyaWFuZ2xlc1sxXSA9IGkxO1xuICAgIHRyaWFuZ2xlc1syXSA9IGkyO1xuICAgIHRoaXMudHJpYW5nbGVzTGVuID0gMztcblxuICAgIHZhciBhZGphY2VudCA9IHRoaXMuYWRqYWNlbnQgPSBuZXcgSW50MzJBcnJheShtYXhUcmlhbmdsZXMgKiAzKTtcbiAgICBhZGphY2VudFswXSA9IC0xO1xuICAgIGFkamFjZW50WzFdID0gLTE7XG4gICAgYWRqYWNlbnRbMl0gPSAtMTtcblxuICAgIHZhciB4cCwgeXA7XG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBpZHMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgaSA9IGlkc1trXTtcbiAgICAgICAgeCA9IGNvb3Jkc1syICogaV07XG4gICAgICAgIHkgPSBjb29yZHNbMiAqIGkgKyAxXTtcblxuICAgICAgICAvLyBza2lwIGR1cGxpY2F0ZSBwb2ludHNcbiAgICAgICAgaWYgKHggPT09IHhwICYmIHkgPT09IHlwKSBjb250aW51ZTtcbiAgICAgICAgeHAgPSB4O1xuICAgICAgICB5cCA9IHk7XG5cbiAgICAgICAgLy8gc2tpcCBzZWVkIHRyaWFuZ2xlIHBvaW50c1xuICAgICAgICBpZiAoKHggPT09IGkweCAmJiB5ID09PSBpMHkpIHx8XG4gICAgICAgICAgICAoeCA9PT0gaTF4ICYmIHkgPT09IGkxeSkgfHxcbiAgICAgICAgICAgICh4ID09PSBpMnggJiYgeSA9PT0gaTJ5KSkgY29udGludWU7XG5cbiAgICAgICAgLy8gZmluZCBhIHZpc2libGUgZWRnZSBvbiB0aGUgY29udmV4IGh1bGwgdXNpbmcgZWRnZSBoYXNoXG4gICAgICAgIHZhciBzdGFydEtleSA9IHRoaXMuX2hhc2hLZXkoeCwgeSk7XG4gICAgICAgIHZhciBrZXkgPSBzdGFydEtleTtcbiAgICAgICAgdmFyIHN0YXJ0O1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICBzdGFydCA9IHRoaXMuX2hhc2hba2V5XTtcbiAgICAgICAgICAgIGtleSA9IChrZXkgKyAxKSAlIHRoaXMuX2hhc2hTaXplO1xuICAgICAgICB9IHdoaWxlICgoIXN0YXJ0IHx8IHN0YXJ0LnJlbW92ZWQpICYmIGtleSAhPT0gc3RhcnRLZXkpO1xuXG4gICAgICAgIGUgPSBzdGFydDtcbiAgICAgICAgd2hpbGUgKGFyZWEoeCwgeSwgZS54LCBlLnksIGUubmV4dC54LCBlLm5leHQueSkgPj0gMCkge1xuICAgICAgICAgICAgZSA9IGUubmV4dDtcbiAgICAgICAgICAgIGlmIChlID09PSBzdGFydCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignU29tZXRoaW5nIGlzIHdyb25nIHdpdGggdGhlIGlucHV0IHBvaW50cy4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB3YWxrQmFjayA9IGUgPT09IHN0YXJ0O1xuXG4gICAgICAgIC8vIGFkZCB0aGUgZmlyc3QgdHJpYW5nbGUgZnJvbSB0aGUgcG9pbnRcbiAgICAgICAgdmFyIHQgPSB0aGlzLl9hZGRUcmlhbmdsZShpLCBlKTtcbiAgICAgICAgYWRqYWNlbnRbdF0gPSAtMTtcbiAgICAgICAgYWRqYWNlbnRbdCArIDFdID0gLTE7XG4gICAgICAgIHRoaXMuX2xpbmsodCArIDIsIGUudCk7XG5cbiAgICAgICAgZS50ID0gdDsgLy8ga2VlcCB0cmFjayBvZiBib3VuZGFyeSB0cmlhbmdsZXMgb24gdGhlIGh1bGxcbiAgICAgICAgZSA9IGluc2VydE5vZGUoY29vcmRzLCBpLCBlKTtcblxuICAgICAgICAvLyByZWN1cnNpdmVseSBmbGlwIHRyaWFuZ2xlcyBmcm9tIHRoZSBwb2ludCB1bnRpbCB0aGV5IHNhdGlzZnkgdGhlIERlbGF1bmF5IGNvbmRpdGlvblxuICAgICAgICBlLnQgPSB0aGlzLl9sZWdhbGl6ZSh0ICsgMik7XG5cbiAgICAgICAgLy8gd2FsayBmb3J3YXJkIHRocm91Z2ggdGhlIGh1bGwsIGFkZGluZyBtb3JlIHRyaWFuZ2xlcyBhbmQgZmxpcHBpbmcgcmVjdXJzaXZlbHlcbiAgICAgICAgdmFyIHEgPSBlLm5leHQ7XG4gICAgICAgIHdoaWxlIChhcmVhKHgsIHksIHEueCwgcS55LCBxLm5leHQueCwgcS5uZXh0LnkpIDwgMCkge1xuXG4gICAgICAgICAgICB0ID0gdGhpcy5fYWRkVHJpYW5nbGUoaSwgcSk7XG4gICAgICAgICAgICB0aGlzLl9saW5rKHQsIHEucHJldi50KTtcbiAgICAgICAgICAgIGFkamFjZW50W3QgKyAxXSA9IC0xO1xuICAgICAgICAgICAgdGhpcy5fbGluayh0ICsgMiwgcS50KTtcblxuICAgICAgICAgICAgcS5wcmV2LnQgPSB0aGlzLl9sZWdhbGl6ZSh0ICsgMik7XG5cbiAgICAgICAgICAgIHRoaXMuaHVsbCA9IHJlbW92ZU5vZGUocSk7XG4gICAgICAgICAgICBxID0gcS5uZXh0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHdhbGtCYWNrKSB7XG4gICAgICAgICAgICAvLyB3YWxrIGJhY2t3YXJkIGZyb20gdGhlIG90aGVyIHNpZGUsIGFkZGluZyBtb3JlIHRyaWFuZ2xlcyBhbmQgZmxpcHBpbmdcbiAgICAgICAgICAgIHEgPSBlLnByZXY7XG4gICAgICAgICAgICB3aGlsZSAoYXJlYSh4LCB5LCBxLnByZXYueCwgcS5wcmV2LnksIHEueCwgcS55KSA8IDApIHtcblxuICAgICAgICAgICAgICAgIHQgPSB0aGlzLl9hZGRUcmlhbmdsZShpLCBxLnByZXYpO1xuICAgICAgICAgICAgICAgIGFkamFjZW50W3RdID0gLTE7XG4gICAgICAgICAgICAgICAgdGhpcy5fbGluayh0ICsgMSwgcS50KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9saW5rKHQgKyAyLCBxLnByZXYudCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9sZWdhbGl6ZSh0ICsgMik7XG5cbiAgICAgICAgICAgICAgICBxLnByZXYudCA9IHQ7XG4gICAgICAgICAgICAgICAgdGhpcy5odWxsID0gcmVtb3ZlTm9kZShxKTtcbiAgICAgICAgICAgICAgICBxID0gcS5wcmV2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2F2ZSB0aGUgdHdvIG5ldyBlZGdlcyBpbiB0aGUgaGFzaCB0YWJsZVxuICAgICAgICB0aGlzLl9oYXNoRWRnZShlKTtcbiAgICAgICAgdGhpcy5faGFzaEVkZ2UoZS5wcmV2KTtcbiAgICB9XG5cbiAgICAvLyB0cmltIHR5cGVkIHRyaWFuZ2xlIG1lc2ggYXJyYXlzXG4gICAgdGhpcy50cmlhbmdsZXMgPSB0cmlhbmdsZXMuc3ViYXJyYXkoMCwgdGhpcy50cmlhbmdsZXNMZW4pO1xuICAgIHRoaXMuYWRqYWNlbnQgPSBhZGphY2VudC5zdWJhcnJheSgwLCB0aGlzLnRyaWFuZ2xlc0xlbik7XG59XG5cbkRlbGF1bmF0b3IucHJvdG90eXBlID0ge1xuXG4gICAgX2hhc2hFZGdlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLl9oYXNoW3RoaXMuX2hhc2hLZXkoZS54LCBlLnkpXSA9IGU7XG4gICAgfSxcblxuICAgIF9oYXNoS2V5OiBmdW5jdGlvbiAoeCwgeSkge1xuICAgICAgICB2YXIgZHggPSB4IC0gdGhpcy5fY3g7XG4gICAgICAgIHZhciBkeSA9IHkgLSB0aGlzLl9jeTtcbiAgICAgICAgLy8gdXNlIHBzZXVkby1hbmdsZTogYSBtZWFzdXJlIHRoYXQgbW9ub3RvbmljYWxseSBpbmNyZWFzZXNcbiAgICAgICAgLy8gd2l0aCByZWFsIGFuZ2xlLCBidXQgZG9lc24ndCByZXF1aXJlIGV4cGVuc2l2ZSB0cmlnb25vbWV0cnlcbiAgICAgICAgdmFyIHAgPSAxIC0gZHggLyAoTWF0aC5hYnMoZHgpICsgTWF0aC5hYnMoZHkpKTtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKDIgKyAoZHkgPCAwID8gLXAgOiBwKSkgKiAodGhpcy5faGFzaFNpemUgLyA0KSk7XG4gICAgfSxcblxuICAgIF9sZWdhbGl6ZTogZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgdmFyIHRyaWFuZ2xlcyA9IHRoaXMudHJpYW5nbGVzO1xuICAgICAgICB2YXIgY29vcmRzID0gdGhpcy5jb29yZHM7XG4gICAgICAgIHZhciBhZGphY2VudCA9IHRoaXMuYWRqYWNlbnQ7XG5cbiAgICAgICAgdmFyIGIgPSBhZGphY2VudFthXTtcblxuICAgICAgICB2YXIgYTAgPSBhIC0gYSAlIDM7XG4gICAgICAgIHZhciBiMCA9IGIgLSBiICUgMztcblxuICAgICAgICB2YXIgYWwgPSBhMCArIChhICsgMSkgJSAzO1xuICAgICAgICB2YXIgYXIgPSBhMCArIChhICsgMikgJSAzO1xuICAgICAgICB2YXIgYnIgPSBiMCArIChiICsgMSkgJSAzO1xuICAgICAgICB2YXIgYmwgPSBiMCArIChiICsgMikgJSAzO1xuXG4gICAgICAgIHZhciBwMCA9IHRyaWFuZ2xlc1thcl07XG4gICAgICAgIHZhciBwciA9IHRyaWFuZ2xlc1thXTtcbiAgICAgICAgdmFyIHBsID0gdHJpYW5nbGVzW2FsXTtcbiAgICAgICAgdmFyIHAxID0gdHJpYW5nbGVzW2JsXTtcblxuICAgICAgICB2YXIgaWxsZWdhbCA9IGluQ2lyY2xlKFxuICAgICAgICAgICAgY29vcmRzWzIgKiBwMF0sIGNvb3Jkc1syICogcDAgKyAxXSxcbiAgICAgICAgICAgIGNvb3Jkc1syICogcHJdLCBjb29yZHNbMiAqIHByICsgMV0sXG4gICAgICAgICAgICBjb29yZHNbMiAqIHBsXSwgY29vcmRzWzIgKiBwbCArIDFdLFxuICAgICAgICAgICAgY29vcmRzWzIgKiBwMV0sIGNvb3Jkc1syICogcDEgKyAxXSk7XG5cbiAgICAgICAgaWYgKGlsbGVnYWwpIHtcbiAgICAgICAgICAgIHRyaWFuZ2xlc1thXSA9IHAxO1xuICAgICAgICAgICAgdHJpYW5nbGVzW2JdID0gcDA7XG5cbiAgICAgICAgICAgIHRoaXMuX2xpbmsoYSwgYWRqYWNlbnRbYmxdKTtcbiAgICAgICAgICAgIHRoaXMuX2xpbmsoYiwgYWRqYWNlbnRbYXJdKTtcbiAgICAgICAgICAgIHRoaXMuX2xpbmsoYXIsIGJsKTtcblxuICAgICAgICAgICAgdGhpcy5fbGVnYWxpemUoYSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbGVnYWxpemUoYnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFyO1xuICAgIH0sXG5cbiAgICBfbGluazogZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgdGhpcy5hZGphY2VudFthXSA9IGI7XG4gICAgICAgIGlmIChiICE9PSAtMSkgdGhpcy5hZGphY2VudFtiXSA9IGE7XG4gICAgfSxcblxuICAgIF9hZGRUcmlhbmdsZShpLCBlKSB7XG4gICAgICAgIHZhciB0ID0gdGhpcy50cmlhbmdsZXNMZW47XG4gICAgICAgIHRoaXMudHJpYW5nbGVzW3RdID0gZS5pO1xuICAgICAgICB0aGlzLnRyaWFuZ2xlc1t0ICsgMV0gPSBpO1xuICAgICAgICB0aGlzLnRyaWFuZ2xlc1t0ICsgMl0gPSBlLm5leHQuaTtcbiAgICAgICAgdGhpcy50cmlhbmdsZXNMZW4gKz0gMztcbiAgICAgICAgcmV0dXJuIHQ7XG4gICAgfVxufTtcblxuZnVuY3Rpb24gZGlzdChheCwgYXksIGJ4LCBieSkge1xuICAgIHZhciBkeCA9IGF4IC0gYng7XG4gICAgdmFyIGR5ID0gYXkgLSBieTtcbiAgICByZXR1cm4gZHggKiBkeCArIGR5ICogZHk7XG59XG5cbmZ1bmN0aW9uIGFyZWEocHgsIHB5LCBxeCwgcXksIHJ4LCByeSkge1xuICAgIHJldHVybiAocXkgLSBweSkgKiAocnggLSBxeCkgLSAocXggLSBweCkgKiAocnkgLSBxeSk7XG59XG5cbmZ1bmN0aW9uIGluQ2lyY2xlKGF4LCBheSwgYngsIGJ5LCBjeCwgY3ksIHB4LCBweSkge1xuICAgIGF4IC09IHB4O1xuICAgIGF5IC09IHB5O1xuICAgIGJ4IC09IHB4O1xuICAgIGJ5IC09IHB5O1xuICAgIGN4IC09IHB4O1xuICAgIGN5IC09IHB5O1xuXG4gICAgdmFyIGFwID0gYXggKiBheCArIGF5ICogYXk7XG4gICAgdmFyIGJwID0gYnggKiBieCArIGJ5ICogYnk7XG4gICAgdmFyIGNwID0gY3ggKiBjeCArIGN5ICogY3k7XG5cbiAgICB2YXIgZGV0ID0gYXggKiAoYnkgKiBjcCAtIGJwICogY3kpIC1cbiAgICAgICAgICAgICAgYXkgKiAoYnggKiBjcCAtIGJwICogY3gpICtcbiAgICAgICAgICAgICAgYXAgKiAoYnggKiBjeSAtIGJ5ICogY3gpO1xuXG4gICAgcmV0dXJuIGRldCA8IDA7XG59XG5cbmZ1bmN0aW9uIGNpcmN1bXJhZGl1cyhheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7XG4gICAgYnggLT0gYXg7XG4gICAgYnkgLT0gYXk7XG4gICAgY3ggLT0gYXg7XG4gICAgY3kgLT0gYXk7XG5cbiAgICB2YXIgYmwgPSBieCAqIGJ4ICsgYnkgKiBieTtcbiAgICB2YXIgY2wgPSBjeCAqIGN4ICsgY3kgKiBjeTtcblxuICAgIGlmIChibCA9PT0gMCB8fCBjbCA9PT0gMCkgcmV0dXJuIEluZmluaXR5O1xuXG4gICAgdmFyIGQgPSBieCAqIGN5IC0gYnkgKiBjeDtcbiAgICBpZiAoZCA9PT0gMCkgcmV0dXJuIEluZmluaXR5O1xuXG4gICAgdmFyIHggPSAoY3kgKiBibCAtIGJ5ICogY2wpICogMC41IC8gZDtcbiAgICB2YXIgeSA9IChieCAqIGNsIC0gY3ggKiBibCkgKiAwLjUgLyBkO1xuXG4gICAgcmV0dXJuIHggKiB4ICsgeSAqIHk7XG59XG5cbmZ1bmN0aW9uIGNpcmN1bWNlbnRlcihheCwgYXksIGJ4LCBieSwgY3gsIGN5KSB7XG4gICAgYnggLT0gYXg7XG4gICAgYnkgLT0gYXk7XG4gICAgY3ggLT0gYXg7XG4gICAgY3kgLT0gYXk7XG5cbiAgICB2YXIgYmwgPSBieCAqIGJ4ICsgYnkgKiBieTtcbiAgICB2YXIgY2wgPSBjeCAqIGN4ICsgY3kgKiBjeTtcblxuICAgIHZhciBkID0gYnggKiBjeSAtIGJ5ICogY3g7XG5cbiAgICB2YXIgeCA9IChjeSAqIGJsIC0gYnkgKiBjbCkgKiAwLjUgLyBkO1xuICAgIHZhciB5ID0gKGJ4ICogY2wgLSBjeCAqIGJsKSAqIDAuNSAvIGQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBheCArIHgsXG4gICAgICAgIHk6IGF5ICsgeVxuICAgIH07XG59XG5cbi8vIGNyZWF0ZSBhIG5ldyBub2RlIGluIGEgZG91Ymx5IGxpbmtlZCBsaXN0XG5mdW5jdGlvbiBpbnNlcnROb2RlKGNvb3JkcywgaSwgcHJldikge1xuICAgIHZhciBub2RlID0ge1xuICAgICAgICBpOiBpLFxuICAgICAgICB4OiBjb29yZHNbMiAqIGldLFxuICAgICAgICB5OiBjb29yZHNbMiAqIGkgKyAxXSxcbiAgICAgICAgdDogMCxcbiAgICAgICAgcHJldjogbnVsbCxcbiAgICAgICAgbmV4dDogbnVsbCxcbiAgICAgICAgcmVtb3ZlZDogZmFsc2VcbiAgICB9O1xuXG4gICAgaWYgKCFwcmV2KSB7XG4gICAgICAgIG5vZGUucHJldiA9IG5vZGU7XG4gICAgICAgIG5vZGUubmV4dCA9IG5vZGU7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgICBub2RlLm5leHQgPSBwcmV2Lm5leHQ7XG4gICAgICAgIG5vZGUucHJldiA9IHByZXY7XG4gICAgICAgIHByZXYubmV4dC5wcmV2ID0gbm9kZTtcbiAgICAgICAgcHJldi5uZXh0ID0gbm9kZTtcbiAgICB9XG4gICAgcmV0dXJuIG5vZGU7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5vZGUobm9kZSkge1xuICAgIG5vZGUucHJldi5uZXh0ID0gbm9kZS5uZXh0O1xuICAgIG5vZGUubmV4dC5wcmV2ID0gbm9kZS5wcmV2O1xuICAgIG5vZGUucmVtb3ZlZCA9IHRydWU7XG4gICAgcmV0dXJuIG5vZGUucHJldjtcbn1cblxuZnVuY3Rpb24gcXVpY2tzb3J0KGlkcywgY29vcmRzLCBsZWZ0LCByaWdodCwgY3gsIGN5KSB7XG4gICAgdmFyIGksIGosIHRlbXA7XG5cbiAgICBpZiAocmlnaHQgLSBsZWZ0IDw9IDIwKSB7XG4gICAgICAgIGZvciAoaSA9IGxlZnQgKyAxOyBpIDw9IHJpZ2h0OyBpKyspIHtcbiAgICAgICAgICAgIHRlbXAgPSBpZHNbaV07XG4gICAgICAgICAgICBqID0gaSAtIDE7XG4gICAgICAgICAgICB3aGlsZSAoaiA+PSBsZWZ0ICYmIGNvbXBhcmUoY29vcmRzLCBpZHNbal0sIHRlbXAsIGN4LCBjeSkgPiAwKSBpZHNbaiArIDFdID0gaWRzW2otLV07XG4gICAgICAgICAgICBpZHNbaiArIDFdID0gdGVtcDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBtZWRpYW4gPSAobGVmdCArIHJpZ2h0KSA+PiAxO1xuICAgICAgICBpID0gbGVmdCArIDE7XG4gICAgICAgIGogPSByaWdodDtcbiAgICAgICAgc3dhcChpZHMsIG1lZGlhbiwgaSk7XG4gICAgICAgIGlmIChjb21wYXJlKGNvb3JkcywgaWRzW2xlZnRdLCBpZHNbcmlnaHRdLCBjeCwgY3kpID4gMCkgc3dhcChpZHMsIGxlZnQsIHJpZ2h0KTtcbiAgICAgICAgaWYgKGNvbXBhcmUoY29vcmRzLCBpZHNbaV0sIGlkc1tyaWdodF0sIGN4LCBjeSkgPiAwKSBzd2FwKGlkcywgaSwgcmlnaHQpO1xuICAgICAgICBpZiAoY29tcGFyZShjb29yZHMsIGlkc1tsZWZ0XSwgaWRzW2ldLCBjeCwgY3kpID4gMCkgc3dhcChpZHMsIGxlZnQsIGkpO1xuXG4gICAgICAgIHRlbXAgPSBpZHNbaV07XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICBkbyBpKys7IHdoaWxlIChjb21wYXJlKGNvb3JkcywgaWRzW2ldLCB0ZW1wLCBjeCwgY3kpIDwgMCk7XG4gICAgICAgICAgICBkbyBqLS07IHdoaWxlIChjb21wYXJlKGNvb3JkcywgaWRzW2pdLCB0ZW1wLCBjeCwgY3kpID4gMCk7XG4gICAgICAgICAgICBpZiAoaiA8IGkpIGJyZWFrO1xuICAgICAgICAgICAgc3dhcChpZHMsIGksIGopO1xuICAgICAgICB9XG4gICAgICAgIGlkc1tsZWZ0ICsgMV0gPSBpZHNbal07XG4gICAgICAgIGlkc1tqXSA9IHRlbXA7XG5cbiAgICAgICAgaWYgKHJpZ2h0IC0gaSArIDEgPj0gaiAtIGxlZnQpIHtcbiAgICAgICAgICAgIHF1aWNrc29ydChpZHMsIGNvb3JkcywgaSwgcmlnaHQsIGN4LCBjeSk7XG4gICAgICAgICAgICBxdWlja3NvcnQoaWRzLCBjb29yZHMsIGxlZnQsIGogLSAxLCBjeCwgY3kpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcXVpY2tzb3J0KGlkcywgY29vcmRzLCBsZWZ0LCBqIC0gMSwgY3gsIGN5KTtcbiAgICAgICAgICAgIHF1aWNrc29ydChpZHMsIGNvb3JkcywgaSwgcmlnaHQsIGN4LCBjeSk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvbXBhcmUoY29vcmRzLCBpLCBqLCBjeCwgY3kpIHtcbiAgICB2YXIgZDEgPSBkaXN0KGNvb3Jkc1syICogaV0sIGNvb3Jkc1syICogaSArIDFdLCBjeCwgY3kpO1xuICAgIHZhciBkMiA9IGRpc3QoY29vcmRzWzIgKiBqXSwgY29vcmRzWzIgKiBqICsgMV0sIGN4LCBjeSk7XG4gICAgcmV0dXJuIChkMSAtIGQyKSB8fCAoY29vcmRzWzIgKiBpXSAtIGNvb3Jkc1syICogal0pIHx8IChjb29yZHNbMiAqIGkgKyAxXSAtIGNvb3Jkc1syICogaiArIDFdKTtcbn1cblxuZnVuY3Rpb24gc3dhcChhcnIsIGksIGopIHtcbiAgICB2YXIgdG1wID0gYXJyW2ldO1xuICAgIGFycltpXSA9IGFycltqXTtcbiAgICBhcnJbal0gPSB0bXA7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRHZXRYKHApIHtcbiAgICByZXR1cm4gcFswXTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRHZXRZKHApIHtcbiAgICByZXR1cm4gcFsxXTtcbn1cbiJdfQ== require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ module.exports = function (a, b) { var sum = 0 var n for (n = 0; n < a.length; n++) { sum += Math.pow(a[n] - b[n], 2) } return sum } },{}],"euclidean-distance":[function(require,module,exports){ // http://en.wikipedia.org/wiki/Euclidean_distance#Three_dimensions var distanceSquared = require('./squared') module.exports = function (a, b) { return Math.sqrt(distanceSquared(a,b)) } },{"./squared":1}]},{},[]) //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsInNxdWFyZWQuanMiLCJldWNsaWRlYW4tZGlzdGFuY2UiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhLCBiKSB7XG4gIHZhciBzdW0gPSAwXG4gIHZhciBuXG4gIGZvciAobiA9IDA7IG4gPCBhLmxlbmd0aDsgbisrKSB7XG4gICAgc3VtICs9IE1hdGgucG93KGFbbl0gLSBiW25dLCAyKVxuICB9XG4gIHJldHVybiBzdW1cbn1cbiIsIi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRXVjbGlkZWFuX2Rpc3RhbmNlI1RocmVlX2RpbWVuc2lvbnNcblxudmFyIGRpc3RhbmNlU3F1YXJlZCA9IHJlcXVpcmUoJy4vc3F1YXJlZCcpXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGEsIGIpIHtcbiAgcmV0dXJuIE1hdGguc3FydChkaXN0YW5jZVNxdWFyZWQoYSxiKSlcbn1cbiJdfQ== var Simplex = require('perlin-simplex') var Delaunator = require('delaunator') var getDistance = require('euclidean-distance') var simplex = new Simplex() var SPEED = 0.001 var N_POINTS = 200 document.body.style.background = 'rgb(20, 20, 20)' var stage = createStage() document.body.appendChild(stage) var points = createPoints(N_POINTS) var triangles = createTrianges(points) stage.appendChild(triangles.el) window.requestAnimationFrame(updateLoop) function updateLoop () { window.requestAnimationFrame(updateLoop) points.forEach(function (point) { point.update() }) triangles.update(points) } function createPoints (n) { var points = [] for (var i = 0; i < n; i++) { points.push({ x: Math.random(), y: Math.random(), theta: Math.random() * 2 * Math.PI, update: updatePoint }) } return points } function updatePoint () { var nx = this.x * 5 var ny = this.y * 10 var nz = Date.now() / 1000 var s = simplex.noise3d(nx, ny, nz) var theta = s * 2 * Math.PI this.theta = (0.01 * theta) + (0.99 * this.theta) this.x += SPEED * Math.cos(this.theta) this.y += SPEED * Math.sin(this.theta) this.x = mod(this.x, 1) this.y = mod(this.y, 1) } function createTrianges (points) { var viewBox = [0, 0, 1, 1].join(' ') var pathData = createPathData(points) var parent = document.createElement('div') parent.style.width = '100%' parent.style.height = '100%' parent.innerHTML = ` <svg xmlns='http://www.w3.org/svg/2000' viewBox='${viewBox}' width='100%' height='100%' stroke='none' fill='none'> ${pathData} </svg> ` var svg = parent.children[0] return { el: parent, update: function (points) { svg.innerHTML = createPathData(points) } } } function createPathData (points) { var coords = points.map(function (point) { return [point.x, point.y] }) var triangles = new Delaunator(coords).triangles var pathData = [] for (var i = 0; i < triangles.length; i += 3) { pathData.push(createTrianglePath( coords[triangles[i + 0]], coords[triangles[i + 1]], coords[triangles[i + 2]] )) } return pathData.join('\n') } function createTrianglePath (pa, pb, pc) { var x0 = pa[0] var y0 = pa[1] var x1 = pb[0] var y1 = pb[1] var x2 = pc[0] var y2 = pc[1] var d = [ 'M', x0, y0, 'L', x1, y1, 'L', x2, y2, 'L', x0, y0 ].join(' ') var eq = equalness(x0, y0, x1, y1, x2, y2) eq = eq * eq var b = Math.floor(30 + (eq * 130)) var fill = `rgb(${b}, ${b}, ${b})` return `<path d='${d}' fill='${fill}' stroke='none' />` } function equalness (x0, y0, x1, y1, x2, y2) { var a = getDistance([x0, y0], [x1, y1]) var b = getDistance([x0, y0], [x2, y2]) var c = getDistance([x2, y2], [x1, y1]) var diff = Math.abs(a - b) + Math.abs(a - c) + Math.abs(b - c) return 1 - (diff / (a + b + c)) } function createStage (w, h) { var stage = document.createElement('div') stage.style.position = 'absolute' stage.style.top = '10%' stage.style.left = '10%' stage.style.width = '80%' stage.style.height = '80%' return stage } function mod (a, n) { return ((a % n) + n) % n } ;}, 0) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,9 @@ { "name": "requirebin-sketch", "version": "1.0.0", "dependencies": { "perlin-simplex": "0.0.2", "delaunator": "1.0.2", "euclidean-distance": "1.0.0" } } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ <!-- contents of this file will be placed inside the <body> --> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ <!-- contents of this file will be placed inside the <head> --> This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1 @@ made with [requirebin](http://requirebin.com)