From 49ea59fd3016b4b125855511a05abe92a2e69082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 25 Jan 2016 11:09:53 -0500 Subject: [PATCH] 1.5.0 --- dist/plotly-geo-assets.js | 115 +- dist/plotly-with-meta.js | 87042 ++++++++++++++++++------------------ dist/plotly.js | 69228 ++++++++++++++-------------- dist/plotly.min.js | 78 +- package.json | 2 +- src/assets/geo_assets.js | 2 +- src/core.js | 2 +- 7 files changed, 78354 insertions(+), 78115 deletions(-) diff --git a/dist/plotly-geo-assets.js b/dist/plotly-geo-assets.js index 27bc5c3d313..b124b85ab74 100644 --- a/dist/plotly-geo-assets.js +++ b/dist/plotly-geo-assets.js @@ -1,5 +1,5 @@ /** -* plotly.js v1.4.1 +* plotly.js v1.5.0 * Copyright 2012-2016, Plotly, Inc. * All rights reserved. * Licensed under the MIT license @@ -55,111 +55,6 @@ exports['usa_110m'] = require('./dist/usa_110m.json'); exports['usa_50m'] = require('./dist/usa_50m.json'); },{"./dist/africa_110m.json":1,"./dist/africa_50m.json":2,"./dist/asia_110m.json":3,"./dist/asia_50m.json":4,"./dist/europe_110m.json":5,"./dist/europe_50m.json":6,"./dist/north-america_110m.json":7,"./dist/north-america_50m.json":8,"./dist/south-america_110m.json":9,"./dist/south-america_50m.json":10,"./dist/usa_110m.json":11,"./dist/usa_50m.json":12,"./dist/world_110m.json":13,"./dist/world_50m.json":14}],16:[function(require,module,exports){ -module.exports={ - "name": "plotly.js", - "version": "1.4.1", - "description": "The open source javascript graphing library that powers plotly", - "license": "MIT", - "main": "./src/index.js", - "webpack": "./dist/plotly.min.js", - "repository": { - "type": "git", - "url": "https://github.com/plotly/plotly.js.git" - }, - "bugs": { - "url": "https://github.com/plotly/plotly.js/issues" - }, - "author": "Plotly, Inc.", - "keywords": [ - "graphing", - "plotting", - "data", - "visualization", - "plotly" - ], - "scripts": { - "preprocess": "node tasks/preprocess.js", - "bundle": "node tasks/bundle.js", - "header": "node tasks/header.js", - "build": "npm run preprocess && npm run bundle && npm run header", - "cibuild": "node tasks/cibundle.js", - "watch": "node tasks/watch_plotly.js", - "lint": "cd src && jshint . || true", - "test-jasmine": "karma start test/jasmine/karma.conf.js", - "citest-jasmine": "karma start test/jasmine/karma.ciconf.js", - "test-image": "./tasks/test_image.sh", - "test-syntax": "node test/syntax_test.js", - "test": "npm run test-jasmine && npm test-image", - "start-test_dashboard": "node devtools/test_dashboard/server.js", - "start-image_viewer": "node devtools/image_viewer/server.js", - "baseline": "./tasks/baseline.sh", - "version": "npm run build && git add -A dist", - "postversion": "git push && git push --tags" - }, - "dependencies": { - "3d-view": "^2.0.0", - "alpha-shape": "^1.0.0", - "arraytools": "^1.0.0", - "convex-hull": "^1.0.3", - "d3": "3.5.6", - "delaunay-triangulate": "^1.1.6", - "es6-promise": "^3.0.2", - "fast-isnumeric": "^1.1.1", - "fs-extra": "^0.26.2", - "gl-error2d": "^1.0.0", - "gl-error3d": "^1.0.0", - "gl-line2d": "^1.2.1", - "gl-line3d": "^1.0.1", - "gl-mat4": "^1.1.2", - "gl-mesh3d": "^1.0.4", - "gl-plot2d": "^1.1.6", - "gl-plot3d": "^1.3.0", - "gl-scatter2d": "^1.0.5", - "gl-scatter2d-fancy": "^1.1.1", - "gl-scatter3d": "^1.0.4", - "gl-select-box": "^1.0.1", - "gl-spikes2d": "^1.0.1", - "gl-surface3d": "^1.1.0", - "mouse-change": "^1.1.1", - "mouse-wheel": "^1.0.2", - "ndarray": "^1.0.16", - "ndarray-fill": "^1.0.1", - "ndarray-homography": "^1.0.0", - "ndarray-ops": "^1.2.2", - "right-now": "^1.0.0", - "robust-orientation": "^1.1.3", - "sane-topojson": "^1.2.0", - "superscript-text": "^1.0.0", - "tinycolor2": "1.1.2", - "topojson": "^1.6.19" - }, - "devDependencies": { - "brfs": "^1.4.1", - "browserify": "^12.0.1", - "browserify-transform-tools": "^1.5.0", - "ecstatic": "^1.2.0", - "falafel": "^1.2.0", - "glob": "^6.0.1", - "jasmine-core": "^2.3.4", - "jshint": "^2.8.0", - "karma": "^0.13.15", - "karma-browserify": "^4.4.1", - "karma-chrome-launcher": "^0.2.1", - "karma-coverage": "^0.5.3", - "karma-firefox-launcher": "^0.1.6", - "karma-jasmine": "^0.3.6", - "node-sass": "^3.4.1", - "open": "0.0.5", - "prepend-file": "^1.3.0", - "prettysize": "0.0.3", - "through2": "^2.0.0", - "uglify-js": "^2.5.0", - "watchify": "^3.6.0", - "xml2js": "^0.4.15" - } -} - -},{}],17:[function(require,module,exports){ /** * Copyright 2012-2016, Plotly, Inc. * All rights reserved. @@ -168,13 +63,15 @@ module.exports={ * LICENSE file in the root directory of this source tree. */ +'use strict'; var saneTopojson = require('sane-topojson'); -// export the version found in the package.json -exports.version = require('../../package.json').version; + +// package version injected by `npm run preprocess` +exports.version = '1.5.0'; exports.topojson = saneTopojson; -},{"../../package.json":16,"sane-topojson":15}]},{},[17])(17) +},{"sane-topojson":15}]},{},[16])(16) }); \ No newline at end of file diff --git a/dist/plotly-with-meta.js b/dist/plotly-with-meta.js index c492de02c85..a8a667e4d16 100644 --- a/dist/plotly-with-meta.js +++ b/dist/plotly-with-meta.js @@ -1,5 +1,5 @@ /** -* plotly.js v1.4.1 +* plotly.js v1.5.0 * Copyright 2012-2016, Plotly, Inc. * All rights reserved. * Licensed under the MIT license @@ -66,9 +66,7 @@ for(var selector in rules) { Plotly.Lib.addStyleRule(fullSelector, rules[selector]); } -},{"../src/plotly":1070}],2:[function(require,module,exports){ -/* jshint quotmark:true */ - +},{"../src/plotly":365}],2:[function(require,module,exports){ 'use strict'; module.exports = { @@ -189,205 +187,501 @@ module.exports = { }; },{}],3:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/bar'); + +},{"../src/traces/bar":420}],4:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/box'); + +},{"../src/traces/box":431}],5:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/choropleth'); + +},{"../src/traces/choropleth":439}],6:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/contour'); + +},{"../src/traces/contour":446}],7:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/core'); + +},{"../src/core":338}],8:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/heatmap'); + +},{"../src/traces/heatmap":457}],9:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/histogram'); + +},{"../src/traces/histogram":468}],10:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/histogram2d'); + +},{"../src/traces/histogram2d":473}],11:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/histogram2dcontour'); + +},{"../src/traces/histogram2dcontour":477}],12:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +'use strict'; + +/* + * This file is browserify'ed into a standalone 'Plotly' object. + */ + +var Core = require('./core'); + +// Load all trace modules +Core.register([ + require('./bar'), + require('./box'), + require('./heatmap'), + require('./histogram'), + require('./histogram2d'), + require('./histogram2dcontour'), + require('./pie'), + require('./contour'), + require('./scatter3d'), + require('./surface'), + require('./mesh3d'), + require('./scattergeo'), + require('./choropleth'), + require('./scattergl') +]); + +module.exports = Core; + +},{"./bar":3,"./box":4,"./choropleth":5,"./contour":6,"./core":7,"./heatmap":8,"./histogram":9,"./histogram2d":10,"./histogram2dcontour":11,"./mesh3d":13,"./pie":14,"./scatter3d":15,"./scattergeo":16,"./scattergl":17,"./surface":18}],13:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/mesh3d'); + +},{"../src/traces/mesh3d":481}],14:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/pie'); + +},{"../src/traces/pie":486}],15:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/scatter3d'); + +},{"../src/traces/scatter3d":519}],16:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/scattergeo'); + +},{"../src/traces/scattergeo":523}],17:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/scattergl'); + +},{"../src/traces/scattergl":528}],18:[function(require,module,exports){ +/** +* Copyright 2012-2016, Plotly, Inc. +* All rights reserved. +* +* This source code is licensed under the MIT license found in the +* LICENSE file in the root directory of this source tree. +*/ + +module.exports = require('../src/traces/surface'); + +},{"../src/traces/surface":533}],19:[function(require,module,exports){ 'use strict' -var bsearch = require('binary-search-bounds') -var m4interp = require('mat4-interpolate') -var invert44 = require('gl-mat4/invert') -var rotateX = require('gl-mat4/rotateX') -var rotateY = require('gl-mat4/rotateY') -var rotateZ = require('gl-mat4/rotateZ') -var lookAt = require('gl-mat4/lookAt') -var translate = require('gl-mat4/translate') -var scale = require('gl-mat4/scale') -var normalize = require('gl-vec3/normalize') +module.exports = createFilteredVector -var DEFAULT_CENTER = [0,0,0] +var cubicHermite = require('cubic-hermite') +var bsearch = require('binary-search-bounds') -module.exports = createMatrixCameraController +function clamp(lo, hi, x) { + return Math.min(hi, Math.max(lo, x)) +} -function MatrixCameraController(initialMatrix) { - this._components = initialMatrix.slice() - this._time = [0] - this.prevMatrix = initialMatrix.slice() - this.nextMatrix = initialMatrix.slice() - this.computedMatrix = initialMatrix.slice() - this.computedInverse = initialMatrix.slice() - this.computedEye = [0,0,0] - this.computedUp = [0,0,0] - this.computedCenter = [0,0,0] - this.computedRadius = [0] - this._limits = [-Infinity, Infinity] +function FilteredVector(state0, velocity0, t0) { + this.dimension = state0.length + this.bounds = [ new Array(this.dimension), new Array(this.dimension) ] + for(var i=0; i= n-1) { + var ptr = state.length-1 + var tf = t - time[n-1] + for(var i=0; i= n-1) { + var ptr = state.length-1 + var tf = t - time[n-1] + for(var i=0; i=0; --i) { + if(velocity[--ptr]) { + return false + } } + return true } -proto.idle = function(t) { - if(t < this.lastT()) { +proto.jump = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t < t0 || arguments.length !== d+1) { return } - var mc = this._components - var ptr = mc.length-16 - for(var i=0; i<16; ++i) { - mc.push(mc[ptr++]) + var state = this._state + var velocity = this._velocity + var ptr = state.length-this.dimension + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + this._time.push(t0, t) + for(var j=0; j<2; ++j) { + for(var i=0; i0; --i) { + state.push(clamp(lo[i-1], hi[i-1], arguments[i])) + velocity.push(0) + } } -proto.flush = function(t) { - var idx = bsearch.gt(this._time, t) - 2 - if(idx < 0) { +proto.push = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t < t0 || arguments.length !== d+1) { return } - this._time.slice(0, idx) - this._components.slice(0, 16*idx) -} - -proto.lastT = function() { - return this._time[this._time.length-1] -} - -proto.lookAt = function(t, eye, center, up) { - this.recalcMatrix(t) - eye = eye || this.computedEye - center = center || DEFAULT_CENTER - up = up || this.computedUp - this.setMatrix(t, lookAt(this.computedMatrix, eye, center, up)) - var d2 = 0.0 - for(var i=0; i<3; ++i) { - d2 += Math.pow(center[i] - eye[i], 2) + var state = this._state + var velocity = this._velocity + var ptr = state.length-this.dimension + var dt = t - t0 + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var sf = (dt > 1e-6) ? 1/dt : 0 + this._time.push(t) + for(var i=d; i>0; --i) { + var xc = clamp(lo[i-1], hi[i-1], arguments[i]) + state.push(xc) + velocity.push((xc - state[ptr++]) * sf) } - d2 = Math.log(Math.sqrt(d2)) - this.computedRadius[0] = d2 -} - -proto.rotate = function(t, yaw, pitch, roll) { - this.recalcMatrix(t) - var mat = this.computedInverse - if(yaw) rotateY(mat, mat, yaw) - if(pitch) rotateX(mat, mat, pitch) - if(roll) rotateZ(mat, mat, roll) - this.setMatrix(t, invert44(this.computedMatrix, mat)) -} - -var tvec = [0,0,0] - -proto.pan = function(t, dx, dy, dz) { - tvec[0] = -(dx || 0.0) - tvec[1] = -(dy || 0.0) - tvec[2] = -(dz || 0.0) - this.recalcMatrix(t) - var mat = this.computedInverse - translate(mat, mat, tvec) - this.setMatrix(t, invert44(mat, mat)) -} - -proto.translate = function(t, dx, dy, dz) { - tvec[0] = dx || 0.0 - tvec[1] = dy || 0.0 - tvec[2] = dz || 0.0 - this.recalcMatrix(t) - var mat = this.computedMatrix - translate(mat, mat, tvec) - this.setMatrix(t, mat) } -proto.setMatrix = function(t, mat) { - if(t < this.lastT()) { +proto.set = function(t) { + var d = this.dimension + if(t < this.lastT() || arguments.length !== d+1) { return } + var state = this._state + var velocity = this._velocity + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] this._time.push(t) - for(var i=0; i<16; ++i) { - this._components.push(mat[i]) + for(var i=d; i>0; --i) { + state.push(clamp(lo[i-1], hi[i-1], arguments[i])) + velocity.push(0) } } -proto.setDistance = function(t, d) { - this.computedRadius[0] = d +proto.move = function(t) { + var t0 = this.lastT() + var d = this.dimension + if(t <= t0 || arguments.length !== d+1) { + return + } + var state = this._state + var velocity = this._velocity + var statePtr = state.length - this.dimension + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var dt = t - t0 + var sf = (dt > 1e-6) ? 1/dt : 0.0 + this._time.push(t) + for(var i=d; i>0; --i) { + var dx = arguments[i] + state.push(clamp(lo[i-1], hi[i-1], state[statePtr++] + dx)) + velocity.push(dx * sf) + } } -proto.setDistanceLimits = function(a,b) { - var lim = this._limits - lim[0] = a - lim[1] = b +proto.idle = function(t) { + var t0 = this.lastT() + if(t < t0) { + return + } + var d = this.dimension + var state = this._state + var velocity = this._velocity + var statePtr = state.length-d + var bounds = this.bounds + var lo = bounds[0] + var hi = bounds[1] + var dt = t - t0 + this._time.push(t) + for(var i=d-1; i>=0; --i) { + state.push(clamp(lo[i], hi[i], state[statePtr] + dt * velocity[statePtr])) + velocity.push(0) + statePtr += 1 + } } -proto.getDistanceLimits = function(out) { - var lim = this._limits - if(out) { - out[0] = lim[0] - out[1] = lim[1] - return out +function getZero(d) { + var result = new Array(d) + for(var i=0; i=0; --i) { + f[i] = dh00*p0[i] + dh10*v0[i] + dh01*p1[i] + dh11*v1[i] + } + return f + } + return dh00*p0 + dh10*v0 + dh01*p1[i] + dh11*v1 +} + +function cubicHermite(p0, v0, p1, v1, t, f) { + var ti = (t-1), t2 = t*t, ti2 = ti*ti, + h00 = (1+2*t)*ti2, + h10 = t*ti2, + h01 = t2*(3-2*t), + h11 = t2*ti + if(p0.length) { + if(!f) { + f = new Array(p0.length) + } + for(var i=p0.length-1; i>=0; --i) { + f[i] = h00*p0[i] + h10*v0[i] + h01*p1[i] + h11*v1[i] + } + return f + } + return h00*p0 + h10*v0 + h01*p1 + h11*v1 +} + +module.exports = cubicHermite +module.exports.derivative = dcubicHermite +},{}],22:[function(require,module,exports){ module.exports = cross; /** @@ -469,7 +803,7 @@ function cross(out, a, b) { out[2] = ax * by - ay * bx return out } -},{}],6:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ module.exports = dot; /** @@ -482,7 +816,7 @@ module.exports = dot; function dot(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] } -},{}],7:[function(require,module,exports){ +},{}],24:[function(require,module,exports){ module.exports = length; /** @@ -497,7 +831,7 @@ function length(a) { z = a[2] return Math.sqrt(x*x + y*y + z*z) } -},{}],8:[function(require,module,exports){ +},{}],25:[function(require,module,exports){ module.exports = lerp; /** @@ -518,7 +852,7 @@ function lerp(out, a, b, t) { out[2] = az + t * (b[2] - az) return out } -},{}],9:[function(require,module,exports){ +},{}],26:[function(require,module,exports){ module.exports = normalize; /** @@ -542,7 +876,208 @@ function normalize(out, a) { } return out } -},{}],10:[function(require,module,exports){ +},{}],27:[function(require,module,exports){ +'use strict' + +var bsearch = require('binary-search-bounds') +var m4interp = require('mat4-interpolate') +var invert44 = require('gl-mat4/invert') +var rotateX = require('gl-mat4/rotateX') +var rotateY = require('gl-mat4/rotateY') +var rotateZ = require('gl-mat4/rotateZ') +var lookAt = require('gl-mat4/lookAt') +var translate = require('gl-mat4/translate') +var scale = require('gl-mat4/scale') +var normalize = require('gl-vec3/normalize') + +var DEFAULT_CENTER = [0,0,0] + +module.exports = createMatrixCameraController + +function MatrixCameraController(initialMatrix) { + this._components = initialMatrix.slice() + this._time = [0] + this.prevMatrix = initialMatrix.slice() + this.nextMatrix = initialMatrix.slice() + this.computedMatrix = initialMatrix.slice() + this.computedInverse = initialMatrix.slice() + this.computedEye = [0,0,0] + this.computedUp = [0,0,0] + this.computedCenter = [0,0,0] + this.computedRadius = [0] + this._limits = [-Infinity, Infinity] +} + +var proto = MatrixCameraController.prototype + +proto.recalcMatrix = function(t) { + var time = this._time + var tidx = bsearch.le(time, t) + var mat = this.computedMatrix + if(tidx < 0) { + return + } + var comps = this._components + if(tidx === time.length-1) { + var ptr = 16*tidx + for(var i=0; i<16; ++i) { + mat[i] = comps[ptr++] + } + } else { + var dt = (time[tidx+1] - time[tidx]) + var ptr = 16*tidx + var prev = this.prevMatrix + var allEqual = true + for(var i=0; i<16; ++i) { + prev[i] = comps[ptr++] + } + var next = this.nextMatrix + for(var i=0; i<16; ++i) { + next[i] = comps[ptr++] + allEqual = allEqual && (prev[i] === next[i]) + } + if(dt < 1e-6 || allEqual) { + for(var i=0; i<16; ++i) { + mat[i] = prev[i] + } + } else { + m4interp(mat, prev, next, (t - time[tidx])/dt) + } + } + + var up = this.computedUp + up[0] = mat[1] + up[1] = mat[5] + up[2] = mat[6] + normalize(up, up) + + var imat = this.computedInverse + invert44(imat, mat) + var eye = this.computedEye + var w = imat[15] + eye[0] = imat[12]/w + eye[1] = imat[13]/w + eye[2] = imat[14]/w + + var center = this.computedCenter + var radius = Math.exp(this.computedRadius[0]) + for(var i=0; i<3; ++i) { + center[i] = eye[i] - mat[2+4*i] * radius + } +} + +proto.idle = function(t) { + if(t < this.lastT()) { + return + } + var mc = this._components + var ptr = mc.length-16 + for(var i=0; i<16; ++i) { + mc.push(mc[ptr++]) + } + this._time.push(t) +} + +proto.flush = function(t) { + var idx = bsearch.gt(this._time, t) - 2 + if(idx < 0) { + return + } + this._time.slice(0, idx) + this._components.slice(0, 16*idx) +} + +proto.lastT = function() { + return this._time[this._time.length-1] +} + +proto.lookAt = function(t, eye, center, up) { + this.recalcMatrix(t) + eye = eye || this.computedEye + center = center || DEFAULT_CENTER + up = up || this.computedUp + this.setMatrix(t, lookAt(this.computedMatrix, eye, center, up)) + var d2 = 0.0 + for(var i=0; i<3; ++i) { + d2 += Math.pow(center[i] - eye[i], 2) + } + d2 = Math.log(Math.sqrt(d2)) + this.computedRadius[0] = d2 +} + +proto.rotate = function(t, yaw, pitch, roll) { + this.recalcMatrix(t) + var mat = this.computedInverse + if(yaw) rotateY(mat, mat, yaw) + if(pitch) rotateX(mat, mat, pitch) + if(roll) rotateZ(mat, mat, roll) + this.setMatrix(t, invert44(this.computedMatrix, mat)) +} + +var tvec = [0,0,0] + +proto.pan = function(t, dx, dy, dz) { + tvec[0] = -(dx || 0.0) + tvec[1] = -(dy || 0.0) + tvec[2] = -(dz || 0.0) + this.recalcMatrix(t) + var mat = this.computedInverse + translate(mat, mat, tvec) + this.setMatrix(t, invert44(mat, mat)) +} + +proto.translate = function(t, dx, dy, dz) { + tvec[0] = dx || 0.0 + tvec[1] = dy || 0.0 + tvec[2] = dz || 0.0 + this.recalcMatrix(t) + var mat = this.computedMatrix + translate(mat, mat, tvec) + this.setMatrix(t, mat) +} + +proto.setMatrix = function(t, mat) { + if(t < this.lastT()) { + return + } + this._time.push(t) + for(var i=0; i<16; ++i) { + this._components.push(mat[i]) + } +} + +proto.setDistance = function(t, d) { + this.computedRadius[0] = d +} + +proto.setDistanceLimits = function(a,b) { + var lim = this._limits + lim[0] = a + lim[1] = b +} + +proto.getDistanceLimits = function(out) { + var lim = this._limits + if(out) { + out[0] = lim[0] + out[1] = lim[1] + return out + } + return lim +} + +function createMatrixCameraController(options) { + options = options || {} + var matrix = options.matrix || + [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + return new MatrixCameraController(matrix) +} +},{"binary-search-bounds":28,"gl-mat4/invert":94,"gl-mat4/lookAt":95,"gl-mat4/rotateX":99,"gl-mat4/rotateY":100,"gl-mat4/rotateZ":101,"gl-mat4/scale":102,"gl-mat4/translate":103,"gl-vec3/normalize":26,"mat4-interpolate":29}],28:[function(require,module,exports){ +arguments[4][20][0].apply(exports,arguments) +},{"dup":20}],29:[function(require,module,exports){ var lerp = require('gl-vec3/lerp') var recompose = require('mat4-recompose') @@ -595,7 +1130,7 @@ function vec3(n) { function vec4() { return [0,0,0,1] } -},{"gl-mat4/determinant":210,"gl-vec3/lerp":8,"mat4-decompose":11,"mat4-recompose":13,"quat-slerp":14}],11:[function(require,module,exports){ +},{"gl-mat4/determinant":90,"gl-vec3/lerp":25,"mat4-decompose":30,"mat4-recompose":32,"quat-slerp":33}],30:[function(require,module,exports){ /*jshint unused:true*/ /* Input: matrix ; a 4x4 matrix @@ -775,7 +1310,7 @@ function combine(out, a, b, scale1, scale2) { out[1] = a[1] * scale1 + b[1] * scale2 out[2] = a[2] * scale1 + b[2] * scale2 } -},{"./normalize":12,"gl-mat4/clone":208,"gl-mat4/create":209,"gl-mat4/determinant":210,"gl-mat4/invert":214,"gl-mat4/transpose":224,"gl-vec3/cross":5,"gl-vec3/dot":6,"gl-vec3/length":7,"gl-vec3/normalize":9}],12:[function(require,module,exports){ +},{"./normalize":31,"gl-mat4/clone":88,"gl-mat4/create":89,"gl-mat4/determinant":90,"gl-mat4/invert":94,"gl-mat4/transpose":104,"gl-vec3/cross":22,"gl-vec3/dot":23,"gl-vec3/length":24,"gl-vec3/normalize":26}],31:[function(require,module,exports){ module.exports = function normalize(out, mat) { var m44 = mat[15] // Cannot normalize. @@ -786,7 +1321,7 @@ module.exports = function normalize(out, mat) { out[i] = mat[i] * scale return true } -},{}],13:[function(require,module,exports){ +},{}],32:[function(require,module,exports){ /* Input: translation ; a 3 component vector scale ; a 3 component vector @@ -847,9 +1382,9 @@ module.exports = function recomposeMat4(matrix, translation, scale, skew, perspe mat4.scale(matrix, matrix, scale) return matrix } -},{"gl-mat4/create":209,"gl-mat4/fromRotationTranslation":212,"gl-mat4/identity":213,"gl-mat4/multiply":216,"gl-mat4/scale":222,"gl-mat4/translate":223}],14:[function(require,module,exports){ +},{"gl-mat4/create":89,"gl-mat4/fromRotationTranslation":92,"gl-mat4/identity":93,"gl-mat4/multiply":96,"gl-mat4/scale":102,"gl-mat4/translate":103}],33:[function(require,module,exports){ module.exports = require('gl-quat/slerp') -},{"gl-quat/slerp":15}],15:[function(require,module,exports){ +},{"gl-quat/slerp":34}],34:[function(require,module,exports){ module.exports = slerp /** @@ -902,7 +1437,7 @@ function slerp (out, a, b, t) { return out } -},{}],16:[function(require,module,exports){ +},{}],35:[function(require,module,exports){ 'use strict' module.exports = quatFromFrame @@ -944,342 +1479,7 @@ function quatFromFrame( } return out } -},{}],17:[function(require,module,exports){ -'use strict' - -module.exports = createFilteredVector - -var cubicHermite = require('cubic-hermite') -var bsearch = require('binary-search-bounds') - -function clamp(lo, hi, x) { - return Math.min(hi, Math.max(lo, x)) -} - -function FilteredVector(state0, velocity0, t0) { - this.dimension = state0.length - this.bounds = [ new Array(this.dimension), new Array(this.dimension) ] - for(var i=0; i= n-1) { - var ptr = state.length-1 - var tf = t - time[n-1] - for(var i=0; i= n-1) { - var ptr = state.length-1 - var tf = t - time[n-1] - for(var i=0; i=0; --i) { - if(velocity[--ptr]) { - return false - } - } - return true -} - -proto.jump = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t < t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var ptr = state.length-this.dimension - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - this._time.push(t0, t) - for(var j=0; j<2; ++j) { - for(var i=0; i0; --i) { - state.push(clamp(lo[i-1], hi[i-1], arguments[i])) - velocity.push(0) - } -} - -proto.push = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t < t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var ptr = state.length-this.dimension - var dt = t - t0 - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var sf = (dt > 1e-6) ? 1/dt : 0 - this._time.push(t) - for(var i=d; i>0; --i) { - var xc = clamp(lo[i-1], hi[i-1], arguments[i]) - state.push(xc) - velocity.push((xc - state[ptr++]) * sf) - } -} - -proto.set = function(t) { - var d = this.dimension - if(t < this.lastT() || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - this._time.push(t) - for(var i=d; i>0; --i) { - state.push(clamp(lo[i-1], hi[i-1], arguments[i])) - velocity.push(0) - } -} - -proto.move = function(t) { - var t0 = this.lastT() - var d = this.dimension - if(t <= t0 || arguments.length !== d+1) { - return - } - var state = this._state - var velocity = this._velocity - var statePtr = state.length - this.dimension - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var dt = t - t0 - var sf = (dt > 1e-6) ? 1/dt : 0.0 - this._time.push(t) - for(var i=d; i>0; --i) { - var dx = arguments[i] - state.push(clamp(lo[i-1], hi[i-1], state[statePtr++] + dx)) - velocity.push(dx * sf) - } -} - -proto.idle = function(t) { - var t0 = this.lastT() - if(t < t0) { - return - } - var d = this.dimension - var state = this._state - var velocity = this._velocity - var statePtr = state.length-d - var bounds = this.bounds - var lo = bounds[0] - var hi = bounds[1] - var dt = t - t0 - this._time.push(t) - for(var i=d-1; i>=0; --i) { - state.push(clamp(lo[i], hi[i], state[statePtr] + dt * velocity[statePtr])) - velocity.push(0) - statePtr += 1 - } -} - -function getZero(d) { - var result = new Array(d) - for(var i=0; i=0; --i) { - f[i] = dh00*p0[i] + dh10*v0[i] + dh01*p1[i] + dh11*v1[i] - } - return f - } - return dh00*p0 + dh10*v0 + dh01*p1[i] + dh11*v1 -} - -function cubicHermite(p0, v0, p1, v1, t, f) { - var ti = (t-1), t2 = t*t, ti2 = ti*ti, - h00 = (1+2*t)*ti2, - h10 = t*ti2, - h01 = t2*(3-2*t), - h11 = t2*ti - if(p0.length) { - if(!f) { - f = new Array(p0.length) - } - for(var i=p0.length-1; i>=0; --i) { - f[i] = h00*p0[i] + h10*v0[i] + h01*p1[i] + h11*v1[i] - } - return f - } - return h00*p0 + h10*v0 + h01*p1 + h11*v1 -} - -module.exports = cubicHermite -module.exports.derivative = dcubicHermite -},{}],20:[function(require,module,exports){ +},{}],36:[function(require,module,exports){ 'use strict' module.exports = createOrbitController @@ -1673,19 +1873,7 @@ function createOrbitController(options) { return result } -},{"./lib/quatFromFrame":16,"filtered-vector":17,"gl-mat4/fromQuat":211,"gl-mat4/invert":214,"gl-mat4/lookAt":215}],21:[function(require,module,exports){ -arguments[4][17][0].apply(exports,arguments) -},{"binary-search-bounds":22,"cubic-hermite":23,"dup":17}],22:[function(require,module,exports){ -arguments[4][4][0].apply(exports,arguments) -},{"dup":4}],23:[function(require,module,exports){ -arguments[4][19][0].apply(exports,arguments) -},{"dup":19}],24:[function(require,module,exports){ -arguments[4][5][0].apply(exports,arguments) -},{"dup":5}],25:[function(require,module,exports){ -arguments[4][6][0].apply(exports,arguments) -},{"dup":6}],26:[function(require,module,exports){ -arguments[4][9][0].apply(exports,arguments) -},{"dup":9}],27:[function(require,module,exports){ +},{"./lib/quatFromFrame":35,"filtered-vector":19,"gl-mat4/fromQuat":91,"gl-mat4/invert":94,"gl-mat4/lookAt":95}],37:[function(require,module,exports){ 'use strict' module.exports = createTurntableController @@ -2258,7 +2446,7 @@ function createTurntableController(options) { theta, phi) } -},{"filtered-vector":21,"gl-mat4/invert":214,"gl-mat4/rotate":218,"gl-vec3/cross":24,"gl-vec3/dot":25,"gl-vec3/normalize":26}],28:[function(require,module,exports){ +},{"filtered-vector":19,"gl-mat4/invert":94,"gl-mat4/rotate":98,"gl-vec3/cross":22,"gl-vec3/dot":23,"gl-vec3/normalize":26}],38:[function(require,module,exports){ 'use strict' module.exports = createViewController @@ -2381,7 +2569,7 @@ function createViewController(options) { matrix: matrix }, mode) } -},{"matrix-camera-controller":3,"orbit-camera-controller":20,"turntable-camera-controller":27}],29:[function(require,module,exports){ +},{"matrix-camera-controller":27,"orbit-camera-controller":36,"turntable-camera-controller":37}],39:[function(require,module,exports){ module.exports = alphaShape var ac = require('alpha-complex') @@ -2390,7 +2578,7 @@ var bnd = require('simplicial-complex-boundary') function alphaShape(alpha, points) { return bnd(ac(alpha, points)) } -},{"alpha-complex":30,"simplicial-complex-boundary":41}],30:[function(require,module,exports){ +},{"alpha-complex":40,"simplicial-complex-boundary":43}],40:[function(require,module,exports){ 'use strict' module.exports = alphaComplex @@ -2407,7 +2595,7 @@ function alphaComplex(alpha, points) { return circumradius(simplex) * alpha < 1 }) } -},{"circumradius":31,"delaunay-triangulate":70}],31:[function(require,module,exports){ +},{"circumradius":41,"delaunay-triangulate":71}],41:[function(require,module,exports){ module.exports = circumradius var circumcenter = require('circumcenter') @@ -2423,7 +2611,7 @@ function circumradius(points) { } return Math.sqrt(avgDist / points.length) } -},{"circumcenter":32}],32:[function(require,module,exports){ +},{"circumcenter":42}],42:[function(require,module,exports){ "use strict" var dup = require("dup") @@ -2492,785 +2680,208 @@ function circumcenter(points) { circumcenter.barycenetric = barycentricCircumcenter module.exports = circumcenter -},{"dup":33,"robust-linear-solve":34}],33:[function(require,module,exports){ -"use strict" +},{"dup":72,"robust-linear-solve":211}],43:[function(require,module,exports){ +'use strict' -function dupe_array(count, value, i) { - var c = count[i]|0 - if(c <= 0) { - return [] - } - var result = new Array(c), j - if(i === count.length-1) { - for(j=0; j 0) { - return dupe_number(count|0, value) - } - break - case "object": - if(typeof (count.length) === "number") { - return dupe_array(count, value, 0) + var result = new Array(sz) + var ptr = 0 + for(var i=0; i 0) { - code.push(",") - } - code.push("[") - for(var k=0; k 0) { - code.push(",") - } - if(k === i) { - code.push("+b[", j, "]") - } else { - code.push("+A[", j, "][", k, "]") - } +function orientation(s) { + var p = 1 + for(var i=1; i=0; --i) { - var a = Q - var b = e[i] - Q = a + b - var bv = Q - a - var q = b - bv - if(q) { - e[--bottom] = Q - Q = q +module.exports = reduceCellComplex + +function reduceCellComplex(cells) { + cells.sort(compareOrientedCell) + var n = cells.length + var ptr = 0 + for(var i=0; i 0) { + var f = cells[ptr-1] + if(compareCell(c, f) === 0 && + orientation(f) !== o) { + ptr -= 1 + continue + } } + cells[ptr++] = c } - e[top++] = Q - e.length = top - return e + cells.length = ptr + return cells } -},{}],36:[function(require,module,exports){ -"use strict" -module.exports = fastTwoSum +},{"cell-orientation":45,"compare-cell":59,"compare-oriented-cell":46}],48:[function(require,module,exports){ +'use strict'; -function fastTwoSum(a, b, result) { - var x = a + b - var bv = x - a - var av = x - bv - var br = b - bv - var ar = a - av - if(result) { - result[0] = ar + br - result[1] = x - return result - } - return [ar+br, x] -} -},{}],37:[function(require,module,exports){ -"use strict" +var arraytools = function () { -var twoProduct = require("two-product") -var twoSum = require("two-sum") + var that = {}; -module.exports = scaleLinearExpansion + var RGB_REGEX = /^rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(,.*)?\)$/; + var RGB_GROUP_REGEX = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(.*)?\)$/; -function scaleLinearExpansion(e, scale) { - var n = e.length - if(n === 1) { - var ts = twoProduct(e[0], scale) - if(ts[0]) { - return ts - } - return [ ts[1] ] - } - var g = new Array(2 * n) - var q = [0.1, 0.1] - var t = [0.1, 0.1] - var count = 0 - twoProduct(e[0], scale, q) - if(q[0]) { - g[count++] = q[0] - } - for(var i=1; i= nf)) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - fa = abs(fi) - } - } - var x = a + b - var bv = x - a - var y = b - bv - var q0 = y - var q1 = x - var _x, _bv, _av, _br, _ar - while(eptr < ne && fptr < nf) { - if(ea < fa) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = f[fptr] - fa = abs(fi) + function zip () { + var arrays = [].slice.call(arguments); + var lengths = arrays.map(function (a) {return a.length;}); + var len = Math.min.apply(null, lengths); + var zipped = []; + for (var i = 0; i < len; i++) { + zipped[i] = []; + for (var j = 0; j < arrays.length; ++j) { + zipped[i][j] = arrays[j][i]; + } } - } - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x + return zipped; } - while(eptr < ne) { - a = ei - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - } + + function zip3 (a, b, c) { + var len = Math.min.apply(null, [a.length, b.length, c.length]); + var result = []; + for (var n = 0; n < len; n++) { + result.push([a[n], b[n], c[n]]); + } + return result; } - while(fptr < nf) { - a = fi - b = q0 - x = a + b - bv = x - a - y = b - bv - if(y) { - g[count++] = y - } - _x = q1 + x - _bv = _x - q1 - _av = _x - _bv - _br = x - _bv - _ar = q1 - _av - q0 = _ar + _br - q1 = _x - fptr += 1 - if(fptr < nf) { - fi = f[fptr] + + function sum (A) { + var acc = 0; + accumulate(A, acc); + function accumulate(x) { + for (var i = 0; i < x.length; i++) { + if (Array.isArray(x[i])) + accumulate(x[i], acc); + else + acc += x[i]; + } } + return acc; } - if(q0) { - g[count++] = q0 - } - if(q1) { - g[count++] = q1 - } - if(!count) { - g[count++] = 0.0 - } - g.length = count - return g -} -},{}],39:[function(require,module,exports){ -"use strict" -module.exports = twoProduct + function copy2D (arr) { + var carr = []; + for (var i = 0; i < arr.length; ++i) { + carr[i] = []; + for (var j = 0; j < arr[i].length; ++j) { + carr[i][j] = arr[i][j]; + } + } -var SPLITTER = +(Math.pow(2, 27) + 1.0) + return carr; + } -function twoProduct(a, b, result) { - var x = a * b - var c = SPLITTER * a - var abig = c - a - var ahi = c - abig - var alo = a - ahi + function copy1D (arr) { + var carr = []; + for (var i = 0; i < arr.length; ++i) { + carr[i] = arr[i]; + } - var d = SPLITTER * b - var bbig = d - b - var bhi = d - bbig - var blo = b - bhi + return carr; + } - var err1 = x - (ahi * bhi) - var err2 = err1 - (alo * bhi) - var err3 = err2 - (ahi * blo) - var y = alo * blo - err3 + function isEqual(arr1, arr2) { + if(arr1.length !== arr2.length) + return false; + for(var i = arr1.length; i--;) { + if(arr1[i] !== arr2[i]) + return false; + } - if(result) { - result[0] = y - result[1] = x - return result + return true; } - return [ y, x ] -} -},{}],40:[function(require,module,exports){ -"use strict" -var twoProduct = require("two-product") -var robustSum = require("robust-sum") -var robustScale = require("robust-scale") -var compress = require("robust-compress") + function str2RgbArray(str, twoFiftySix) { + // convert hex or rbg strings to 0->1 or 0->255 rgb array + var rgb, + match; -var NUM_EXPANDED = 6 - -function cofactor(m, c) { - var result = new Array(m.length-1) - for(var i=1; i>1 - return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") - } -} - -function determinant(m) { - if(m.length === 2) { - return ["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("") - } else { - var expr = [] - for(var i=0; i 0) { - var f = cells[ptr-1] - if(compareCell(c, f) === 0 && - orientation(f) !== o) { - ptr -= 1 - continue - } - } - cells[ptr++] = c - } - cells.length = ptr - return cells -} - -},{"cell-orientation":43,"compare-cell":44,"compare-oriented-cell":45}],47:[function(require,module,exports){ -'use strict'; - -var arraytools = function () { - - var that = {}; - - var RGB_REGEX = /^rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(,.*)?\)$/; - var RGB_GROUP_REGEX = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,?\s*(.*)?\)$/; - - function isPlainObject (v) { - return !Array.isArray(v) && v !== null && typeof v === 'object'; - } - - function linspace (start, end, num) { - var inc = (end - start) / (num - 1); - var a = []; - for( var ii = 0; ii < num; ii++) - a.push(start + ii*inc); - return a; - } - - function zip () { - var arrays = [].slice.call(arguments); - var lengths = arrays.map(function (a) {return a.length;}); - var len = Math.min.apply(null, lengths); - var zipped = []; - for (var i = 0; i < len; i++) { - zipped[i] = []; - for (var j = 0; j < arrays.length; ++j) { - zipped[i][j] = arrays[j][i]; - } - } - return zipped; - } - - function zip3 (a, b, c) { - var len = Math.min.apply(null, [a.length, b.length, c.length]); - var result = []; - for (var n = 0; n < len; n++) { - result.push([a[n], b[n], c[n]]); - } - return result; - } - - function sum (A) { - var acc = 0; - accumulate(A, acc); - function accumulate(x) { - for (var i = 0; i < x.length; i++) { - if (Array.isArray(x[i])) - accumulate(x[i], acc); - else - acc += x[i]; - } - } - return acc; - } - - function copy2D (arr) { - var carr = []; - for (var i = 0; i < arr.length; ++i) { - carr[i] = []; - for (var j = 0; j < arr[i].length; ++j) { - carr[i][j] = arr[i][j]; - } - } - - return carr; - } - - - function copy1D (arr) { - var carr = []; - for (var i = 0; i < arr.length; ++i) { - carr[i] = arr[i]; - } - - return carr; - } - - - function isEqual(arr1, arr2) { - if(arr1.length !== arr2.length) - return false; - for(var i = arr1.length; i--;) { - if(arr1[i] !== arr2[i]) - return false; - } - - return true; - } - - - function str2RgbArray(str, twoFiftySix) { - // convert hex or rbg strings to 0->1 or 0->255 rgb array - var rgb, - match; - - if (typeof str !== 'string') return str; + if (typeof str !== 'string') return str; rgb = []; // hex notation @@ -3360,150 +2971,350 @@ var arraytools = function () { module.exports = arraytools(); -},{}],48:[function(require,module,exports){ -(function (global){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -/* eslint-disable no-proto */ - -'use strict' - -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('isarray') - -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 -Buffer.poolSize = 8192 // not used by this implementation - -var rootParent = {} - -/** - * If `Buffer.TYPED_ARRAY_SUPPORT`: - * === true Use Uint8Array implementation (fastest) - * === false Use Object implementation (most compatible, even IE6) - * - * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, - * Opera 11.6+, iOS 4.2+. - * - * Due to various browser bugs, sometimes the Object implementation will be used even - * when the browser supports typed arrays. - * - * Note: - * - * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, - * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. - * - * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property - * on objects. - * - * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. - * - * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of - * incorrect length in some situations. - - * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they - * get the Object implementation, which is slower but behaves correctly. - */ -Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined - ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() - -function typedArraySupport () { - function Bar () {} - try { - var arr = new Uint8Array(1) - arr.foo = function () { return 42 } - arr.constructor = Bar - return arr.foo() === 42 && // typed array instances can be augmented - arr.constructor === Bar && // constructor can be set - typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` - arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` - } catch (e) { - return false - } -} - -function kMaxLength () { - return Buffer.TYPED_ARRAY_SUPPORT - ? 0x7fffffff - : 0x3fffffff -} - +},{}],49:[function(require,module,exports){ /** - * Class: Buffer - * ============= + * Bit twiddling hacks for JavaScript. * - * The Buffer constructor returns instances of `Uint8Array` that are augmented - * with function properties for all the node `Buffer` API functions. We use - * `Uint8Array` so that square bracket notation works as expected -- it returns - * a single octet. + * Author: Mikola Lysenko * - * By augmenting the instances, we can avoid modifying the `Uint8Array` - * prototype. + * Ported from Stanford bit twiddling hack library: + * http://graphics.stanford.edu/~seander/bithacks.html */ -function Buffer (arg) { - if (!(this instanceof Buffer)) { - // Avoid going through an ArgumentsAdaptorTrampoline in the common case. - if (arguments.length > 1) return new Buffer(arg, arguments[1]) - return new Buffer(arg) - } - if (!Buffer.TYPED_ARRAY_SUPPORT) { - this.length = 0 - this.parent = undefined - } +"use strict"; "use restrict"; - // Common case. - if (typeof arg === 'number') { - return fromNumber(this, arg) - } +//Number of bits in an integer +var INT_BITS = 32; - // Slightly less common case. - if (typeof arg === 'string') { - return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') - } +//Constants +exports.INT_BITS = INT_BITS; +exports.INT_MAX = 0x7fffffff; +exports.INT_MIN = -1<<(INT_BITS-1); - // Unusual. - return fromObject(this, arg) +//Returns -1, 0, +1 depending on sign of x +exports.sign = function(v) { + return (v > 0) - (v < 0); } -function fromNumber (that, length) { - that = allocate(that, length < 0 ? 0 : checked(length) | 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) { - for (var i = 0; i < length; i++) { - that[i] = 0 - } - } - return that +//Computes absolute value of integer +exports.abs = function(v) { + var mask = v >> (INT_BITS-1); + return (v ^ mask) - mask; } -function fromString (that, string, encoding) { - if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' +//Computes minimum of integers x and y +exports.min = function(x, y) { + return y ^ ((x ^ y) & -(x < y)); +} - // Assumption: byteLength() return value is always < kMaxLength. - var length = byteLength(string, encoding) | 0 - that = allocate(that, length) +//Computes maximum of integers x and y +exports.max = function(x, y) { + return x ^ ((x ^ y) & -(x < y)); +} - that.write(string, encoding) - return that +//Checks if a number is a power of two +exports.isPow2 = function(v) { + return !(v & (v-1)) && (!!v); } -function fromObject (that, object) { - if (Buffer.isBuffer(object)) return fromBuffer(that, object) +//Computes log base 2 of v +exports.log2 = function(v) { + var r, shift; + r = (v > 0xFFFF) << 4; v >>>= r; + shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; + shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; + shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; + return r | (v >> 1); +} - if (isArray(object)) return fromArray(that, object) +//Computes log base 10 of v +exports.log10 = function(v) { + return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : + (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : + (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; +} - if (object == null) { - throw new TypeError('must start with number, buffer, array or string') - } +//Counts number of bits +exports.popCount = function(v) { + v = v - ((v >>> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); + return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; +} - if (typeof ArrayBuffer !== 'undefined') { +//Counts number of trailing zeros +function countTrailingZeros(v) { + var c = 32; + v &= -v; + if (v) c--; + if (v & 0x0000FFFF) c -= 16; + if (v & 0x00FF00FF) c -= 8; + if (v & 0x0F0F0F0F) c -= 4; + if (v & 0x33333333) c -= 2; + if (v & 0x55555555) c -= 1; + return c; +} +exports.countTrailingZeros = countTrailingZeros; + +//Rounds to next power of 2 +exports.nextPow2 = function(v) { + v += v === 0; + --v; + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v + 1; +} + +//Rounds down to previous power of 2 +exports.prevPow2 = function(v) { + v |= v >>> 1; + v |= v >>> 2; + v |= v >>> 4; + v |= v >>> 8; + v |= v >>> 16; + return v - (v>>>1); +} + +//Computes parity of word +exports.parity = function(v) { + v ^= v >>> 16; + v ^= v >>> 8; + v ^= v >>> 4; + v &= 0xf; + return (0x6996 >>> v) & 1; +} + +var REVERSE_TABLE = new Array(256); + +(function(tab) { + for(var i=0; i<256; ++i) { + var v = i, r = i, s = 7; + for (v >>>= 1; v; v >>>= 1) { + r <<= 1; + r |= v & 1; + --s; + } + tab[i] = (r << s) & 0xff; + } +})(REVERSE_TABLE); + +//Reverse bits in a 32 bit word +exports.reverse = function(v) { + return (REVERSE_TABLE[ v & 0xff] << 24) | + (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | + (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | + REVERSE_TABLE[(v >>> 24) & 0xff]; +} + +//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes +exports.interleave2 = function(x, y) { + x &= 0xFFFF; + x = (x | (x << 8)) & 0x00FF00FF; + x = (x | (x << 4)) & 0x0F0F0F0F; + x = (x | (x << 2)) & 0x33333333; + x = (x | (x << 1)) & 0x55555555; + + y &= 0xFFFF; + y = (y | (y << 8)) & 0x00FF00FF; + y = (y | (y << 4)) & 0x0F0F0F0F; + y = (y | (y << 2)) & 0x33333333; + y = (y | (y << 1)) & 0x55555555; + + return x | (y << 1); +} + +//Extracts the nth interleaved component +exports.deinterleave2 = function(v, n) { + v = (v >>> n) & 0x55555555; + v = (v | (v >>> 1)) & 0x33333333; + v = (v | (v >>> 2)) & 0x0F0F0F0F; + v = (v | (v >>> 4)) & 0x00FF00FF; + v = (v | (v >>> 16)) & 0x000FFFF; + return (v << 16) >> 16; +} + + +//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes +exports.interleave3 = function(x, y, z) { + x &= 0x3FF; + x = (x | (x<<16)) & 4278190335; + x = (x | (x<<8)) & 251719695; + x = (x | (x<<4)) & 3272356035; + x = (x | (x<<2)) & 1227133513; + + y &= 0x3FF; + y = (y | (y<<16)) & 4278190335; + y = (y | (y<<8)) & 251719695; + y = (y | (y<<4)) & 3272356035; + y = (y | (y<<2)) & 1227133513; + x |= (y << 1); + + z &= 0x3FF; + z = (z | (z<<16)) & 4278190335; + z = (z | (z<<8)) & 251719695; + z = (z | (z<<4)) & 3272356035; + z = (z | (z<<2)) & 1227133513; + + return x | (z << 2); +} + +//Extracts nth interleaved component of a 3-tuple +exports.deinterleave3 = function(v, n) { + v = (v >>> n) & 1227133513; + v = (v | (v>>>2)) & 3272356035; + v = (v | (v>>>4)) & 251719695; + v = (v | (v>>>8)) & 4278190335; + v = (v | (v>>>16)) & 0x3FF; + return (v<<22)>>22; +} + +//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) +exports.nextCombination = function(v) { + var t = v | (v - 1); + return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); +} + + +},{}],50:[function(require,module,exports){ +(function (global){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var isArray = require('isarray') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var rootParent = {} + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + +function typedArraySupport () { + try { + var arr = new Uint8Array(1) + arr.foo = function () { return 42 } + return arr.foo() === 42 && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +} + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (arg) { + if (!(this instanceof Buffer)) { + // Avoid going through an ArgumentsAdaptorTrampoline in the common case. + if (arguments.length > 1) return new Buffer(arg, arguments[1]) + return new Buffer(arg) + } + + if (!Buffer.TYPED_ARRAY_SUPPORT) { + this.length = 0 + this.parent = undefined + } + + // Common case. + if (typeof arg === 'number') { + return fromNumber(this, arg) + } + + // Slightly less common case. + if (typeof arg === 'string') { + return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') + } + + // Unusual. + return fromObject(this, arg) +} + +function fromNumber (that, length) { + that = allocate(that, length < 0 ? 0 : checked(length) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < length; i++) { + that[i] = 0 + } + } + return that +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' + + // Assumption: byteLength() return value is always < kMaxLength. + var length = byteLength(string, encoding) | 0 + that = allocate(that, length) + + that.write(string, encoding) + return that +} + +function fromObject (that, object) { + if (Buffer.isBuffer(object)) return fromBuffer(that, object) + + if (isArray(object)) return fromArray(that, object) + + if (object == null) { + throw new TypeError('must start with number, buffer, array or string') + } + + if (typeof ArrayBuffer !== 'undefined') { if (object.buffer instanceof ArrayBuffer) { return fromTypedArray(that, object) } @@ -3547,10 +3358,12 @@ function fromTypedArray (that, array) { } function fromArrayBuffer (that, array) { + array.byteLength // this throws if `array` is not a valid ArrayBuffer + if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance - array.byteLength - that = Buffer._augment(new Uint8Array(array)) + that = new Uint8Array(array) + that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that = fromTypedArray(that, new Uint8Array(array)) @@ -3597,12 +3410,11 @@ if (Buffer.TYPED_ARRAY_SUPPORT) { function allocate (that, length) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance - that = Buffer._augment(new Uint8Array(length)) + that = new Uint8Array(length) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that.length = length - that._isBuffer = true } var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 @@ -3785,6 +3597,10 @@ function slowToString (encoding, start, end) { } } +// Even though this property is private, it shouldn't be removed because it is +// used by `is-buffer` to detect buffer instances in Safari 5-7. +Buffer.prototype._isBuffer = true + Buffer.prototype.toString = function toString () { var length = this.length | 0 if (length === 0) return '' @@ -3855,18 +3671,6 @@ Buffer.prototype.indexOf = function indexOf (val, byteOffset) { throw new TypeError('val must be string, number or Buffer') } -// `get` is deprecated -Buffer.prototype.get = function get (offset) { - console.log('.get() is deprecated. Access using array indexes instead.') - return this.readUInt8(offset) -} - -// `set` is deprecated -Buffer.prototype.set = function set (v, offset) { - console.log('.set() is deprecated. Access using array indexes instead.') - return this.writeUInt8(v, offset) -} - function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 var remaining = buf.length - offset @@ -4162,7 +3966,8 @@ Buffer.prototype.slice = function slice (start, end) { var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = Buffer._augment(this.subarray(start, end)) + newBuf = this.subarray(start, end) + newBuf.__proto__ = Buffer.prototype } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) @@ -4642,7 +4447,11 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) { target[i + targetStart] = this[i + start] } } else { - target._set(this.subarray(start, start + len), targetStart) + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ) } return len @@ -4679,97 +4488,9 @@ Buffer.prototype.fill = function fill (value, start, end) { return this } -/** - * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. - * Added in Node 0.12. Only available in browsers that support ArrayBuffer. - */ -Buffer.prototype.toArrayBuffer = function toArrayBuffer () { - if (typeof Uint8Array !== 'undefined') { - if (Buffer.TYPED_ARRAY_SUPPORT) { - return (new Buffer(this)).buffer - } else { - var buf = new Uint8Array(this.length) - for (var i = 0, len = buf.length; i < len; i += 1) { - buf[i] = this[i] - } - return buf.buffer - } - } else { - throw new TypeError('Buffer.toArrayBuffer not supported in this browser') - } -} - // HELPER FUNCTIONS // ================ -var BP = Buffer.prototype - -/** - * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods - */ -Buffer._augment = function _augment (arr) { - arr.constructor = Buffer - arr._isBuffer = true - - // save reference to original Uint8Array set method before overwriting - arr._set = arr.set - - // deprecated - arr.get = BP.get - arr.set = BP.set - - arr.write = BP.write - arr.toString = BP.toString - arr.toLocaleString = BP.toString - arr.toJSON = BP.toJSON - arr.equals = BP.equals - arr.compare = BP.compare - arr.indexOf = BP.indexOf - arr.copy = BP.copy - arr.slice = BP.slice - arr.readUIntLE = BP.readUIntLE - arr.readUIntBE = BP.readUIntBE - arr.readUInt8 = BP.readUInt8 - arr.readUInt16LE = BP.readUInt16LE - arr.readUInt16BE = BP.readUInt16BE - arr.readUInt32LE = BP.readUInt32LE - arr.readUInt32BE = BP.readUInt32BE - arr.readIntLE = BP.readIntLE - arr.readIntBE = BP.readIntBE - arr.readInt8 = BP.readInt8 - arr.readInt16LE = BP.readInt16LE - arr.readInt16BE = BP.readInt16BE - arr.readInt32LE = BP.readInt32LE - arr.readInt32BE = BP.readInt32BE - arr.readFloatLE = BP.readFloatLE - arr.readFloatBE = BP.readFloatBE - arr.readDoubleLE = BP.readDoubleLE - arr.readDoubleBE = BP.readDoubleBE - arr.writeUInt8 = BP.writeUInt8 - arr.writeUIntLE = BP.writeUIntLE - arr.writeUIntBE = BP.writeUIntBE - arr.writeUInt16LE = BP.writeUInt16LE - arr.writeUInt16BE = BP.writeUInt16BE - arr.writeUInt32LE = BP.writeUInt32LE - arr.writeUInt32BE = BP.writeUInt32BE - arr.writeIntLE = BP.writeIntLE - arr.writeIntBE = BP.writeIntBE - arr.writeInt8 = BP.writeInt8 - arr.writeInt16LE = BP.writeInt16LE - arr.writeInt16BE = BP.writeInt16BE - arr.writeInt32LE = BP.writeInt32LE - arr.writeInt32BE = BP.writeInt32BE - arr.writeFloatLE = BP.writeFloatLE - arr.writeFloatBE = BP.writeFloatBE - arr.writeDoubleLE = BP.writeDoubleLE - arr.writeDoubleBE = BP.writeDoubleBE - arr.fill = BP.fill - arr.inspect = BP.inspect - arr.toArrayBuffer = BP.toArrayBuffer - - return arr -} - var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g function base64clean (str) { @@ -4912,133 +4633,127 @@ function blitBuffer (src, dst, offset, length) { } }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"base64-js":49,"ieee754":50,"isarray":51}],49:[function(require,module,exports){ -var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - +},{"base64-js":51,"ieee754":52,"isarray":53}],51:[function(require,module,exports){ ;(function (exports) { - 'use strict'; + 'use strict' + + var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' var Arr = (typeof Uint8Array !== 'undefined') ? Uint8Array : Array - var PLUS = '+'.charCodeAt(0) - var SLASH = '/'.charCodeAt(0) - var NUMBER = '0'.charCodeAt(0) - var LOWER = 'a'.charCodeAt(0) - var UPPER = 'A'.charCodeAt(0) - var PLUS_URL_SAFE = '-'.charCodeAt(0) - var SLASH_URL_SAFE = '_'.charCodeAt(0) - - function decode (elt) { - var code = elt.charCodeAt(0) - if (code === PLUS || - code === PLUS_URL_SAFE) - return 62 // '+' - if (code === SLASH || - code === SLASH_URL_SAFE) - return 63 // '/' - if (code < NUMBER) - return -1 //no match - if (code < NUMBER + 10) - return code - NUMBER + 26 + 26 - if (code < UPPER + 26) - return code - UPPER - if (code < LOWER + 26) - return code - LOWER + 26 - } + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) - function b64ToByteArray (b64) { - var i, j, l, tmp, placeHolders, arr - - if (b64.length % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } - - // the number of equal signs (place holders) - // if there are two placeholders, than the two characters before it - // represent one byte - // if there is only one, then the three characters before it represent 2 bytes - // this is just a cheap hack to not do indexOf twice - var len = b64.length - placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 - - // base64 is 4/3 + up to two characters of the original data - arr = new Arr(b64.length * 3 / 4 - placeHolders) - - // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? b64.length - 4 : b64.length - - var L = 0 - - function push (v) { - arr[L++] = v - } - - for (i = 0, j = 0; i < l; i += 4, j += 3) { - tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) - push((tmp & 0xFF0000) >> 16) - push((tmp & 0xFF00) >> 8) - push(tmp & 0xFF) - } - - if (placeHolders === 2) { - tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) - push(tmp & 0xFF) - } else if (placeHolders === 1) { - tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) - push((tmp >> 8) & 0xFF) - push(tmp & 0xFF) - } - - return arr - } + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS || code === PLUS_URL_SAFE) return 62 // '+' + if (code === SLASH || code === SLASH_URL_SAFE) return 63 // '/' + if (code < NUMBER) return -1 // no match + if (code < NUMBER + 10) return code - NUMBER + 26 + 26 + if (code < UPPER + 26) return code - UPPER + if (code < LOWER + 26) return code - LOWER + 26 + } - function uint8ToBase64 (uint8) { - var i, - extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes - output = "", - temp, length - - function encode (num) { - return lookup.charAt(num) - } - - function tripletToBase64 (num) { - return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) - } - - // go through the array every three bytes, we'll deal with trailing stuff later - for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { - temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) - output += tripletToBase64(temp) - } - - // pad the end with zeros, but make sure to not forget the extra bytes - switch (extraBytes) { - case 1: - temp = uint8[uint8.length - 1] - output += encode(temp >> 2) - output += encode((temp << 4) & 0x3F) - output += '==' - break - case 2: - temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) - output += encode(temp >> 10) - output += encode((temp >> 4) & 0x3F) - output += encode((temp << 2) & 0x3F) - output += '=' - break - } - - return output - } + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = b64.charAt(len - 2) === '=' ? 2 : b64.charAt(len - 1) === '=' ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i + var extraBytes = uint8.length % 3 // if we have 1 byte left, pad 2 bytes + var output = '' + var temp, length - exports.toByteArray = b64ToByteArray - exports.fromByteArray = uint8ToBase64 + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + default: + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 }(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) -},{}],50:[function(require,module,exports){ +},{}],52:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 @@ -5124,14 +4839,14 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { buffer[offset + i - d] |= s * 128 } -},{}],51:[function(require,module,exports){ +},{}],53:[function(require,module,exports){ var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; -},{}],52:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -5431,7 +5146,7 @@ function isUndefined(arg) { return arg === void 0; } -},{}],53:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ // shim for using process in browser var process = module.exports = {}; @@ -5524,7 +5239,366 @@ process.chdir = function (dir) { }; process.umask = function() { return 0; }; -},{}],54:[function(require,module,exports){ +},{}],56:[function(require,module,exports){ +module.exports={"jet":[{"index":0,"rgb":[0,0,131]},{"index":0.125,"rgb":[0,60,170]},{"index":0.375,"rgb":[5,255,255]},{"index":0.625,"rgb":[255,255,0]},{"index":0.875,"rgb":[250,0,0]},{"index":1,"rgb":[128,0,0]}],"hsv":[{"index":0,"rgb":[255,0,0]},{"index":0.169,"rgb":[253,255,2]},{"index":0.173,"rgb":[247,255,2]},{"index":0.337,"rgb":[0,252,4]},{"index":0.341,"rgb":[0,252,10]},{"index":0.506,"rgb":[1,249,255]},{"index":0.671,"rgb":[2,0,253]},{"index":0.675,"rgb":[8,0,253]},{"index":0.839,"rgb":[255,0,251]},{"index":0.843,"rgb":[255,0,245]},{"index":1,"rgb":[255,0,6]}],"hot":[{"index":0,"rgb":[0,0,0]},{"index":0.3,"rgb":[230,0,0]},{"index":0.6,"rgb":[255,210,0]},{"index":1,"rgb":[255,255,255]}],"cool":[{"index":0,"rgb":[0,255,255]},{"index":1,"rgb":[255,0,255]}],"spring":[{"index":0,"rgb":[255,0,255]},{"index":1,"rgb":[255,255,0]}],"summer":[{"index":0,"rgb":[0,128,102]},{"index":1,"rgb":[255,255,102]}],"autumn":[{"index":0,"rgb":[255,0,0]},{"index":1,"rgb":[255,255,0]}],"winter":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[0,255,128]}],"bone":[{"index":0,"rgb":[0,0,0]},{"index":0.376,"rgb":[84,84,116]},{"index":0.753,"rgb":[169,200,200]},{"index":1,"rgb":[255,255,255]}],"copper":[{"index":0,"rgb":[0,0,0]},{"index":0.804,"rgb":[255,160,102]},{"index":1,"rgb":[255,199,127]}],"greys":[{"index":0,"rgb":[0,0,0]},{"index":1,"rgb":[255,255,255]}],"yignbu":[{"index":0,"rgb":[8,29,88]},{"index":0.125,"rgb":[37,52,148]},{"index":0.25,"rgb":[34,94,168]},{"index":0.375,"rgb":[29,145,192]},{"index":0.5,"rgb":[65,182,196]},{"index":0.625,"rgb":[127,205,187]},{"index":0.75,"rgb":[199,233,180]},{"index":0.875,"rgb":[237,248,217]},{"index":1,"rgb":[255,255,217]}],"greens":[{"index":0,"rgb":[0,68,27]},{"index":0.125,"rgb":[0,109,44]},{"index":0.25,"rgb":[35,139,69]},{"index":0.375,"rgb":[65,171,93]},{"index":0.5,"rgb":[116,196,118]},{"index":0.625,"rgb":[161,217,155]},{"index":0.75,"rgb":[199,233,192]},{"index":0.875,"rgb":[229,245,224]},{"index":1,"rgb":[247,252,245]}],"yiorrd":[{"index":0,"rgb":[128,0,38]},{"index":0.125,"rgb":[189,0,38]},{"index":0.25,"rgb":[227,26,28]},{"index":0.375,"rgb":[252,78,42]},{"index":0.5,"rgb":[253,141,60]},{"index":0.625,"rgb":[254,178,76]},{"index":0.75,"rgb":[254,217,118]},{"index":0.875,"rgb":[255,237,160]},{"index":1,"rgb":[255,255,204]}],"bluered":[{"index":0,"rgb":[0,0,255]},{"index":1,"rgb":[255,0,0]}],"rdbu":[{"index":0,"rgb":[5,10,172]},{"index":0.35,"rgb":[106,137,247]},{"index":0.5,"rgb":[190,190,190]},{"index":0.6,"rgb":[220,170,132]},{"index":0.7,"rgb":[230,145,90]},{"index":1,"rgb":[178,10,28]}],"picnic":[{"index":0,"rgb":[0,0,255]},{"index":0.1,"rgb":[51,153,255]},{"index":0.2,"rgb":[102,204,255]},{"index":0.3,"rgb":[153,204,255]},{"index":0.4,"rgb":[204,204,255]},{"index":0.5,"rgb":[255,255,255]},{"index":0.6,"rgb":[255,204,255]},{"index":0.7,"rgb":[255,153,255]},{"index":0.8,"rgb":[255,102,204]},{"index":0.9,"rgb":[255,102,102]},{"index":1,"rgb":[255,0,0]}],"rainbow":[{"index":0,"rgb":[150,0,90]},{"index":0.125,"rgb":[0,0,200]},{"index":0.25,"rgb":[0,25,255]},{"index":0.375,"rgb":[0,152,255]},{"index":0.5,"rgb":[44,255,150]},{"index":0.625,"rgb":[151,255,0]},{"index":0.75,"rgb":[255,234,0]},{"index":0.875,"rgb":[255,111,0]},{"index":1,"rgb":[255,0,0]}],"portland":[{"index":0,"rgb":[12,51,131]},{"index":0.25,"rgb":[10,136,186]},{"index":0.5,"rgb":[242,211,56]},{"index":0.75,"rgb":[242,143,56]},{"index":1,"rgb":[217,30,30]}],"blackbody":[{"index":0,"rgb":[0,0,0]},{"index":0.2,"rgb":[230,0,0]},{"index":0.4,"rgb":[230,210,0]},{"index":0.7,"rgb":[255,255,255]},{"index":1,"rgb":[160,200,255]}],"earth":[{"index":0,"rgb":[0,0,130]},{"index":0.1,"rgb":[0,180,180]},{"index":0.2,"rgb":[40,210,40]},{"index":0.4,"rgb":[230,230,50]},{"index":0.6,"rgb":[120,70,20]},{"index":1,"rgb":[255,255,255]}],"electric":[{"index":0,"rgb":[0,0,0]},{"index":0.15,"rgb":[30,0,100]},{"index":0.4,"rgb":[120,0,100]},{"index":0.6,"rgb":[160,90,0]},{"index":0.8,"rgb":[230,200,0]},{"index":1,"rgb":[255,250,220]}], "alpha": [{"index":0, "rgb": [255,255,255,0]},{"index":0, "rgb": [255,255,255,1]}]}; + +},{}],57:[function(require,module,exports){ +/* + * Ben Postlethwaite + * January 2013 + * License MIT + */ +'use strict'; + +var at = require('arraytools'); +var clone = require('clone'); +var colorScale = require('./colorScales'); + +module.exports = function (spec) { + + /* + * Default Options + */ + var indicies, rgba, fromrgba, torgba, + nsteps, cmap, colormap, format, + nshades, colors, alpha, index, i, + r = [], + g = [], + b = [], + a = []; + + if ( !at.isPlainObject(spec) ) spec = {}; + + nshades = spec.nshades || 72; + format = spec.format || 'hex'; + + colormap = spec.colormap; + if (!colormap) colormap = 'jet'; + + if (typeof colormap === 'string') { + colormap = colormap.toLowerCase(); + + if (!colorScale[colormap]) { + throw Error(colormap + ' not a supported colorscale'); + } + + cmap = clone(colorScale[colormap]); + + } else if (Array.isArray(colormap)) { + cmap = clone(colormap); + + } else { + throw Error('unsupported colormap option', colormap); + } + + if (cmap.length > nshades) { + throw new Error( + colormap+' map requires nshades to be at least size '+cmap.length + ); + } + + if (!Array.isArray(spec.alpha)) { + + if (typeof spec.alpha === 'number') { + alpha = [spec.alpha, spec.alpha]; + + } else { + alpha = [1, 1]; + } + + } else if (spec.alpha.length !== 2) { + alpha = [1, 1]; + + } else { + alpha = clone(spec.alpha); + } + + /* + * map index points from 0->1 to 0 -> n-1 + */ + indicies = cmap.map(function(c) { + return Math.round(c.index * nshades); + }); + + /* + * Add alpha channel to the map + */ + if (alpha[0] < 0) alpha[0] = 0; + if (alpha[1] < 0) alpha[0] = 0; + if (alpha[0] > 1) alpha[0] = 1; + if (alpha[1] > 1) alpha[0] = 1; + + for (i = 0; i < indicies.length; ++i) { + index = cmap[i].index; + rgba = cmap[i].rgb; + + // if user supplies their own map use it + if (rgba.length === 4 && rgba[3] >= 0 && rgba[3] <= 1) continue; + rgba[3] = alpha[0] + (alpha[1] - alpha[0])*index; + } + + /* + * map increasing linear values between indicies to + * linear steps in colorvalues + */ + for (i = 0; i < indicies.length-1; ++i) { + nsteps = indicies[i+1] - indicies[i]; + fromrgba = cmap[i].rgb; + torgba = cmap[i+1].rgb; + r = r.concat(at.linspace(fromrgba[0], torgba[0], nsteps ) ); + g = g.concat(at.linspace(fromrgba[1], torgba[1], nsteps ) ); + b = b.concat(at.linspace(fromrgba[2], torgba[2], nsteps ) ); + a = a.concat(at.linspace(fromrgba[3], torgba[3], nsteps ) ); + } + + r = r.map( Math.round ); + g = g.map( Math.round ); + b = b.map( Math.round ); + + colors = at.zip(r, g, b, a); + + if (format === 'hex') colors = colors.map( rgb2hex ); + if (format === 'rgbaString') colors = colors.map( rgbaStr ); + + return colors; +}; + + +function rgb2hex (rgba) { + var dig, hex = '#'; + for (var i = 0; i < 3; ++i) { + dig = rgba[i]; + dig = dig.toString(16); + hex += ('00' + dig).substr( dig.length ); + } + return hex; +} + +function rgbaStr (rgba) { + return 'rgba(' + rgba.join(',') + ')'; +} + +},{"./colorScales":56,"arraytools":48,"clone":58}],58:[function(require,module,exports){ +(function (Buffer){ +var clone = (function() { +'use strict'; + +/** + * Clones (copies) an Object using deep copying. + * + * This function supports circular references by default, but if you are certain + * there are no circular references in your object, you can save some CPU time + * by calling clone(obj, false). + * + * Caution: if `circular` is false and `parent` contains circular references, + * your program may enter an infinite loop and crash. + * + * @param `parent` - the object to be cloned + * @param `circular` - set to true if the object to be cloned may contain + * circular references. (optional - true by default) + * @param `depth` - set to a number if the object is only to be cloned to + * a particular depth. (optional - defaults to Infinity) + * @param `prototype` - sets the prototype to be used when cloning an object. + * (optional - defaults to parent prototype). +*/ +function clone(parent, circular, depth, prototype) { + var filter; + if (typeof circular === 'object') { + depth = circular.depth; + prototype = circular.prototype; + filter = circular.filter; + circular = circular.circular + } + // maintain two arrays for circular references, where corresponding parents + // and children have the same index + var allParents = []; + var allChildren = []; + + var useBuffer = typeof Buffer != 'undefined'; + + if (typeof circular == 'undefined') + circular = true; + + if (typeof depth == 'undefined') + depth = Infinity; + + // recurse this function so we don't reset allParents and allChildren + function _clone(parent, depth) { + // cloning null always returns null + if (parent === null) + return null; + + if (depth == 0) + return parent; + + var child; + var proto; + if (typeof parent != 'object') { + return parent; + } + + if (clone.__isArray(parent)) { + child = []; + } else if (clone.__isRegExp(parent)) { + child = new RegExp(parent.source, __getRegExpFlags(parent)); + if (parent.lastIndex) child.lastIndex = parent.lastIndex; + } else if (clone.__isDate(parent)) { + child = new Date(parent.getTime()); + } else if (useBuffer && Buffer.isBuffer(parent)) { + child = new Buffer(parent.length); + parent.copy(child); + return child; + } else { + if (typeof prototype == 'undefined') { + proto = Object.getPrototypeOf(parent); + child = Object.create(proto); + } + else { + child = Object.create(prototype); + proto = prototype; + } + } + + if (circular) { + var index = allParents.indexOf(parent); + + if (index != -1) { + return allChildren[index]; + } + allParents.push(parent); + allChildren.push(child); + } + + for (var i in parent) { + var attrs; + if (proto) { + attrs = Object.getOwnPropertyDescriptor(proto, i); + } + + if (attrs && attrs.set == null) { + continue; + } + child[i] = _clone(parent[i], depth - 1); + } + + return child; + } + + return _clone(parent, depth); +} + +/** + * Simple flat clone using prototype, accepts only objects, usefull for property + * override on FLAT configuration object (no nested props). + * + * USE WITH CAUTION! This may not behave as you wish if you do not know how this + * works. + */ +clone.clonePrototype = function clonePrototype(parent) { + if (parent === null) + return null; + + var c = function () {}; + c.prototype = parent; + return new c(); +}; + +// private utility functions + +function __objToStr(o) { + return Object.prototype.toString.call(o); +}; +clone.__objToStr = __objToStr; + +function __isDate(o) { + return typeof o === 'object' && __objToStr(o) === '[object Date]'; +}; +clone.__isDate = __isDate; + +function __isArray(o) { + return typeof o === 'object' && __objToStr(o) === '[object Array]'; +}; +clone.__isArray = __isArray; + +function __isRegExp(o) { + return typeof o === 'object' && __objToStr(o) === '[object RegExp]'; +}; +clone.__isRegExp = __isRegExp; + +function __getRegExpFlags(re) { + var flags = ''; + if (re.global) flags += 'g'; + if (re.ignoreCase) flags += 'i'; + if (re.multiline) flags += 'm'; + return flags; +}; +clone.__getRegExpFlags = __getRegExpFlags; + +return clone; +})(); + +if (typeof module === 'object' && module.exports) { + module.exports = clone; +} + +}).call(this,require("buffer").Buffer) +},{"buffer":50}],59:[function(require,module,exports){ +module.exports = compareCells + +var min = Math.min + +function compareInt(a, b) { + return a - b +} + +function compareCells(a, b) { + var n = a.length + , t = a.length - b.length + if(t) { + return t + } + switch(n) { + case 0: + return 0 + case 1: + return a[0] - b[0] + case 2: + return (a[0]+a[1]-b[0]-b[1]) || + min(a[0],a[1]) - min(b[0],b[1]) + case 3: + var l1 = a[0]+a[1] + , m1 = b[0]+b[1] + t = l1+a[2] - (m1+b[2]) + if(t) { + return t + } + var l0 = min(a[0], a[1]) + , m0 = min(b[0], b[1]) + return min(l0, a[2]) - min(m0, b[2]) || + min(l0+a[2], l1) - min(m0+b[2], m1) + case 4: + var aw=a[0], ax=a[1], ay=a[2], az=a[3] + , bw=b[0], bx=b[1], by=b[2], bz=b[3] + return (aw+ax+ay+az)-(bw+bx+by+bz) || + min(aw,ax,ay,az)-min(bw,bx,by,bz,bw) || + min(aw+ax,aw+ay,aw+az,ax+ay,ax+az,ay+az) - + min(bw+bx,bw+by,bw+bz,bx+by,bx+bz,by+bz) || + min(aw+ax+ay,aw+ax+az,aw+ay+az,ax+ay+az) - + min(bw+bx+by,bw+bx+bz,bw+by+bz,bx+by+bz) + default: + var as = a.slice().sort(compareInt) + var bs = b.slice().sort(compareInt) + for(var i=0; i 0) { - code.push(",") - } - code.push("tuple[", i, "]") - } - code.push(")}return orient") - var proc = new Function("test", code.join("")) - var test = orient[d+1] - if(!test) { - test = orient - } - return proc(test) -} - -var BAKED = [] - -function Triangulation(dimension, vertices, simplices) { - this.dimension = dimension - this.vertices = vertices - this.simplices = simplices - this.interior = simplices.filter(function(c) { - return !c.boundary - }) - - this.tuple = new Array(dimension+1) - for(var i=0; i<=dimension; ++i) { - this.tuple[i] = this.vertices[i] - } +},{"robust-orientation":214}],65:[function(require,module,exports){ +'use strict' - var o = BAKED[dimension] - if(!o) { - o = BAKED[dimension] = bakeOrient(dimension) - } - this.orient = o -} +module.exports = monotoneConvexHull2D -var proto = Triangulation.prototype +var orient = require('robust-orientation')[3] -//Degenerate situation where we are on boundary, but coplanar to face -proto.handleBoundaryDegeneracy = function(cell, point) { - var d = this.dimension - var n = this.vertices.length - 1 - var tuple = this.tuple - var verts = this.vertices +function monotoneConvexHull2D(points) { + var n = points.length - //Dumb solution: Just do dfs from boundary cell until we find any peak, or terminate - var toVisit = [ cell ] - cell.lastVisited = -n - while(toVisit.length > 0) { - cell = toVisit.pop() - var cellVerts = cell.vertices - var cellAdj = cell.adjacent - for(var i=0; i<=d; ++i) { - var neighbor = cellAdj[i] - if(!neighbor.boundary || neighbor.lastVisited <= -n) { - continue - } - var nv = neighbor.vertices - for(var j=0; j<=d; ++j) { - var vv = nv[j] - if(vv < 0) { - tuple[j] = point - } else { - tuple[j] = verts[vv] - } - } - var o = this.orient() - if(o > 0) { - return neighbor - } - neighbor.lastVisited = -n - if(o === 0) { - toVisit.push(neighbor) - } + if(n < 3) { + var result = new Array(n) + for(var i=0; i= n) { - continue - } - var prev = tuple[i] - tuple[i] = point - var o = this.orient() - tuple[i] = prev - if(o < 0) { - cell = neighbor - continue outerLoop - } else { - if(!neighbor.boundary) { - neighbor.lastVisited = n - } else { - neighbor.lastVisited = -n - } - } - } - return + return result } - return cell -} - -proto.addPeaks = function(point, cell) { - var n = this.vertices.length - 1 - var d = this.dimension - var verts = this.vertices - var tuple = this.tuple - var interior = this.interior - var simplices = this.simplices - - //Walking finished at boundary, time to add peaks - var tovisit = [ cell ] - - //Stretch initial boundary cell into a peak - cell.lastVisited = n - cell.vertices[cell.vertices.indexOf(-1)] = n - cell.boundary = false - interior.push(cell) - - //Record a list of all new boundaries created by added peaks so we can glue them together when we are all done - var glueFacets = [] - - //Do a traversal of the boundary walking outward from starting peak - while(tovisit.length > 0) { - //Pop off peak and walk over adjacent cells - var cell = tovisit.pop() - var cellVerts = cell.vertices - var cellAdj = cell.adjacent - var indexOfN = cellVerts.indexOf(n) - if(indexOfN < 0) { - continue - } - - for(var i=0; i<=d; ++i) { - if(i === indexOfN) { - continue - } - - //For each boundary neighbor of the cell - var neighbor = cellAdj[i] - if(!neighbor.boundary || neighbor.lastVisited >= n) { - continue - } - - var nv = neighbor.vertices - - //Test if neighbor is a peak - if(neighbor.lastVisited !== -n) { - //Compute orientation of p relative to each boundary peak - var indexOfNeg1 = 0 - for(var j=0; j<=d; ++j) { - if(nv[j] < 0) { - indexOfNeg1 = j - tuple[j] = point - } else { - tuple[j] = verts[nv[j]] - } - } - var o = this.orient() - - //Test if neighbor cell is also a peak - if(o > 0) { - nv[indexOfNeg1] = n - neighbor.boundary = false - interior.push(neighbor) - tovisit.push(neighbor) - neighbor.lastVisited = n - continue - } else { - neighbor.lastVisited = -n - } - } - - var na = neighbor.adjacent - - //Otherwise, replace neighbor with new face - var vverts = cellVerts.slice() - var vadj = cellAdj.slice() - var ncell = new Simplex(vverts, vadj, true) - simplices.push(ncell) - - //Connect to neighbor - var opposite = na.indexOf(cell) - if(opposite < 0) { - continue - } - na[opposite] = ncell - vadj[indexOfN] = neighbor - - //Connect to cell - vverts[i] = -1 - vadj[i] = cell - cellAdj[i] = ncell - - //Flip facet - ncell.flip() - - //Add to glue list - for(var j=0; j<=d; ++j) { - var uu = vverts[j] - if(uu < 0 || uu === n) { - continue - } - var nface = new Array(d-1) - var nptr = 0 - for(var k=0; k<=d; ++k) { - var vv = vverts[k] - if(vv < 0 || k === j) { - continue - } - nface[nptr++] = vv - } - glueFacets.push(new GlueFacet(nface, ncell, j)) - } - } + //Sort point indices along x-axis + var sorted = new Array(n) + for(var i=0; i 1 && orient( + points[lower[m-2]], + points[lower[m-1]], + p) <= 0) { + m -= 1 + lower.pop() } - } - - //Add peaks - this.addPeaks(point, cell) -} + lower.push(idx) -//Extract all boundary cells -proto.boundary = function() { - var d = this.dimension - var boundary = [] - var cells = this.simplices - var nc = cells.length - for(var i=0; i= 0) { - bcell[ptr++] = cv[j] - } else { - parity = j&1 - } - } - if(parity === (d&1)) { - var t = bcell[0] - bcell[0] = bcell[1] - bcell[1] = t - } - boundary.push(bcell) + //Insert into upper list + m = upper.length + while(m > 1 && orient( + points[upper[m-2]], + points[upper[m-1]], + p) >= 0) { + m -= 1 + upper.pop() } - } - return boundary -} - -function incrementalConvexHull(points, randomSearch) { - var n = points.length - if(n === 0) { - throw new Error("Must have at least d+1 points") - } - var d = points[0].length - if(n <= d) { - throw new Error("Must input at least d+1 points") - } - - //FIXME: This could be degenerate, but need to select d+1 non-coplanar points to bootstrap process - var initialSimplex = points.slice(0, d+1) - - //Make sure initial simplex is positively oriented - var o = orient.apply(void 0, initialSimplex) - if(o === 0) { - throw new Error("Input not in general position") - } - var initialCoords = new Array(d+1) - for(var i=0; i<=d; ++i) { - initialCoords[i] = i - } - if(o < 0) { - initialCoords[0] = 1 - initialCoords[1] = 0 + upper.push(idx) } - //Create initial topological index, glue pointers together (kind of messy) - var initialCell = new Simplex(initialCoords, new Array(d+1), false) - var boundary = initialCell.adjacent - var list = new Array(d+2) - for(var i=0; i<=d; ++i) { - var verts = initialCoords.slice() - for(var j=0; j<=d; ++j) { - if(j === i) { - verts[j] = -1 - } - } - var t = verts[0] - verts[0] = verts[1] - verts[1] = t - var cell = new Simplex(verts, new Array(d+1), true) - boundary[i] = cell - list[i] = cell - } - list[d+1] = initialCell - for(var i=0; i<=d; ++i) { - var verts = boundary[i].vertices - var adj = boundary[i].adjacent - for(var j=0; j<=d; ++j) { - var v = verts[j] - if(v < 0) { - adj[j] = initialCell - continue - } - for(var k=0; k<=d; ++k) { - if(boundary[k].vertices.indexOf(v) < 0) { - adj[j] = boundary[k] - } - } - } + //Merge lists together + var result = new Array(upper.length + lower.length - 2) + var ptr = 0 + for(var i=0, nl=lower.length; i0; --j) { + result[ptr++] = upper[j] } - - //Extract boundary cells - return triangles.boundary() -} -},{"robust-orientation":996,"simplicial-complex":62}],60:[function(require,module,exports){ -/** - * Bit twiddling hacks for JavaScript. - * - * Author: Mikola Lysenko - * - * Ported from Stanford bit twiddling hack library: - * http://graphics.stanford.edu/~seander/bithacks.html - */ - -"use strict"; "use restrict"; - -//Number of bits in an integer -var INT_BITS = 32; - -//Constants -exports.INT_BITS = INT_BITS; -exports.INT_MAX = 0x7fffffff; -exports.INT_MIN = -1<<(INT_BITS-1); - -//Returns -1, 0, +1 depending on sign of x -exports.sign = function(v) { - return (v > 0) - (v < 0); -} -//Computes absolute value of integer -exports.abs = function(v) { - var mask = v >> (INT_BITS-1); - return (v ^ mask) - mask; -} - -//Computes minimum of integers x and y -exports.min = function(x, y) { - return y ^ ((x ^ y) & -(x < y)); -} - -//Computes maximum of integers x and y -exports.max = function(x, y) { - return x ^ ((x ^ y) & -(x < y)); -} - -//Checks if a number is a power of two -exports.isPow2 = function(v) { - return !(v & (v-1)) && (!!v); -} - -//Computes log base 2 of v -exports.log2 = function(v) { - var r, shift; - r = (v > 0xFFFF) << 4; v >>>= r; - shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift; - shift = (v > 0xF ) << 2; v >>>= shift; r |= shift; - shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift; - return r | (v >> 1); -} - -//Computes log base 10 of v -exports.log10 = function(v) { - return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 : - (v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 : - (v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0; + //Return result + return result } +},{"robust-orientation":214}],66:[function(require,module,exports){ +"use strict" + +var createThunk = require("./lib/thunk.js") + +function Procedure() { + this.argTypes = [] + this.shimArgs = [] + this.arrayArgs = [] + this.arrayBlockIndices = [] + this.scalarArgs = [] + this.offsetArgs = [] + this.offsetArgIndex = [] + this.indexArgs = [] + this.shapeArgs = [] + this.funcName = "" + this.pre = null + this.body = null + this.post = null + this.debug = false +} + +function compileCwise(user_args) { + //Create procedure + var proc = new Procedure() + + //Parse blocks + proc.pre = user_args.pre + proc.body = user_args.body + proc.post = user_args.post + + //Parse arguments + var proc_args = user_args.args.slice(0) + proc.argTypes = proc_args + for(var i=0; i0) { + throw new Error("cwise: pre() block may not reference array args") + } + if(i < proc.post.args.length && proc.post.args[i].count>0) { + throw new Error("cwise: post() block may not reference array args") + } + } else if(arg_type === "scalar") { + proc.scalarArgs.push(i) + proc.shimArgs.push("scalar" + i) + } else if(arg_type === "index") { + proc.indexArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { + throw new Error("cwise: pre() block may not reference array index") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array index") + } + if(i < proc.post.args.length && proc.post.args[i].count > 0) { + throw new Error("cwise: post() block may not reference array index") + } + } else if(arg_type === "shape") { + proc.shapeArgs.push(i) + if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { + throw new Error("cwise: pre() block may not write to array shape") + } + if(i < proc.body.args.length && proc.body.args[i].lvalue) { + throw new Error("cwise: body() block may not write to array shape") + } + if(i < proc.post.args.length && proc.post.args[i].lvalue) { + throw new Error("cwise: post() block may not write to array shape") + } + } else if(typeof arg_type === "object" && arg_type.offset) { + proc.argTypes[i] = "offset" + proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) + proc.offsetArgIndex.push(i) + } else { + throw new Error("cwise: Unknown argument type " + proc_args[i]) + } + } + + //Make sure at least one array argument was specified + if(proc.arrayArgs.length <= 0) { + throw new Error("cwise: No array arguments specified") + } + + //Make sure arguments are correct + if(proc.pre.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in pre() block") + } + if(proc.body.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in body() block") + } + if(proc.post.args.length > proc_args.length) { + throw new Error("cwise: Too many arguments in post() block") + } + + //Check debug flag + proc.debug = !!user_args.printCode || !!user_args.debug + + //Retrieve name + proc.funcName = user_args.funcName || "cwise" + + //Read in block size + proc.blockSize = user_args.blockSize || 64 + + return createThunk(proc) +} + +module.exports = compileCwise -//Counts number of bits -exports.popCount = function(v) { - v = v - ((v >>> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); - return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; -} +},{"./lib/thunk.js":68}],67:[function(require,module,exports){ +"use strict" + +var uniq = require("uniq") + +// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index) +// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments. +function innerFill(order, proc, body) { + var dimension = order.length + , nargs = proc.arrayArgs.length + , has_index = proc.indexArgs.length>0 + , code = [] + , vars = [] + , idx=0, pidx=0, i, j + for(i=0; i=0; --i) { // Start at largest stride and work your way inwards + idx = order[i] + code.push(["for(i",i,"=0;i",i," 0) { + code.push(["index[",pidx,"]-=s",pidx].join("")) + } + code.push(["++index[",idx,"]"].join("")) + } + code.push("}") + } + return code.join("\n") +} + +// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block. +// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. +// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used. +function outerFill(matched, order, proc, body) { + var dimension = order.length + , nargs = proc.arrayArgs.length + , blockSize = proc.blockSize + , has_index = proc.indexArgs.length > 0 + , code = [] + for(var i=0; i0;){"].join("")) // Iterate back to front + code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). + code.push(["s",order[i],"=j",i].join("")) + code.push(["j",i,"=0"].join("")) + code.push(["}else{s",order[i],"=",blockSize].join("")) + code.push(["j",i,"-=",blockSize,"}"].join("")) + if(has_index) { + code.push(["index[",order[i],"]=j",i].join("")) + } + } + for(var i=0; i 0) { + allEqual = allEqual && summary[i] === summary[i-1] + } + } + if(allEqual) { + return summary[0] + } + return summary.join("") +} + +//Generates a cwise operator +function generateCWiseOp(proc, typesig) { + + //Compute dimension + // Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg. + var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 + var orders = new Array(proc.arrayArgs.length) + var dtypes = new Array(proc.arrayArgs.length) + for(var i=0; i 0) { + vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example) + } + if(proc.indexArgs.length > 0) { + // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. + var zeros = new Array(dimension) + for(var i=0; i 3) { + code.push(processBlock(proc.pre, proc, dtypes)) + } + + //Process body + var body = processBlock(proc.body, proc, dtypes) + var matched = countMatches(loopOrders) + if(matched < dimension) { + code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example. + } else { + code.push(innerFill(loopOrders[0], proc, body)) + } + + //Inline epilog + if(proc.post.body.length > 3) { + code.push(processBlock(proc.post, proc, dtypes)) + } + + if(proc.debug) { + console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") + } + + var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") + var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) + return f() +} +module.exports = generateCWiseOp -//Counts number of trailing zeros -function countTrailingZeros(v) { - var c = 32; - v &= -v; - if (v) c--; - if (v & 0x0000FFFF) c -= 16; - if (v & 0x00FF00FF) c -= 8; - if (v & 0x0F0F0F0F) c -= 4; - if (v & 0x33333333) c -= 2; - if (v & 0x55555555) c -= 1; - return c; -} -exports.countTrailingZeros = countTrailingZeros; - -//Rounds to next power of 2 -exports.nextPow2 = function(v) { - v += v === 0; - --v; - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v + 1; -} - -//Rounds down to previous power of 2 -exports.prevPow2 = function(v) { - v |= v >>> 1; - v |= v >>> 2; - v |= v >>> 4; - v |= v >>> 8; - v |= v >>> 16; - return v - (v>>>1); -} - -//Computes parity of word -exports.parity = function(v) { - v ^= v >>> 16; - v ^= v >>> 8; - v ^= v >>> 4; - v &= 0xf; - return (0x6996 >>> v) & 1; -} - -var REVERSE_TABLE = new Array(256); - -(function(tab) { - for(var i=0; i<256; ++i) { - var v = i, r = i, s = 7; - for (v >>>= 1; v; v >>>= 1) { - r <<= 1; - r |= v & 1; - --s; - } - tab[i] = (r << s) & 0xff; - } -})(REVERSE_TABLE); - -//Reverse bits in a 32 bit word -exports.reverse = function(v) { - return (REVERSE_TABLE[ v & 0xff] << 24) | - (REVERSE_TABLE[(v >>> 8) & 0xff] << 16) | - (REVERSE_TABLE[(v >>> 16) & 0xff] << 8) | - REVERSE_TABLE[(v >>> 24) & 0xff]; -} - -//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes -exports.interleave2 = function(x, y) { - x &= 0xFFFF; - x = (x | (x << 8)) & 0x00FF00FF; - x = (x | (x << 4)) & 0x0F0F0F0F; - x = (x | (x << 2)) & 0x33333333; - x = (x | (x << 1)) & 0x55555555; - - y &= 0xFFFF; - y = (y | (y << 8)) & 0x00FF00FF; - y = (y | (y << 4)) & 0x0F0F0F0F; - y = (y | (y << 2)) & 0x33333333; - y = (y | (y << 1)) & 0x55555555; - - return x | (y << 1); -} - -//Extracts the nth interleaved component -exports.deinterleave2 = function(v, n) { - v = (v >>> n) & 0x55555555; - v = (v | (v >>> 1)) & 0x33333333; - v = (v | (v >>> 2)) & 0x0F0F0F0F; - v = (v | (v >>> 4)) & 0x00FF00FF; - v = (v | (v >>> 16)) & 0x000FFFF; - return (v << 16) >> 16; -} - - -//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes -exports.interleave3 = function(x, y, z) { - x &= 0x3FF; - x = (x | (x<<16)) & 4278190335; - x = (x | (x<<8)) & 251719695; - x = (x | (x<<4)) & 3272356035; - x = (x | (x<<2)) & 1227133513; - - y &= 0x3FF; - y = (y | (y<<16)) & 4278190335; - y = (y | (y<<8)) & 251719695; - y = (y | (y<<4)) & 3272356035; - y = (y | (y<<2)) & 1227133513; - x |= (y << 1); - - z &= 0x3FF; - z = (z | (z<<16)) & 4278190335; - z = (z | (z<<8)) & 251719695; - z = (z | (z<<4)) & 3272356035; - z = (z | (z<<2)) & 1227133513; - - return x | (z << 2); -} - -//Extracts nth interleaved component of a 3-tuple -exports.deinterleave3 = function(v, n) { - v = (v >>> n) & 1227133513; - v = (v | (v>>>2)) & 3272356035; - v = (v | (v>>>4)) & 251719695; - v = (v | (v>>>8)) & 4278190335; - v = (v | (v>>>16)) & 0x3FF; - return (v<<22)>>22; -} - -//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page) -exports.nextCombination = function(v) { - var t = v | (v - 1); - return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1)); -} - - -},{}],61:[function(require,module,exports){ -"use strict"; "use restrict"; - -module.exports = UnionFind; - -function UnionFind(count) { - this.roots = new Array(count); - this.ranks = new Array(count); - - for(var i=0; i> 1 - , s = compareCells(cells[mid], c) - if(s <= 0) { - if(s === 0) { - r = mid - } - lo = mid + 1 - } else if(s > 0) { - hi = mid - 1 - } - } - return r -} -exports.findCell = findCell; - -//Builds an index for an n-cell. This is more general than dual, but less efficient -function incidence(from_cells, to_cells) { - var index = new Array(from_cells.length) - for(var i=0, il=index.length; i= from_cells.length || compareCells(from_cells[idx], b) !== 0) { - break - } - } - } - } - return index -} -exports.incidence = incidence - -//Computes the dual of the mesh. This is basically an optimized version of buildIndex for the situation where from_cells is just the list of vertices -function dual(cells, vertex_count) { - if(!vertex_count) { - return incidence(unique(skeleton(cells, 0)), cells, 0) - } - var res = new Array(vertex_count) - for(var i=0; i>> k) & 1) { - b.push(c[k]) - } - } - result.push(b) - } - } - return normalize(result) -} -exports.explode = explode - -//Enumerates all of the n-cells of a cell complex -function skeleton(cells, n) { - if(n < 0) { - return [] - } - var result = [] - , k0 = (1<<(n+1))-1 - for(var i=0; i 1 && orient( - points[lower[m-2]], - points[lower[m-1]], - p) <= 0) { - m -= 1 - lower.pop() - } - lower.push(idx) - - //Insert into upper list - m = upper.length - while(m > 1 && orient( - points[upper[m-2]], - points[upper[m-1]], - p) >= 0) { - m -= 1 - upper.pop() - } - upper.push(idx) - } - - //Merge lists together - var result = new Array(upper.length + lower.length - 2) - var ptr = 0 - for(var i=0, nl=lower.length; i0; --j) { - result[ptr++] = upper[j] - } - - //Return result - return result -} -},{"robust-orientation":996}],64:[function(require,module,exports){ -!function() { - var d3 = { - version: "3.5.6" - }; - var d3_arraySlice = [].slice, d3_array = function(list) { - return d3_arraySlice.call(list); - }; - var d3_document = this.document; - function d3_documentElement(node) { - return node && (node.ownerDocument || node.document || node).documentElement; - } - function d3_window(node) { - return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); - } - if (d3_document) { - try { - d3_array(d3_document.documentElement.childNodes)[0].nodeType; - } catch (e) { - d3_array = function(list) { - var i = list.length, array = new Array(i); - while (i--) array[i] = list[i]; - return array; - }; - } - } - if (!Date.now) Date.now = function() { - return +new Date(); - }; - if (d3_document) { - try { - d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); - } catch (error) { - var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; - d3_element_prototype.setAttribute = function(name, value) { - d3_element_setAttribute.call(this, name, value + ""); - }; - d3_element_prototype.setAttributeNS = function(space, local, value) { - d3_element_setAttributeNS.call(this, space, local, value + ""); - }; - d3_style_prototype.setProperty = function(name, value, priority) { - d3_style_setProperty.call(this, name, value + "", priority); - }; - } - } - d3.ascending = d3_ascending; - function d3_ascending(a, b) { - return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; - } - d3.descending = function(a, b) { - return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; - }; - d3.min = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && a > b) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; - } - return a; - }; - d3.max = function(array, f) { - var i = -1, n = array.length, a, b; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = array[i]) != null && b > a) a = b; - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; - } - return a; - }; - d3.extent = function(array, f) { - var i = -1, n = array.length, a, b, c; - if (arguments.length === 1) { - while (++i < n) if ((b = array[i]) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = array[i]) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } else { - while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { - a = c = b; - break; - } - while (++i < n) if ((b = f.call(array, array[i], i)) != null) { - if (a > b) a = b; - if (c < b) c = b; - } - } - return [ a, c ]; - }; - function d3_number(x) { - return x === null ? NaN : +x; - } - function d3_numeric(x) { - return !isNaN(x); - } - d3.sum = function(array, f) { - var s = 0, n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = +array[i])) s += a; - } else { - while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; - } - return s; - }; - d3.mean = function(array, f) { - var s = 0, n = array.length, a, i = -1, j = n; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; - } - if (j) return s / j; - }; - d3.quantile = function(values, p) { - var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; - return e ? v + e * (values[h] - v) : v; - }; - d3.median = function(array, f) { - var numbers = [], n = array.length, a, i = -1; - if (arguments.length === 1) { - while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); - } else { - while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); - } - if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); - }; - d3.variance = function(array, f) { - var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; - if (arguments.length === 1) { - while (++i < n) { - if (d3_numeric(a = d3_number(array[i]))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } else { - while (++i < n) { - if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { - d = a - m; - m += d / ++j; - s += d * (a - m); - } - } - } - if (j > 1) return s / (j - 1); - }; - d3.deviation = function() { - var v = d3.variance.apply(this, arguments); - return v ? Math.sqrt(v) : v; - }; - function d3_bisector(compare) { - return { - left: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; - } - return lo; - }, - right: function(a, x, lo, hi) { - if (arguments.length < 3) lo = 0; - if (arguments.length < 4) hi = a.length; - while (lo < hi) { - var mid = lo + hi >>> 1; - if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; - } - return lo; - } - }; - } - var d3_bisect = d3_bisector(d3_ascending); - d3.bisectLeft = d3_bisect.left; - d3.bisect = d3.bisectRight = d3_bisect.right; - d3.bisector = function(f) { - return d3_bisector(f.length === 1 ? function(d, x) { - return d3_ascending(f(d), x); - } : f); - }; - d3.shuffle = function(array, i0, i1) { - if ((m = arguments.length) < 3) { - i1 = array.length; - if (m < 2) i0 = 0; - } - var m = i1 - i0, t, i; - while (m) { - i = Math.random() * m-- | 0; - t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; - } - return array; - }; - d3.permute = function(array, indexes) { - var i = indexes.length, permutes = new Array(i); - while (i--) permutes[i] = array[indexes[i]]; - return permutes; - }; - d3.pairs = function(array) { - var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); - while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; - return pairs; - }; - d3.zip = function() { - if (!(n = arguments.length)) return []; - for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { - for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { - zip[j] = arguments[j][i]; - } - } - return zips; - }; - function d3_zipLength(d) { - return d.length; - } - d3.transpose = function(matrix) { - return d3.zip.apply(d3, matrix); - }; - d3.keys = function(map) { - var keys = []; - for (var key in map) keys.push(key); - return keys; - }; - d3.values = function(map) { - var values = []; - for (var key in map) values.push(map[key]); - return values; - }; - d3.entries = function(map) { - var entries = []; - for (var key in map) entries.push({ - key: key, - value: map[key] - }); - return entries; - }; - d3.merge = function(arrays) { - var n = arrays.length, m, i = -1, j = 0, merged, array; - while (++i < n) j += arrays[i].length; - merged = new Array(j); - while (--n >= 0) { - array = arrays[n]; - m = array.length; - while (--m >= 0) { - merged[--j] = array[m]; - } - } - return merged; - }; - var abs = Math.abs; - d3.range = function(start, stop, step) { - if (arguments.length < 3) { - step = 1; - if (arguments.length < 2) { - stop = start; - start = 0; - } - } - if ((stop - start) / step === Infinity) throw new Error("infinite range"); - var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; - start *= k, stop *= k, step *= k; - if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); - return range; - }; - function d3_range_integerScale(x) { - var k = 1; - while (x * k % 1) k *= 10; - return k; - } - function d3_class(ctor, properties) { - for (var key in properties) { - Object.defineProperty(ctor.prototype, key, { - value: properties[key], - enumerable: false - }); - } - } - d3.map = function(object, f) { - var map = new d3_Map(); - if (object instanceof d3_Map) { - object.forEach(function(key, value) { - map.set(key, value); - }); - } else if (Array.isArray(object)) { - var i = -1, n = object.length, o; - if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); - } else { - for (var key in object) map.set(key, object[key]); - } - return map; - }; - function d3_Map() { - this._ = Object.create(null); - } - var d3_map_proto = "__proto__", d3_map_zero = "\x00"; - d3_class(d3_Map, { - has: d3_map_has, - get: function(key) { - return this._[d3_map_escape(key)]; - }, - set: function(key, value) { - return this._[d3_map_escape(key)] = value; - }, - remove: d3_map_remove, - keys: d3_map_keys, - values: function() { - var values = []; - for (var key in this._) values.push(this._[key]); - return values; - }, - entries: function() { - var entries = []; - for (var key in this._) entries.push({ - key: d3_map_unescape(key), - value: this._[key] - }); - return entries; - }, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); - } - }); - function d3_map_escape(key) { - return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; - } - function d3_map_unescape(key) { - return (key += "")[0] === d3_map_zero ? key.slice(1) : key; - } - function d3_map_has(key) { - return d3_map_escape(key) in this._; - } - function d3_map_remove(key) { - return (key = d3_map_escape(key)) in this._ && delete this._[key]; - } - function d3_map_keys() { - var keys = []; - for (var key in this._) keys.push(d3_map_unescape(key)); - return keys; - } - function d3_map_size() { - var size = 0; - for (var key in this._) ++size; - return size; - } - function d3_map_empty() { - for (var key in this._) return false; - return true; - } - d3.nest = function() { - var nest = {}, keys = [], sortKeys = [], sortValues, rollup; - function map(mapType, array, depth) { - if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; - var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; - while (++i < n) { - if (values = valuesByKey.get(keyValue = key(object = array[i]))) { - values.push(object); - } else { - valuesByKey.set(keyValue, [ object ]); - } - } - if (mapType) { - object = mapType(); - setter = function(keyValue, values) { - object.set(keyValue, map(mapType, values, depth)); - }; - } else { - object = {}; - setter = function(keyValue, values) { - object[keyValue] = map(mapType, values, depth); - }; - } - valuesByKey.forEach(setter); - return object; - } - function entries(map, depth) { - if (depth >= keys.length) return map; - var array = [], sortKey = sortKeys[depth++]; - map.forEach(function(key, keyMap) { - array.push({ - key: key, - values: entries(keyMap, depth) - }); - }); - return sortKey ? array.sort(function(a, b) { - return sortKey(a.key, b.key); - }) : array; - } - nest.map = function(array, mapType) { - return map(mapType, array, 0); - }; - nest.entries = function(array) { - return entries(map(d3.map, array, 0), 0); - }; - nest.key = function(d) { - keys.push(d); - return nest; - }; - nest.sortKeys = function(order) { - sortKeys[keys.length - 1] = order; - return nest; - }; - nest.sortValues = function(order) { - sortValues = order; - return nest; - }; - nest.rollup = function(f) { - rollup = f; - return nest; - }; - return nest; - }; - d3.set = function(array) { - var set = new d3_Set(); - if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); - return set; - }; - function d3_Set() { - this._ = Object.create(null); - } - d3_class(d3_Set, { - has: d3_map_has, - add: function(key) { - this._[d3_map_escape(key += "")] = true; - return key; - }, - remove: d3_map_remove, - values: d3_map_keys, - size: d3_map_size, - empty: d3_map_empty, - forEach: function(f) { - for (var key in this._) f.call(this, d3_map_unescape(key)); - } - }); - d3.behavior = {}; - function d3_identity(d) { - return d; - } - d3.rebind = function(target, source) { - var i = 1, n = arguments.length, method; - while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); - return target; - }; - function d3_rebind(target, source, method) { - return function() { - var value = method.apply(source, arguments); - return value === source ? target : value; - }; - } - function d3_vendorSymbol(object, name) { - if (name in object) return name; - name = name.charAt(0).toUpperCase() + name.slice(1); - for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { - var prefixName = d3_vendorPrefixes[i] + name; - if (prefixName in object) return prefixName; - } - } - var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; - function d3_noop() {} - d3.dispatch = function() { - var dispatch = new d3_dispatch(), i = -1, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - return dispatch; - }; - function d3_dispatch() {} - d3_dispatch.prototype.on = function(type, listener) { - var i = type.indexOf("."), name = ""; - if (i >= 0) { - name = type.slice(i + 1); - type = type.slice(0, i); - } - if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); - if (arguments.length === 2) { - if (listener == null) for (type in this) { - if (this.hasOwnProperty(type)) this[type].on(name, null); - } - return this; - } - }; - function d3_dispatch_event(dispatch) { - var listeners = [], listenerByName = new d3_Map(); - function event() { - var z = listeners, i = -1, n = z.length, l; - while (++i < n) if (l = z[i].on) l.apply(this, arguments); - return dispatch; - } - event.on = function(name, listener) { - var l = listenerByName.get(name), i; - if (arguments.length < 2) return l && l.on; - if (l) { - l.on = null; - listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); - listenerByName.remove(name); - } - if (listener) listeners.push(listenerByName.set(name, { - on: listener - })); - return dispatch; - }; - return event; - } - d3.event = null; - function d3_eventPreventDefault() { - d3.event.preventDefault(); - } - function d3_eventSource() { - var e = d3.event, s; - while (s = e.sourceEvent) e = s; - return e; - } - function d3_eventDispatch(target) { - var dispatch = new d3_dispatch(), i = 0, n = arguments.length; - while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); - dispatch.of = function(thiz, argumentz) { - return function(e1) { - try { - var e0 = e1.sourceEvent = d3.event; - e1.target = target; - d3.event = e1; - dispatch[e1.type].apply(thiz, argumentz); - } finally { - d3.event = e0; - } - }; - }; - return dispatch; - } - d3.requote = function(s) { - return s.replace(d3_requote_re, "\\$&"); - }; - var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; - var d3_subclass = {}.__proto__ ? function(object, prototype) { - object.__proto__ = prototype; - } : function(object, prototype) { - for (var property in prototype) object[property] = prototype[property]; - }; - function d3_selection(groups) { - d3_subclass(groups, d3_selectionPrototype); - return groups; - } - var d3_select = function(s, n) { - return n.querySelector(s); - }, d3_selectAll = function(s, n) { - return n.querySelectorAll(s); - }, d3_selectMatches = function(n, s) { - var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; - d3_selectMatches = function(n, s) { - return d3_selectMatcher.call(n, s); - }; - return d3_selectMatches(n, s); - }; - if (typeof Sizzle === "function") { - d3_select = function(s, n) { - return Sizzle(s, n)[0] || null; - }; - d3_selectAll = Sizzle; - d3_selectMatches = Sizzle.matchesSelector; - } - d3.selection = function() { - return d3.select(d3_document.documentElement); - }; - var d3_selectionPrototype = d3.selection.prototype = []; - d3_selectionPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, group, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(subnode = selector.call(node, node.__data__, i, j)); - if (subnode && "__data__" in node) subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selector(selector) { - return typeof selector === "function" ? selector : function() { - return d3_select(selector, this); - }; - } - d3_selectionPrototype.selectAll = function(selector) { - var subgroups = [], subgroup, node; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); - subgroup.parentNode = node; - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_selectorAll(selector) { - return typeof selector === "function" ? selector : function() { - return d3_selectAll(selector, this); - }; - } - var d3_nsPrefix = { - svg: "http://www.w3.org/2000/svg", - xhtml: "http://www.w3.org/1999/xhtml", - xlink: "http://www.w3.org/1999/xlink", - xml: "http://www.w3.org/XML/1998/namespace", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - d3.ns = { - prefix: d3_nsPrefix, - qualify: function(name) { - var i = name.indexOf(":"), prefix = name; - if (i >= 0) { - prefix = name.slice(0, i); - name = name.slice(i + 1); - } - return d3_nsPrefix.hasOwnProperty(prefix) ? { - space: d3_nsPrefix[prefix], - local: name - } : name; - } - }; - d3_selectionPrototype.attr = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(); - name = d3.ns.qualify(name); - return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); - } - for (value in name) this.each(d3_selection_attr(value, name[value])); - return this; - } - return this.each(d3_selection_attr(name, value)); - }; - function d3_selection_attr(name, value) { - name = d3.ns.qualify(name); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrConstant() { - this.setAttribute(name, value); - } - function attrConstantNS() { - this.setAttributeNS(name.space, name.local, value); - } - function attrFunction() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); - } - function attrFunctionNS() { - var x = value.apply(this, arguments); - if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); - } - return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; - } - function d3_collapse(s) { - return s.trim().replace(/\s+/g, " "); - } - d3_selectionPrototype.classed = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") { - var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; - if (value = node.classList) { - while (++i < n) if (!value.contains(name[i])) return false; - } else { - value = node.getAttribute("class"); - while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; - } - return true; - } - for (value in name) this.each(d3_selection_classed(value, name[value])); - return this; - } - return this.each(d3_selection_classed(name, value)); - }; - function d3_selection_classedRe(name) { - return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); - } - function d3_selection_classes(name) { - return (name + "").trim().split(/^|\s+/); - } - function d3_selection_classed(name, value) { - name = d3_selection_classes(name).map(d3_selection_classedName); - var n = name.length; - function classedConstant() { - var i = -1; - while (++i < n) name[i](this, value); - } - function classedFunction() { - var i = -1, x = value.apply(this, arguments); - while (++i < n) name[i](this, x); - } - return typeof value === "function" ? classedFunction : classedConstant; - } - function d3_selection_classedName(name) { - var re = d3_selection_classedRe(name); - return function(node, value) { - if (c = node.classList) return value ? c.add(name) : c.remove(name); - var c = node.getAttribute("class") || ""; - if (value) { - re.lastIndex = 0; - if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); - } else { - node.setAttribute("class", d3_collapse(c.replace(re, " "))); - } - }; - } - d3_selectionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); - return this; - } - if (n < 2) { - var node = this.node(); - return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); - } - priority = ""; - } - return this.each(d3_selection_style(name, value, priority)); - }; - function d3_selection_style(name, value, priority) { - function styleNull() { - this.style.removeProperty(name); - } - function styleConstant() { - this.style.setProperty(name, value, priority); - } - function styleFunction() { - var x = value.apply(this, arguments); - if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); - } - return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; - } - d3_selectionPrototype.property = function(name, value) { - if (arguments.length < 2) { - if (typeof name === "string") return this.node()[name]; - for (value in name) this.each(d3_selection_property(value, name[value])); - return this; - } - return this.each(d3_selection_property(name, value)); - }; - function d3_selection_property(name, value) { - function propertyNull() { - delete this[name]; - } - function propertyConstant() { - this[name] = value; - } - function propertyFunction() { - var x = value.apply(this, arguments); - if (x == null) delete this[name]; else this[name] = x; - } - return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; - } - d3_selectionPrototype.text = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.textContent = v == null ? "" : v; - } : value == null ? function() { - this.textContent = ""; - } : function() { - this.textContent = value; - }) : this.node().textContent; - }; - d3_selectionPrototype.html = function(value) { - return arguments.length ? this.each(typeof value === "function" ? function() { - var v = value.apply(this, arguments); - this.innerHTML = v == null ? "" : v; - } : value == null ? function() { - this.innerHTML = ""; - } : function() { - this.innerHTML = value; - }) : this.node().innerHTML; - }; - d3_selectionPrototype.append = function(name) { - name = d3_selection_creator(name); - return this.select(function() { - return this.appendChild(name.apply(this, arguments)); - }); - }; - function d3_selection_creator(name) { - function create() { - var document = this.ownerDocument, namespace = this.namespaceURI; - return namespace ? document.createElementNS(namespace, name) : document.createElement(name); - } - function createNS() { - return this.ownerDocument.createElementNS(name.space, name.local); - } - return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; - } - d3_selectionPrototype.insert = function(name, before) { - name = d3_selection_creator(name); - before = d3_selection_selector(before); - return this.select(function() { - return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); - }); - }; - d3_selectionPrototype.remove = function() { - return this.each(d3_selectionRemove); - }; - function d3_selectionRemove() { - var parent = this.parentNode; - if (parent) parent.removeChild(this); - } - d3_selectionPrototype.data = function(value, key) { - var i = -1, n = this.length, group, node; - if (!arguments.length) { - value = new Array(n = (group = this[0]).length); - while (++i < n) { - if (node = group[i]) { - value[i] = node.__data__; - } - } - return value; - } - function bind(group, groupData) { - var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; - if (key) { - var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) { - exitNodes[i] = node; - } else { - nodeByKeyValue.set(keyValue, node); - } - keyValues[i] = keyValue; - } - for (i = -1; ++i < m; ) { - if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { - enterNodes[i] = d3_selection_dataNode(nodeData); - } else if (node !== true) { - updateNodes[i] = node; - node.__data__ = nodeData; - } - nodeByKeyValue.set(keyValue, true); - } - for (i = -1; ++i < n; ) { - if (nodeByKeyValue.get(keyValues[i]) !== true) { - exitNodes[i] = group[i]; - } - } - } else { - for (i = -1; ++i < n0; ) { - node = group[i]; - nodeData = groupData[i]; - if (node) { - node.__data__ = nodeData; - updateNodes[i] = node; - } else { - enterNodes[i] = d3_selection_dataNode(nodeData); - } - } - for (;i < m; ++i) { - enterNodes[i] = d3_selection_dataNode(groupData[i]); - } - for (;i < n; ++i) { - exitNodes[i] = group[i]; - } - } - enterNodes.update = updateNodes; - enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; - enter.push(enterNodes); - update.push(updateNodes); - exit.push(exitNodes); - } - var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); - if (typeof value === "function") { - while (++i < n) { - bind(group = this[i], value.call(group, group.parentNode.__data__, i)); - } - } else { - while (++i < n) { - bind(group = this[i], value); - } - } - update.enter = function() { - return enter; - }; - update.exit = function() { - return exit; - }; - return update; - }; - function d3_selection_dataNode(data) { - return { - __data__: data - }; - } - d3_selectionPrototype.datum = function(value) { - return arguments.length ? this.property("__data__", value) : this.property("__data__"); - }; - d3_selectionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - subgroup.parentNode = (group = this[j]).parentNode; - for (var i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } - } - return d3_selection(subgroups); - }; - function d3_selection_filter(selector) { - return function() { - return d3_selectMatches(this, selector); - }; - } - d3_selectionPrototype.order = function() { - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { - if (node = group[i]) { - if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); - next = node; - } - } - } - return this; - }; - d3_selectionPrototype.sort = function(comparator) { - comparator = d3_selection_sortComparator.apply(this, arguments); - for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); - return this.order(); - }; - function d3_selection_sortComparator(comparator) { - if (!arguments.length) comparator = d3_ascending; - return function(a, b) { - return a && b ? comparator(a.__data__, b.__data__) : !a - !b; - }; - } - d3_selectionPrototype.each = function(callback) { - return d3_selection_each(this, function(node, i, j) { - callback.call(node, node.__data__, i, j); - }); - }; - function d3_selection_each(groups, callback) { - for (var j = 0, m = groups.length; j < m; j++) { - for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { - if (node = group[i]) callback(node, i, j); - } - } - return groups; - } - d3_selectionPrototype.call = function(callback) { - var args = d3_array(arguments); - callback.apply(args[0] = this, args); - return this; - }; - d3_selectionPrototype.empty = function() { - return !this.node(); - }; - d3_selectionPrototype.node = function() { - for (var j = 0, m = this.length; j < m; j++) { - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - var node = group[i]; - if (node) return node; - } - } - return null; - }; - d3_selectionPrototype.size = function() { - var n = 0; - d3_selection_each(this, function() { - ++n; - }); - return n; - }; - function d3_selection_enter(selection) { - d3_subclass(selection, d3_selection_enterPrototype); - return selection; - } - var d3_selection_enterPrototype = []; - d3.selection.enter = d3_selection_enter; - d3.selection.enter.prototype = d3_selection_enterPrototype; - d3_selection_enterPrototype.append = d3_selectionPrototype.append; - d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; - d3_selection_enterPrototype.node = d3_selectionPrototype.node; - d3_selection_enterPrototype.call = d3_selectionPrototype.call; - d3_selection_enterPrototype.size = d3_selectionPrototype.size; - d3_selection_enterPrototype.select = function(selector) { - var subgroups = [], subgroup, subnode, upgroup, group, node; - for (var j = -1, m = this.length; ++j < m; ) { - upgroup = (group = this[j]).update; - subgroups.push(subgroup = []); - subgroup.parentNode = group.parentNode; - for (var i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); - subnode.__data__ = node.__data__; - } else { - subgroup.push(null); - } - } - } - return d3_selection(subgroups); - }; - d3_selection_enterPrototype.insert = function(name, before) { - if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); - return d3_selectionPrototype.insert.call(this, name, before); - }; - function d3_selection_enterInsertBefore(enter) { - var i0, j0; - return function(d, i, j) { - var group = enter[j].update, n = group.length, node; - if (j != j0) j0 = j, i0 = 0; - if (i >= i0) i0 = i + 1; - while (!(node = group[i0]) && ++i0 < n) ; - return node; - }; - } - d3.select = function(node) { - var group; - if (typeof node === "string") { - group = [ d3_select(node, d3_document) ]; - group.parentNode = d3_document.documentElement; - } else { - group = [ node ]; - group.parentNode = d3_documentElement(node); - } - return d3_selection([ group ]); - }; - d3.selectAll = function(nodes) { - var group; - if (typeof nodes === "string") { - group = d3_array(d3_selectAll(nodes, d3_document)); - group.parentNode = d3_document.documentElement; - } else { - group = nodes; - group.parentNode = null; - } - return d3_selection([ group ]); - }; - d3_selectionPrototype.on = function(type, listener, capture) { - var n = arguments.length; - if (n < 3) { - if (typeof type !== "string") { - if (n < 2) listener = false; - for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); - return this; - } - if (n < 2) return (n = this.node()["__on" + type]) && n._; - capture = false; - } - return this.each(d3_selection_on(type, listener, capture)); - }; - function d3_selection_on(type, listener, capture) { - var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; - if (i > 0) type = type.slice(0, i); - var filter = d3_selection_onFilters.get(type); - if (filter) type = filter, wrap = d3_selection_onFilter; - function onRemove() { - var l = this[name]; - if (l) { - this.removeEventListener(type, l, l.$); - delete this[name]; - } - } - function onAdd() { - var l = wrap(listener, d3_array(arguments)); - onRemove.call(this); - this.addEventListener(type, this[name] = l, l.$ = capture); - l._ = listener; - } - function removeAll() { - var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; - for (var name in this) { - if (match = name.match(re)) { - var l = this[name]; - this.removeEventListener(match[1], l, l.$); - delete this[name]; - } - } - } - return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; - } - var d3_selection_onFilters = d3.map({ - mouseenter: "mouseover", - mouseleave: "mouseout" - }); - if (d3_document) { - d3_selection_onFilters.forEach(function(k) { - if ("on" + k in d3_document) d3_selection_onFilters.remove(k); - }); - } - function d3_selection_onListener(listener, argumentz) { - return function(e) { - var o = d3.event; - d3.event = e; - argumentz[0] = this.__data__; - try { - listener.apply(this, argumentz); - } finally { - d3.event = o; - } - }; - } - function d3_selection_onFilter(listener, argumentz) { - var l = d3_selection_onListener(listener, argumentz); - return function(e) { - var target = this, related = e.relatedTarget; - if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { - l.call(target, e); - } - }; - } - var d3_event_dragSelect, d3_event_dragId = 0; - function d3_event_dragSuppress(node) { - var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); - if (d3_event_dragSelect == null) { - d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); - } - if (d3_event_dragSelect) { - var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; - style[d3_event_dragSelect] = "none"; - } - return function(suppressClick) { - w.on(name, null); - if (d3_event_dragSelect) style[d3_event_dragSelect] = select; - if (suppressClick) { - var off = function() { - w.on(click, null); - }; - w.on(click, function() { - d3_eventPreventDefault(); - off(); - }, true); - setTimeout(off, 0); - } - }; - } - d3.mouse = function(container) { - return d3_mousePoint(container, d3_eventSource()); - }; - var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; - function d3_mousePoint(container, e) { - if (e.changedTouches) e = e.changedTouches[0]; - var svg = container.ownerSVGElement || container; - if (svg.createSVGPoint) { - var point = svg.createSVGPoint(); - if (d3_mouse_bug44083 < 0) { - var window = d3_window(container); - if (window.scrollX || window.scrollY) { - svg = d3.select("body").append("svg").style({ - position: "absolute", - top: 0, - left: 0, - margin: 0, - padding: 0, - border: "none" - }, "important"); - var ctm = svg[0][0].getScreenCTM(); - d3_mouse_bug44083 = !(ctm.f || ctm.e); - svg.remove(); - } - } - if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, - point.y = e.clientY; - point = point.matrixTransform(container.getScreenCTM().inverse()); - return [ point.x, point.y ]; - } - var rect = container.getBoundingClientRect(); - return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; - } - d3.touch = function(container, touches, identifier) { - if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; - if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { - if ((touch = touches[i]).identifier === identifier) { - return d3_mousePoint(container, touch); - } - } - }; - d3.behavior.drag = function() { - var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); - function drag() { - this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); - } - function dragstart(id, position, subject, move, end) { - return function() { - var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); - if (origin) { - dragOffset = origin.apply(that, arguments); - dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; - } else { - dragOffset = [ 0, 0 ]; - } - dispatch({ - type: "dragstart" - }); - function moved() { - var position1 = position(parent, dragId), dx, dy; - if (!position1) return; - dx = position1[0] - position0[0]; - dy = position1[1] - position0[1]; - dragged |= dx | dy; - position0 = position1; - dispatch({ - type: "drag", - x: position1[0] + dragOffset[0], - y: position1[1] + dragOffset[1], - dx: dx, - dy: dy - }); - } - function ended() { - if (!position(parent, dragId)) return; - dragSubject.on(move + dragName, null).on(end + dragName, null); - dragRestore(dragged && d3.event.target === target); - dispatch({ - type: "dragend" - }); - } - }; - } - drag.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return drag; - }; - return d3.rebind(drag, event, "on"); +},{"uniq":234}],68:[function(require,module,exports){ +"use strict" + +// The function below is called when constructing a cwise function object, and does the following: +// A function object is constructed which accepts as argument a compilation function and returns another function. +// It is this other function that is eventually returned by createThunk, and this function is the one that actually +// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. +// The compilation passed to the first function object is used for compiling new functions. +// Once this function object is created, it is called with compile as argument, where the first argument of compile +// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). +// So createThunk roughly works like this: +// function createThunk(proc) { +// var thunk = function(compileBound) { +// var CACHED = {} +// return function(arrays and scalars) { +// if (dtype and order of arrays in CACHED) { +// var func = CACHED[dtype and order of arrays] +// } else { +// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) +// } +// return func(arrays and scalars) +// } +// } +// return thunk(compile.bind1(proc)) +// } + +var compile = require("./compile.js") + +function createThunk(proc) { + var code = ["'use strict'", "var CACHED={}"] + var vars = [] + var thunkName = proc.funcName + "_cwise_thunk" + + //Build thunk + code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) + var typesig = [] + var string_typesig = [] + var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS). + Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")] + var shapeLengthConditions = [], shapeConditions = [] + // Process array arguments + for(var i=0; i0) { // Gather conditions to check for shape equality (ignoring block indices) + shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i]))) + shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]") + } + } + // Check for shape equality + if (proc.arrayArgs.length > 1) { + code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')") + code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {") + code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") + code.push("}") + } + // Process scalar arguments + for(var i=0; i 0 ? 1 : x < 0 ? -1 : 0; - } - function d3_cross2d(a, b, c) { - return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); - } - function d3_acos(x) { - return x > 1 ? 0 : x < -1 ? π : Math.acos(x); - } - function d3_asin(x) { - return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); - } - function d3_sinh(x) { - return ((x = Math.exp(x)) - 1 / x) / 2; - } - function d3_cosh(x) { - return ((x = Math.exp(x)) + 1 / x) / 2; - } - function d3_tanh(x) { - return ((x = Math.exp(2 * x)) - 1) / (x + 1); + var d3_document = this.document; + function d3_documentElement(node) { + return node && (node.ownerDocument || node.document || node).documentElement; } - function d3_haversin(x) { - return (x = Math.sin(x / 2)) * x; + function d3_window(node) { + return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView); } - var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; - d3.interpolateZoom = function(p0, p1) { - var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2]; - var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ; - function interpolate(t) { - var s = t * S; - if (dr) { - var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); - return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; - } - return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ]; + if (d3_document) { + try { + d3_array(d3_document.documentElement.childNodes)[0].nodeType; + } catch (e) { + d3_array = function(list) { + var i = list.length, array = new Array(i); + while (i--) array[i] = list[i]; + return array; + }; } - interpolate.duration = S * 1e3; - return interpolate; + } + if (!Date.now) Date.now = function() { + return +new Date(); }; - d3.behavior.zoom = function() { - var view = { - x: 0, - y: 0, - k: 1 - }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; - if (!d3_behavior_zoomWheel) { - d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); - }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { - return d3.event.wheelDelta; - }, "mousewheel") : (d3_behavior_zoomDelta = function() { - return -d3.event.detail; - }, "MozMousePixelScroll"); - } - function zoom(g) { - g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); - } - zoom.event = function(g) { - g.each(function() { - var dispatch = event.of(this, arguments), view1 = view; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.zoom", function() { - view = this.__chart__ || { - x: 0, - y: 0, - k: 1 - }; - zoomstarted(dispatch); - }).tween("zoom:zoom", function() { - var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); - return function(t) { - var l = i(t), k = dx / l[2]; - this.__chart__ = view = { - x: cx - l[0] * k, - y: cy - l[1] * k, - k: k - }; - zoomed(dispatch); - }; - }).each("interrupt.zoom", function() { - zoomended(dispatch); - }).each("end.zoom", function() { - zoomended(dispatch); - }); - } else { - this.__chart__ = view; - zoomstarted(dispatch); - zoomed(dispatch); - zoomended(dispatch); - } - }); - }; - zoom.translate = function(_) { - if (!arguments.length) return [ view.x, view.y ]; - view = { - x: +_[0], - y: +_[1], - k: view.k - }; - rescale(); - return zoom; - }; - zoom.scale = function(_) { - if (!arguments.length) return view.k; - view = { - x: view.x, - y: view.y, - k: +_ - }; - rescale(); - return zoom; - }; - zoom.scaleExtent = function(_) { - if (!arguments.length) return scaleExtent; - scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; - return zoom; - }; - zoom.center = function(_) { - if (!arguments.length) return center; - center = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.size = function(_) { - if (!arguments.length) return size; - size = _ && [ +_[0], +_[1] ]; - return zoom; - }; - zoom.duration = function(_) { - if (!arguments.length) return duration; - duration = +_; - return zoom; - }; - zoom.x = function(z) { - if (!arguments.length) return x1; - x1 = z; - x0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 + if (d3_document) { + try { + d3_document.createElement("DIV").style.setProperty("opacity", 0, ""); + } catch (error) { + var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; + d3_element_prototype.setAttribute = function(name, value) { + d3_element_setAttribute.call(this, name, value + ""); }; - return zoom; - }; - zoom.y = function(z) { - if (!arguments.length) return y1; - y1 = z; - y0 = z.copy(); - view = { - x: 0, - y: 0, - k: 1 + d3_element_prototype.setAttributeNS = function(space, local, value) { + d3_element_setAttributeNS.call(this, space, local, value + ""); }; - return zoom; - }; - function location(p) { - return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; - } - function point(l) { - return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; - } - function scaleTo(s) { - view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); - } - function translateTo(p, l) { - l = point(l); - view.x += p[0] - l[0]; - view.y += p[1] - l[1]; - } - function zoomTo(that, p, l, k) { - that.__chart__ = { - x: view.x, - y: view.y, - k: view.k + d3_style_prototype.setProperty = function(name, value, priority) { + d3_style_setProperty.call(this, name, value + "", priority); }; - scaleTo(Math.pow(2, k)); - translateTo(center0 = p, l); - that = d3.select(that); - if (duration > 0) that = that.transition().duration(duration); - that.call(zoom.event); - } - function rescale() { - if (x1) x1.domain(x0.range().map(function(x) { - return (x - view.x) / view.k; - }).map(x0.invert)); - if (y1) y1.domain(y0.range().map(function(y) { - return (y - view.y) / view.k; - }).map(y0.invert)); - } - function zoomstarted(dispatch) { - if (!zooming++) dispatch({ - type: "zoomstart" - }); - } - function zoomed(dispatch) { - rescale(); - dispatch({ - type: "zoom", - scale: view.k, - translate: [ view.x, view.y ] - }); } - function zoomended(dispatch) { - if (!--zooming) dispatch({ - type: "zoomend" - }), center0 = null; + } + d3.ascending = d3_ascending; + function d3_ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + }; + d3.min = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = array[i]) != null && a > b) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; + } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; } - function mousedowned() { - var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); - d3_selection_interrupt.call(that); - zoomstarted(dispatch); - function moved() { - dragged = 1; - translateTo(d3.mouse(that), location0); - zoomed(dispatch); + return a; + }; + d3.max = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = b; + break; } - function ended() { - subject.on(mousemove, null).on(mouseup, null); - dragRestore(dragged && d3.event.target === target); - zoomended(dispatch); + while (++i < n) if ((b = array[i]) != null && b > a) a = b; + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = b; + break; } + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; } - function touchstarted() { - var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); - started(); - zoomstarted(dispatch); - subject.on(mousedown, null).on(touchstart, started); - function relocate() { - var touches = d3.touches(that); - scale0 = view.k; - touches.forEach(function(t) { - if (t.identifier in locations0) locations0[t.identifier] = location(t); - }); - return touches; + return a; + }; + d3.extent = function(array, f) { + var i = -1, n = array.length, a, b, c; + if (arguments.length === 1) { + while (++i < n) if ((b = array[i]) != null && b >= b) { + a = c = b; + break; } - function started() { - var target = d3.event.target; - d3.select(target).on(touchmove, moved).on(touchend, ended); - targets.push(target); - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - locations0[changed[i].identifier] = null; - } - var touches = relocate(), now = Date.now(); - if (touches.length === 1) { - if (now - touchtime < 500) { - var p = touches[0]; - zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); - d3_eventPreventDefault(); - } - touchtime = now; - } else if (touches.length > 1) { - var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; - distance0 = dx * dx + dy * dy; - } + while (++i < n) if ((b = array[i]) != null) { + if (a > b) a = b; + if (c < b) c = b; } - function moved() { - var touches = d3.touches(that), p0, l0, p1, l1; - d3_selection_interrupt.call(that); - for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { - p1 = touches[i]; - if (l1 = locations0[p1.identifier]) { - if (l0) break; - p0 = p1, l0 = l1; - } - } - if (l1) { - var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); - p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; - l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; - scaleTo(scale1 * scale0); - } - touchtime = null; - translateTo(p0, l0); - zoomed(dispatch); + } else { + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) { + a = c = b; + break; } - function ended() { - if (d3.event.touches.length) { - var changed = d3.event.changedTouches; - for (var i = 0, n = changed.length; i < n; ++i) { - delete locations0[changed[i].identifier]; - } - for (var identifier in locations0) { - return void relocate(); - } - } - d3.selectAll(targets).on(zoomName, null); - subject.on(mousedown, mousedowned).on(touchstart, touchstarted); - dragRestore(); - zoomended(dispatch); + while (++i < n) if ((b = f.call(array, array[i], i)) != null) { + if (a > b) a = b; + if (c < b) c = b; } } - function mousewheeled() { - var dispatch = event.of(this, arguments); - if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), - translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); - mousewheelTimer = setTimeout(function() { - mousewheelTimer = null; - zoomended(dispatch); - }, 50); - d3_eventPreventDefault(); - scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); - translateTo(center0, translate0); - zoomed(dispatch); + return [ a, c ]; + }; + function d3_number(x) { + return x === null ? NaN : +x; + } + function d3_numeric(x) { + return !isNaN(x); + } + d3.sum = function(array, f) { + var s = 0, n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = +array[i])) s += a; + } else { + while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a; } - function dblclicked() { - var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; - zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); + return s; + }; + d3.mean = function(array, f) { + var s = 0, n = array.length, a, i = -1, j = n; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j; + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j; } - return d3.rebind(zoom, event, "on"); + if (j) return s / j; }; - var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; - d3.color = d3_color; - function d3_color() {} - d3_color.prototype.toString = function() { - return this.rgb() + ""; + d3.quantile = function(values, p) { + var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; + return e ? v + e * (values[h] - v) : v; }; - d3.hsl = d3_hsl; - function d3_hsl(h, s, l) { - return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); - } - var d3_hslPrototype = d3_hsl.prototype = new d3_color(); - d3_hslPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, this.l / k); + d3.median = function(array, f) { + var numbers = [], n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a); + } else { + while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a); + } + if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5); }; - d3_hslPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_hsl(this.h, this.s, k * this.l); + d3.variance = function(array, f) { + var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0; + if (arguments.length === 1) { + while (++i < n) { + if (d3_numeric(a = d3_number(array[i]))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } else { + while (++i < n) { + if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) { + d = a - m; + m += d / ++j; + s += d * (a - m); + } + } + } + if (j > 1) return s / (j - 1); }; - d3_hslPrototype.rgb = function() { - return d3_hsl_rgb(this.h, this.s, this.l); + d3.deviation = function() { + var v = d3.variance.apply(this, arguments); + return v ? Math.sqrt(v) : v; + }; + function d3_bisector(compare) { + return { + left: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; + } + return lo; + } + }; + } + var d3_bisect = d3_bisector(d3_ascending); + d3.bisectLeft = d3_bisect.left; + d3.bisect = d3.bisectRight = d3_bisect.right; + d3.bisector = function(f) { + return d3_bisector(f.length === 1 ? function(d, x) { + return d3_ascending(f(d), x); + } : f); }; - function d3_hsl_rgb(h, s, l) { - var m1, m2; - h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; - s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; - l = l < 0 ? 0 : l > 1 ? 1 : l; - m2 = l <= .5 ? l * (1 + s) : l + s - l * s; - m1 = 2 * l - m2; - function v(h) { - if (h > 360) h -= 360; else if (h < 0) h += 360; - if (h < 60) return m1 + (m2 - m1) * h / 60; - if (h < 180) return m2; - if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; - return m1; + d3.shuffle = function(array, i0, i1) { + if ((m = arguments.length) < 3) { + i1 = array.length; + if (m < 2) i0 = 0; } - function vv(h) { - return Math.round(v(h) * 255); + var m = i1 - i0, t, i; + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t; } - return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); - } - d3.hcl = d3_hcl; - function d3_hcl(h, c, l) { - return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); - } - var d3_hclPrototype = d3_hcl.prototype = new d3_color(); - d3_hclPrototype.brighter = function(k) { - return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.darker = function(k) { - return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); - }; - d3_hclPrototype.rgb = function() { - return d3_hcl_lab(this.h, this.c, this.l).rgb(); + return array; }; - function d3_hcl_lab(h, c, l) { - if (isNaN(h)) h = 0; - if (isNaN(c)) c = 0; - return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); - } - d3.lab = d3_lab; - function d3_lab(l, a, b) { - return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); - } - var d3_lab_K = 18; - var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; - var d3_labPrototype = d3_lab.prototype = new d3_color(); - d3_labPrototype.brighter = function(k) { - return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + d3.permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; }; - d3_labPrototype.darker = function(k) { - return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + d3.pairs = function(array) { + var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; + return pairs; }; - d3_labPrototype.rgb = function() { - return d3_lab_rgb(this.l, this.a, this.b); + d3.zip = function() { + if (!(n = arguments.length)) return []; + for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { + for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { + zip[j] = arguments[j][i]; + } + } + return zips; }; - function d3_lab_rgb(l, a, b) { - var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; - x = d3_lab_xyz(x) * d3_lab_X; - y = d3_lab_xyz(y) * d3_lab_Y; - z = d3_lab_xyz(z) * d3_lab_Z; - return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); - } - function d3_lab_hcl(l, a, b) { - return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); - } - function d3_lab_xyz(x) { - return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; - } - function d3_xyz_lab(x) { - return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; - } - function d3_xyz_rgb(r) { - return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); - } - d3.rgb = d3_rgb; - function d3_rgb(r, g, b) { - return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); - } - function d3_rgbNumber(value) { - return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); - } - function d3_rgbString(value) { - return d3_rgbNumber(value) + ""; + function d3_zipLength(d) { + return d.length; } - var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); - d3_rgbPrototype.brighter = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - var r = this.r, g = this.g, b = this.b, i = 30; - if (!r && !g && !b) return new d3_rgb(i, i, i); - if (r && r < i) r = i; - if (g && g < i) g = i; - if (b && b < i) b = i; - return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + d3.transpose = function(matrix) { + return d3.zip.apply(d3, matrix); }; - d3_rgbPrototype.darker = function(k) { - k = Math.pow(.7, arguments.length ? k : 1); - return new d3_rgb(k * this.r, k * this.g, k * this.b); + d3.keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; }; - d3_rgbPrototype.hsl = function() { - return d3_rgb_hsl(this.r, this.g, this.b); + d3.values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; }; - d3_rgbPrototype.toString = function() { - return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + d3.entries = function(map) { + var entries = []; + for (var key in map) entries.push({ + key: key, + value: map[key] + }); + return entries; }; - function d3_rgb_hex(v) { - return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); - } - function d3_rgb_parse(format, rgb, hsl) { - format = format.toLowerCase(); - var r = 0, g = 0, b = 0, m1, m2, color; - m1 = /([a-z]+)\((.*)\)/.exec(format); - if (m1) { - m2 = m1[2].split(","); - switch (m1[1]) { - case "hsl": - { - return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); - } - - case "rgb": - { - return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); - } + d3.merge = function(arrays) { + var n = arrays.length, m, i = -1, j = 0, merged, array; + while (++i < n) j += arrays[i].length; + merged = new Array(j); + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; } } - if (color = d3_rgb_names.get(format)) { - return rgb(color.r, color.g, color.b); - } - if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { - if (format.length === 4) { - r = (color & 3840) >> 4; - r = r >> 4 | r; - g = color & 240; - g = g >> 4 | g; - b = color & 15; - b = b << 4 | b; - } else if (format.length === 7) { - r = (color & 16711680) >> 16; - g = (color & 65280) >> 8; - b = color & 255; + return merged; + }; + var abs = Math.abs; + d3.range = function(start, stop, step) { + if (arguments.length < 3) { + step = 1; + if (arguments.length < 2) { + stop = start; + start = 0; } } - return rgb(r, g, b); + if ((stop - start) / step === Infinity) throw new Error("infinite range"); + var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; + start *= k, stop *= k, step *= k; + if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); + return range; + }; + function d3_range_integerScale(x) { + var k = 1; + while (x * k % 1) k *= 10; + return k; } - function d3_rgb_hsl(r, g, b) { - var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; - if (d) { - s = l < .5 ? d / (max + min) : d / (2 - max - min); - if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; - h *= 60; - } else { - h = NaN; - s = l > 0 && l < 1 ? 0 : h; + function d3_class(ctor, properties) { + for (var key in properties) { + Object.defineProperty(ctor.prototype, key, { + value: properties[key], + enumerable: false + }); } - return new d3_hsl(h, s, l); - } - function d3_rgb_lab(r, g, b) { - r = d3_rgb_xyz(r); - g = d3_rgb_xyz(g); - b = d3_rgb_xyz(b); - var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); - return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); - } - function d3_rgb_xyz(r) { - return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); - } - function d3_rgb_parseNumber(c) { - var f = parseFloat(c); - return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; - } - var d3_rgb_names = d3.map({ - aliceblue: 15792383, - antiquewhite: 16444375, - aqua: 65535, - aquamarine: 8388564, - azure: 15794175, - beige: 16119260, - bisque: 16770244, - black: 0, - blanchedalmond: 16772045, - blue: 255, - blueviolet: 9055202, - brown: 10824234, - burlywood: 14596231, - cadetblue: 6266528, - chartreuse: 8388352, - chocolate: 13789470, - coral: 16744272, - cornflowerblue: 6591981, - cornsilk: 16775388, - crimson: 14423100, - cyan: 65535, - darkblue: 139, - darkcyan: 35723, - darkgoldenrod: 12092939, - darkgray: 11119017, - darkgreen: 25600, - darkgrey: 11119017, - darkkhaki: 12433259, - darkmagenta: 9109643, - darkolivegreen: 5597999, - darkorange: 16747520, - darkorchid: 10040012, - darkred: 9109504, - darksalmon: 15308410, - darkseagreen: 9419919, - darkslateblue: 4734347, - darkslategray: 3100495, - darkslategrey: 3100495, - darkturquoise: 52945, - darkviolet: 9699539, - deeppink: 16716947, - deepskyblue: 49151, - dimgray: 6908265, - dimgrey: 6908265, - dodgerblue: 2003199, - firebrick: 11674146, - floralwhite: 16775920, - forestgreen: 2263842, - fuchsia: 16711935, - gainsboro: 14474460, - ghostwhite: 16316671, - gold: 16766720, - goldenrod: 14329120, - gray: 8421504, - green: 32768, - greenyellow: 11403055, - grey: 8421504, - honeydew: 15794160, - hotpink: 16738740, - indianred: 13458524, - indigo: 4915330, - ivory: 16777200, - khaki: 15787660, - lavender: 15132410, - lavenderblush: 16773365, - lawngreen: 8190976, - lemonchiffon: 16775885, - lightblue: 11393254, - lightcoral: 15761536, - lightcyan: 14745599, - lightgoldenrodyellow: 16448210, - lightgray: 13882323, - lightgreen: 9498256, - lightgrey: 13882323, - lightpink: 16758465, - lightsalmon: 16752762, - lightseagreen: 2142890, - lightskyblue: 8900346, - lightslategray: 7833753, - lightslategrey: 7833753, - lightsteelblue: 11584734, - lightyellow: 16777184, - lime: 65280, - limegreen: 3329330, - linen: 16445670, - magenta: 16711935, - maroon: 8388608, - mediumaquamarine: 6737322, - mediumblue: 205, - mediumorchid: 12211667, - mediumpurple: 9662683, - mediumseagreen: 3978097, - mediumslateblue: 8087790, - mediumspringgreen: 64154, - mediumturquoise: 4772300, - mediumvioletred: 13047173, - midnightblue: 1644912, - mintcream: 16121850, - mistyrose: 16770273, - moccasin: 16770229, - navajowhite: 16768685, - navy: 128, - oldlace: 16643558, - olive: 8421376, - olivedrab: 7048739, - orange: 16753920, - orangered: 16729344, - orchid: 14315734, - palegoldenrod: 15657130, - palegreen: 10025880, - paleturquoise: 11529966, - palevioletred: 14381203, - papayawhip: 16773077, - peachpuff: 16767673, - peru: 13468991, - pink: 16761035, - plum: 14524637, - powderblue: 11591910, - purple: 8388736, - rebeccapurple: 6697881, - red: 16711680, - rosybrown: 12357519, - royalblue: 4286945, - saddlebrown: 9127187, - salmon: 16416882, - sandybrown: 16032864, - seagreen: 3050327, - seashell: 16774638, - sienna: 10506797, - silver: 12632256, - skyblue: 8900331, - slateblue: 6970061, - slategray: 7372944, - slategrey: 7372944, - snow: 16775930, - springgreen: 65407, - steelblue: 4620980, - tan: 13808780, - teal: 32896, - thistle: 14204888, - tomato: 16737095, - turquoise: 4251856, - violet: 15631086, - wheat: 16113331, - white: 16777215, - whitesmoke: 16119285, - yellow: 16776960, - yellowgreen: 10145074 - }); - d3_rgb_names.forEach(function(key, value) { - d3_rgb_names.set(key, d3_rgbNumber(value)); - }); - function d3_functor(v) { - return typeof v === "function" ? v : function() { - return v; - }; - } - d3.functor = d3_functor; - d3.xhr = d3_xhrType(d3_identity); - function d3_xhrType(response) { - return function(url, mimeType, callback) { - if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, - mimeType = null; - return d3_xhr(url, mimeType, response, callback); - }; } - function d3_xhr(url, mimeType, response, callback) { - var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; - if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); - "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { - request.readyState > 3 && respond(); - }; - function respond() { - var status = request.status, result; - if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { - try { - result = response.call(xhr, request); - } catch (e) { - dispatch.error.call(xhr, e); - return; - } - dispatch.load.call(xhr, result); - } else { - dispatch.error.call(xhr, request); - } + d3.map = function(object, f) { + var map = new d3_Map(); + if (object instanceof d3_Map) { + object.forEach(function(key, value) { + map.set(key, value); + }); + } else if (Array.isArray(object)) { + var i = -1, n = object.length, o; + if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o); + } else { + for (var key in object) map.set(key, object[key]); } - request.onprogress = function(event) { - var o = d3.event; - d3.event = event; - try { - dispatch.progress.call(xhr, request); - } finally { - d3.event = o; - } - }; - xhr.header = function(name, value) { - name = (name + "").toLowerCase(); - if (arguments.length < 2) return headers[name]; - if (value == null) delete headers[name]; else headers[name] = value + ""; - return xhr; - }; - xhr.mimeType = function(value) { - if (!arguments.length) return mimeType; - mimeType = value == null ? null : value + ""; - return xhr; - }; - xhr.responseType = function(value) { - if (!arguments.length) return responseType; - responseType = value; - return xhr; - }; - xhr.response = function(value) { - response = value; - return xhr; - }; - [ "get", "post" ].forEach(function(method) { - xhr[method] = function() { - return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); - }; - }); - xhr.send = function(method, data, callback) { - if (arguments.length === 2 && typeof data === "function") callback = data, data = null; - request.open(method, url, true); - if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; - if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); - if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); - if (responseType != null) request.responseType = responseType; - if (callback != null) xhr.on("error", callback).on("load", function(request) { - callback(null, request); + return map; + }; + function d3_Map() { + this._ = Object.create(null); + } + var d3_map_proto = "__proto__", d3_map_zero = "\x00"; + d3_class(d3_Map, { + has: d3_map_has, + get: function(key) { + return this._[d3_map_escape(key)]; + }, + set: function(key, value) { + return this._[d3_map_escape(key)] = value; + }, + remove: d3_map_remove, + keys: d3_map_keys, + values: function() { + var values = []; + for (var key in this._) values.push(this._[key]); + return values; + }, + entries: function() { + var entries = []; + for (var key in this._) entries.push({ + key: d3_map_unescape(key), + value: this._[key] }); - dispatch.beforesend.call(xhr, request); - request.send(data == null ? null : data); - return xhr; - }; - xhr.abort = function() { - request.abort(); - return xhr; - }; - d3.rebind(xhr, dispatch, "on"); - return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); + return entries; + }, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]); + } + }); + function d3_map_escape(key) { + return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key; } - function d3_xhr_fixCallback(callback) { - return callback.length === 1 ? function(error, request) { - callback(error == null ? request : null); - } : callback; + function d3_map_unescape(key) { + return (key += "")[0] === d3_map_zero ? key.slice(1) : key; } - function d3_xhrHasResponse(request) { - var type = request.responseType; - return type && type !== "text" ? request.response : request.responseText; + function d3_map_has(key) { + return d3_map_escape(key) in this._; } - d3.dsv = function(delimiter, mimeType) { - var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); - function dsv(url, row, callback) { - if (arguments.length < 3) callback = row, row = null; - var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); - xhr.row = function(_) { - return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; - }; - return xhr; - } - function response(request) { - return dsv.parse(request.responseText); - } - function typedResponse(f) { - return function(request) { - return dsv.parse(request.responseText, f); - }; - } - dsv.parse = function(text, f) { - var o; - return dsv.parseRows(text, function(row, i) { - if (o) return o(row, i - 1); - var a = new Function("d", "return {" + row.map(function(name, i) { - return JSON.stringify(name) + ": d[" + i + "]"; - }).join(",") + "}"); - o = f ? function(row, i) { - return f(a(row), i); - } : a; - }); - }; - dsv.parseRows = function(text, f) { - var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; - function token() { - if (I >= N) return EOF; - if (eol) return eol = false, EOL; - var j = I; - if (text.charCodeAt(j) === 34) { - var i = j; - while (i++ < N) { - if (text.charCodeAt(i) === 34) { - if (text.charCodeAt(i + 1) !== 34) break; - ++i; - } - } - I = i + 2; - var c = text.charCodeAt(i + 1); - if (c === 13) { - eol = true; - if (text.charCodeAt(i + 2) === 10) ++I; - } else if (c === 10) { - eol = true; - } - return text.slice(j + 1, i).replace(/""/g, '"'); - } - while (I < N) { - var c = text.charCodeAt(I++), k = 1; - if (c === 10) eol = true; else if (c === 13) { - eol = true; - if (text.charCodeAt(I) === 10) ++I, ++k; - } else if (c !== delimiterCode) continue; - return text.slice(j, I - k); + function d3_map_remove(key) { + return (key = d3_map_escape(key)) in this._ && delete this._[key]; + } + function d3_map_keys() { + var keys = []; + for (var key in this._) keys.push(d3_map_unescape(key)); + return keys; + } + function d3_map_size() { + var size = 0; + for (var key in this._) ++size; + return size; + } + function d3_map_empty() { + for (var key in this._) return false; + return true; + } + d3.nest = function() { + var nest = {}, keys = [], sortKeys = [], sortValues, rollup; + function map(mapType, array, depth) { + if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; + var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(object = array[i]))) { + values.push(object); + } else { + valuesByKey.set(keyValue, [ object ]); } - return text.slice(j); } - while ((t = token()) !== EOF) { - var a = []; - while (t !== EOL && t !== EOF) { - a.push(t); - t = token(); - } - if (f && (a = f(a, n++)) == null) continue; - rows.push(a); + if (mapType) { + object = mapType(); + setter = function(keyValue, values) { + object.set(keyValue, map(mapType, values, depth)); + }; + } else { + object = {}; + setter = function(keyValue, values) { + object[keyValue] = map(mapType, values, depth); + }; } - return rows; - }; - dsv.format = function(rows) { - if (Array.isArray(rows[0])) return dsv.formatRows(rows); - var fieldSet = new d3_Set(), fields = []; - rows.forEach(function(row) { - for (var field in row) { - if (!fieldSet.has(field)) { - fields.push(fieldSet.add(field)); - } - } + valuesByKey.forEach(setter); + return object; + } + function entries(map, depth) { + if (depth >= keys.length) return map; + var array = [], sortKey = sortKeys[depth++]; + map.forEach(function(key, keyMap) { + array.push({ + key: key, + values: entries(keyMap, depth) + }); }); - return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { - return fields.map(function(field) { - return formatValue(row[field]); - }).join(delimiter); - })).join("\n"); + return sortKey ? array.sort(function(a, b) { + return sortKey(a.key, b.key); + }) : array; + } + nest.map = function(array, mapType) { + return map(mapType, array, 0); }; - dsv.formatRows = function(rows) { - return rows.map(formatRow).join("\n"); + nest.entries = function(array) { + return entries(map(d3.map, array, 0), 0); }; - function formatRow(row) { - return row.map(formatValue).join(delimiter); - } - function formatValue(text) { - return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; - } - return dsv; + nest.key = function(d) { + keys.push(d); + return nest; + }; + nest.sortKeys = function(order) { + sortKeys[keys.length - 1] = order; + return nest; + }; + nest.sortValues = function(order) { + sortValues = order; + return nest; + }; + nest.rollup = function(f) { + rollup = f; + return nest; + }; + return nest; }; - d3.csv = d3.dsv(",", "text/csv"); - d3.tsv = d3.dsv(" ", "text/tab-separated-values"); - var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { - setTimeout(callback, 17); + d3.set = function(array) { + var set = new d3_Set(); + if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); + return set; }; - d3.timer = function(callback, delay, then) { - var n = arguments.length; - if (n < 2) delay = 0; - if (n < 3) then = Date.now(); - var time = then + delay, timer = { - c: callback, - t: time, - f: false, - n: null - }; - if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; - d3_timer_queueTail = timer; - if (!d3_timer_interval) { - d3_timer_timeout = clearTimeout(d3_timer_timeout); - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); + function d3_Set() { + this._ = Object.create(null); + } + d3_class(d3_Set, { + has: d3_map_has, + add: function(key) { + this._[d3_map_escape(key += "")] = true; + return key; + }, + remove: d3_map_remove, + values: d3_map_keys, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this._) f.call(this, d3_map_unescape(key)); } + }); + d3.behavior = {}; + function d3_identity(d) { + return d; + } + d3.rebind = function(target, source) { + var i = 1, n = arguments.length, method; + while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); + return target; }; - function d3_timer_step() { - var now = d3_timer_mark(), delay = d3_timer_sweep() - now; - if (delay > 24) { - if (isFinite(delay)) { - clearTimeout(d3_timer_timeout); - d3_timer_timeout = setTimeout(d3_timer_step, delay); - } - d3_timer_interval = 0; - } else { - d3_timer_interval = 1; - d3_timer_frame(d3_timer_step); + function d3_rebind(target, source, method) { + return function() { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; + } + function d3_vendorSymbol(object, name) { + if (name in object) return name; + name = name.charAt(0).toUpperCase() + name.slice(1); + for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { + var prefixName = d3_vendorPrefixes[i] + name; + if (prefixName in object) return prefixName; } } - d3.timer.flush = function() { - d3_timer_mark(); - d3_timer_sweep(); + var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; + function d3_noop() {} + d3.dispatch = function() { + var dispatch = new d3_dispatch(), i = -1, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + return dispatch; }; - function d3_timer_mark() { - var now = Date.now(); - d3_timer_active = d3_timer_queueHead; - while (d3_timer_active) { - if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t); - d3_timer_active = d3_timer_active.n; + function d3_dispatch() {} + d3_dispatch.prototype.on = function(type, listener) { + var i = type.indexOf("."), name = ""; + if (i >= 0) { + name = type.slice(i + 1); + type = type.slice(0, i); } - return now; - } - function d3_timer_sweep() { - var t0, t1 = d3_timer_queueHead, time = Infinity; - while (t1) { - if (t1.f) { - t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; - } else { - if (t1.t < time) time = t1.t; - t1 = (t0 = t1).n; + if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); + if (arguments.length === 2) { + if (listener == null) for (type in this) { + if (this.hasOwnProperty(type)) this[type].on(name, null); } + return this; } - d3_timer_queueTail = t0; - return time; - } - function d3_format_precision(x, p) { - return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); - } - d3.round = function(x, n) { - return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); }; - var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); - d3.formatPrefix = function(value, precision) { - var i = 0; - if (value) { - if (value < 0) value *= -1; - if (precision) value = d3.round(value, d3_format_precision(value, precision)); - i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); - i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); + function d3_dispatch_event(dispatch) { + var listeners = [], listenerByName = new d3_Map(); + function event() { + var z = listeners, i = -1, n = z.length, l; + while (++i < n) if (l = z[i].on) l.apply(this, arguments); + return dispatch; } - return d3_formatPrefixes[8 + i / 3]; - }; - function d3_formatPrefix(d, i) { - var k = Math.pow(10, abs(8 - i) * 3); - return { - scale: i > 8 ? function(d) { - return d / k; - } : function(d) { - return d * k; - }, - symbol: d + event.on = function(name, listener) { + var l = listenerByName.get(name), i; + if (arguments.length < 2) return l && l.on; + if (l) { + l.on = null; + listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); + listenerByName.remove(name); + } + if (listener) listeners.push(listenerByName.set(name, { + on: listener + })); + return dispatch; }; + return event; } - function d3_locale_numberFormat(locale) { - var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { - var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; - while (i > 0 && g > 0) { - if (length + g + 1 > width) g = Math.max(1, width - length); - t.push(value.substring(i -= g, i + g)); - if ((length += g + 1) > width) break; - g = locale_grouping[j = (j + 1) % locale_grouping.length]; - } - return t.reverse().join(locale_thousands); - } : d3_identity; - return function(specifier) { - var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; - if (precision) precision = +precision.substring(1); - if (zfill || fill === "0" && align === "=") { - zfill = fill = "0"; - align = "="; - } - switch (type) { - case "n": - comma = true; - type = "g"; - break; - - case "%": - scale = 100; - suffix = "%"; - type = "f"; - break; - - case "p": - scale = 100; - suffix = "%"; - type = "r"; - break; - - case "b": - case "o": - case "x": - case "X": - if (symbol === "#") prefix = "0" + type.toLowerCase(); - - case "c": - exponent = false; - - case "d": - integer = true; - precision = 0; - break; - - case "s": - scale = -1; - type = "r"; - break; - } - if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; - if (type == "r" && !precision) type = "g"; - if (precision != null) { - if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); - } - type = d3_format_types.get(type) || d3_format_typeDefault; - var zcomma = zfill && comma; - return function(value) { - var fullSuffix = suffix; - if (integer && value % 1) return ""; - var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; - if (scale < 0) { - var unit = d3.formatPrefix(value, precision); - value = unit.scale(value); - fullSuffix = unit.symbol + suffix; - } else { - value *= scale; - } - value = type(value, precision); - var i = value.lastIndexOf("."), before, after; - if (i < 0) { - var j = exponent ? value.lastIndexOf("e") : -1; - if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); - } else { - before = value.substring(0, i); - after = locale_decimal + value.substring(i + 1); + d3.event = null; + function d3_eventPreventDefault() { + d3.event.preventDefault(); + } + function d3_eventSource() { + var e = d3.event, s; + while (s = e.sourceEvent) e = s; + return e; + } + function d3_eventDispatch(target) { + var dispatch = new d3_dispatch(), i = 0, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + dispatch.of = function(thiz, argumentz) { + return function(e1) { + try { + var e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; } - if (!zfill && comma) before = formatGroup(before, Infinity); - var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; - if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); - negative += prefix; - value = before + after; - return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; }; }; + return dispatch; } - var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; - var d3_format_types = d3.map({ - b: function(x) { - return x.toString(2); - }, - c: function(x) { - return String.fromCharCode(x); - }, - o: function(x) { - return x.toString(8); - }, - x: function(x) { - return x.toString(16); - }, - X: function(x) { - return x.toString(16).toUpperCase(); - }, - g: function(x, p) { - return x.toPrecision(p); - }, - e: function(x, p) { - return x.toExponential(p); - }, - f: function(x, p) { - return x.toFixed(p); - }, - r: function(x, p) { - return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); + d3.requote = function(s) { + return s.replace(d3_requote_re, "\\$&"); + }; + var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + var d3_subclass = {}.__proto__ ? function(object, prototype) { + object.__proto__ = prototype; + } : function(object, prototype) { + for (var property in prototype) object[property] = prototype[property]; + }; + function d3_selection(groups) { + d3_subclass(groups, d3_selectionPrototype); + return groups; + } + var d3_select = function(s, n) { + return n.querySelector(s); + }, d3_selectAll = function(s, n) { + return n.querySelectorAll(s); + }, d3_selectMatches = function(n, s) { + var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")]; + d3_selectMatches = function(n, s) { + return d3_selectMatcher.call(n, s); + }; + return d3_selectMatches(n, s); + }; + if (typeof Sizzle === "function") { + d3_select = function(s, n) { + return Sizzle(s, n)[0] || null; + }; + d3_selectAll = Sizzle; + d3_selectMatches = Sizzle.matchesSelector; + } + d3.selection = function() { + return d3.select(d3_document.documentElement); + }; + var d3_selectionPrototype = d3.selection.prototype = []; + d3_selectionPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, group, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(subnode = selector.call(node, node.__data__, i, j)); + if (subnode && "__data__" in node) subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } } - }); - function d3_format_typeDefault(x) { - return x + ""; + return d3_selection(subgroups); + }; + function d3_selection_selector(selector) { + return typeof selector === "function" ? selector : function() { + return d3_select(selector, this); + }; } - var d3_time = d3.time = {}, d3_date = Date; - function d3_date_utc() { - this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); + d3_selectionPrototype.selectAll = function(selector) { + var subgroups = [], subgroup, node; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); + subgroup.parentNode = node; + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selectorAll(selector) { + return typeof selector === "function" ? selector : function() { + return d3_selectAll(selector, this); + }; } - d3_date_utc.prototype = { - getDate: function() { - return this._.getUTCDate(); - }, - getDay: function() { - return this._.getUTCDay(); - }, - getFullYear: function() { - return this._.getUTCFullYear(); - }, - getHours: function() { - return this._.getUTCHours(); - }, - getMilliseconds: function() { - return this._.getUTCMilliseconds(); - }, - getMinutes: function() { - return this._.getUTCMinutes(); - }, - getMonth: function() { - return this._.getUTCMonth(); - }, - getSeconds: function() { - return this._.getUTCSeconds(); - }, - getTime: function() { - return this._.getTime(); - }, - getTimezoneOffset: function() { - return 0; - }, - valueOf: function() { - return this._.valueOf(); - }, - setDate: function() { - d3_time_prototype.setUTCDate.apply(this._, arguments); - }, - setDay: function() { - d3_time_prototype.setUTCDay.apply(this._, arguments); - }, - setFullYear: function() { - d3_time_prototype.setUTCFullYear.apply(this._, arguments); - }, - setHours: function() { - d3_time_prototype.setUTCHours.apply(this._, arguments); - }, - setMilliseconds: function() { - d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); - }, - setMinutes: function() { - d3_time_prototype.setUTCMinutes.apply(this._, arguments); - }, - setMonth: function() { - d3_time_prototype.setUTCMonth.apply(this._, arguments); - }, - setSeconds: function() { - d3_time_prototype.setUTCSeconds.apply(this._, arguments); - }, - setTime: function() { - d3_time_prototype.setTime.apply(this._, arguments); + var d3_nsPrefix = { + svg: "http://www.w3.org/2000/svg", + xhtml: "http://www.w3.org/1999/xhtml", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: d3_nsPrefix, + qualify: function(name) { + var i = name.indexOf(":"), prefix = name; + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return d3_nsPrefix.hasOwnProperty(prefix) ? { + space: d3_nsPrefix[prefix], + local: name + } : name; } }; - var d3_time_prototype = Date.prototype; - function d3_time_interval(local, step, number) { - function round(date) { - var d0 = local(date), d1 = offset(d0, 1); - return date - d0 < d1 - date ? d0 : d1; + d3_selectionPrototype.attr = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(); + name = d3.ns.qualify(name); + return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); + } + for (value in name) this.each(d3_selection_attr(value, name[value])); + return this; } - function ceil(date) { - step(date = local(new d3_date(date - 1)), 1); - return date; + return this.each(d3_selection_attr(name, value)); + }; + function d3_selection_attr(name, value) { + name = d3.ns.qualify(name); + function attrNull() { + this.removeAttribute(name); } - function offset(date, k) { - step(date = new d3_date(+date), k); - return date; + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); } - function range(t0, t1, dt) { - var time = ceil(t0), times = []; - if (dt > 1) { - while (time < t1) { - if (!(number(time) % dt)) times.push(new Date(+time)); - step(time, 1); + function attrConstant() { + this.setAttribute(name, value); + } + function attrConstantNS() { + this.setAttributeNS(name.space, name.local, value); + } + function attrFunction() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); + } + function attrFunctionNS() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); + } + return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; + } + function d3_collapse(s) { + return s.trim().replace(/\s+/g, " "); + } + d3_selectionPrototype.classed = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; + if (value = node.classList) { + while (++i < n) if (!value.contains(name[i])) return false; + } else { + value = node.getAttribute("class"); + while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; } - } else { - while (time < t1) times.push(new Date(+time)), step(time, 1); + return true; } - return times; + for (value in name) this.each(d3_selection_classed(value, name[value])); + return this; } - function range_utc(t0, t1, dt) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = t0; - return range(utc, t1, dt); - } finally { - d3_date = Date; - } + return this.each(d3_selection_classed(name, value)); + }; + function d3_selection_classedRe(name) { + return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); + } + function d3_selection_classes(name) { + return (name + "").trim().split(/^|\s+/); + } + function d3_selection_classed(name, value) { + name = d3_selection_classes(name).map(d3_selection_classedName); + var n = name.length; + function classedConstant() { + var i = -1; + while (++i < n) name[i](this, value); } - local.floor = local; - local.round = round; - local.ceil = ceil; - local.offset = offset; - local.range = range; - var utc = local.utc = d3_time_interval_utc(local); - utc.floor = utc; - utc.round = d3_time_interval_utc(round); - utc.ceil = d3_time_interval_utc(ceil); - utc.offset = d3_time_interval_utc(offset); - utc.range = range_utc; - return local; + function classedFunction() { + var i = -1, x = value.apply(this, arguments); + while (++i < n) name[i](this, x); + } + return typeof value === "function" ? classedFunction : classedConstant; } - function d3_time_interval_utc(method) { - return function(date, k) { - try { - d3_date = d3_date_utc; - var utc = new d3_date_utc(); - utc._ = date; - return method(utc, k)._; - } finally { - d3_date = Date; + function d3_selection_classedName(name) { + var re = d3_selection_classedRe(name); + return function(node, value) { + if (c = node.classList) return value ? c.add(name) : c.remove(name); + var c = node.getAttribute("class") || ""; + if (value) { + re.lastIndex = 0; + if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); + } else { + node.setAttribute("class", d3_collapse(c.replace(re, " "))); } }; } - d3_time.year = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setMonth(0, 1); - return date; - }, function(date, offset) { - date.setFullYear(date.getFullYear() + offset); - }, function(date) { - return date.getFullYear(); - }); - d3_time.years = d3_time.year.range; - d3_time.years.utc = d3_time.year.utc.range; - d3_time.day = d3_time_interval(function(date) { - var day = new d3_date(2e3, 0); - day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); - return day; - }, function(date, offset) { - date.setDate(date.getDate() + offset); - }, function(date) { - return date.getDate() - 1; - }); - d3_time.days = d3_time.day.range; - d3_time.days.utc = d3_time.day.utc.range; - d3_time.dayOfYear = function(date) { - var year = d3_time.year(date); - return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); + d3_selectionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); + return this; + } + if (n < 2) { + var node = this.node(); + return d3_window(node).getComputedStyle(node, null).getPropertyValue(name); + } + priority = ""; + } + return this.each(d3_selection_style(name, value, priority)); }; - [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { - i = 7 - i; - var interval = d3_time[day] = d3_time_interval(function(date) { - (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); - return date; - }, function(date, offset) { - date.setDate(date.getDate() + Math.floor(offset) * 7); - }, function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); + function d3_selection_style(name, value, priority) { + function styleNull() { + this.style.removeProperty(name); + } + function styleConstant() { + this.style.setProperty(name, value, priority); + } + function styleFunction() { + var x = value.apply(this, arguments); + if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); + } + return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; + } + d3_selectionPrototype.property = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") return this.node()[name]; + for (value in name) this.each(d3_selection_property(value, name[value])); + return this; + } + return this.each(d3_selection_property(name, value)); + }; + function d3_selection_property(name, value) { + function propertyNull() { + delete this[name]; + } + function propertyConstant() { + this[name] = value; + } + function propertyFunction() { + var x = value.apply(this, arguments); + if (x == null) delete this[name]; else this[name] = x; + } + return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; + } + d3_selectionPrototype.text = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + } : value == null ? function() { + this.textContent = ""; + } : function() { + this.textContent = value; + }) : this.node().textContent; + }; + d3_selectionPrototype.html = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + } : value == null ? function() { + this.innerHTML = ""; + } : function() { + this.innerHTML = value; + }) : this.node().innerHTML; + }; + d3_selectionPrototype.append = function(name) { + name = d3_selection_creator(name); + return this.select(function() { + return this.appendChild(name.apply(this, arguments)); }); - d3_time[day + "s"] = interval.range; - d3_time[day + "s"].utc = interval.utc.range; - d3_time[day + "OfYear"] = function(date) { - var day = d3_time.year(date).getDay(); - return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); - }; - }); - d3_time.week = d3_time.sunday; - d3_time.weeks = d3_time.sunday.range; - d3_time.weeks.utc = d3_time.sunday.utc.range; - d3_time.weekOfYear = d3_time.sundayOfYear; - function d3_locale_timeFormat(locale) { - var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; - function d3_time_format(template) { - var n = template.length; - function format(date) { - var string = [], i = -1, j = 0, c, p, f; - while (++i < n) { - if (template.charCodeAt(i) === 37) { - string.push(template.slice(j, i)); - if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); - if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); - string.push(c); - j = i + 1; + }; + function d3_selection_creator(name) { + function create() { + var document = this.ownerDocument, namespace = this.namespaceURI; + return namespace ? document.createElementNS(namespace, name) : document.createElement(name); + } + function createNS() { + return this.ownerDocument.createElementNS(name.space, name.local); + } + return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create; + } + d3_selectionPrototype.insert = function(name, before) { + name = d3_selection_creator(name); + before = d3_selection_selector(before); + return this.select(function() { + return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); + }); + }; + d3_selectionPrototype.remove = function() { + return this.each(d3_selectionRemove); + }; + function d3_selectionRemove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + } + d3_selectionPrototype.data = function(value, key) { + var i = -1, n = this.length, group, node; + if (!arguments.length) { + value = new Array(n = (group = this[0]).length); + while (++i < n) { + if (node = group[i]) { + value[i] = node.__data__; + } + } + return value; + } + function bind(group, groupData) { + var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; + if (key) { + var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue; + for (i = -1; ++i < n; ) { + if (node = group[i]) { + if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) { + exitNodes[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + keyValues[i] = keyValue; } } - string.push(template.slice(j, i)); - return string.join(""); + for (i = -1; ++i < m; ) { + if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) { + enterNodes[i] = d3_selection_dataNode(nodeData); + } else if (node !== true) { + updateNodes[i] = node; + node.__data__ = nodeData; + } + nodeByKeyValue.set(keyValue, true); + } + for (i = -1; ++i < n; ) { + if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) { + exitNodes[i] = group[i]; + } + } + } else { + for (i = -1; ++i < n0; ) { + node = group[i]; + nodeData = groupData[i]; + if (node) { + node.__data__ = nodeData; + updateNodes[i] = node; + } else { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + } + for (;i < m; ++i) { + enterNodes[i] = d3_selection_dataNode(groupData[i]); + } + for (;i < n; ++i) { + exitNodes[i] = group[i]; + } } - format.parse = function(string) { - var d = { - y: 1900, - m: 0, - d: 1, - H: 0, - M: 0, - S: 0, - L: 0, - Z: null - }, i = d3_time_parse(d, template, string, 0); - if (i != string.length) return null; - if ("p" in d) d.H = d.H % 12 + d.p * 12; - var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); - if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) { - date.setFullYear(d.y, 0, 1); - date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); - } else date.setFullYear(d.y, d.m, d.d); - date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); - return localZ ? date._ : date; - }; - format.toString = function() { - return template; - }; - return format; + enterNodes.update = updateNodes; + enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; + enter.push(enterNodes); + update.push(updateNodes); + exit.push(exitNodes); } - function d3_time_parse(date, template, string, j) { - var c, p, t, i = 0, n = template.length, m = string.length; - while (i < n) { - if (j >= m) return -1; - c = template.charCodeAt(i++); - if (c === 37) { - t = template.charAt(i++); - p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; - if (!p || (j = p(date, string, j)) < 0) return -1; - } else if (c != string.charCodeAt(j++)) { - return -1; + var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); + if (typeof value === "function") { + while (++i < n) { + bind(group = this[i], value.call(group, group.parentNode.__data__, i)); + } + } else { + while (++i < n) { + bind(group = this[i], value); + } + } + update.enter = function() { + return enter; + }; + update.exit = function() { + return exit; + }; + return update; + }; + function d3_selection_dataNode(data) { + return { + __data__: data + }; + } + d3_selectionPrototype.datum = function(value) { + return arguments.length ? this.property("__data__", value) : this.property("__data__"); + }; + d3_selectionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); } } - return j; } - d3_time_format.utc = function(template) { - var local = d3_time_format(template); - function format(date) { - try { - d3_date = d3_date_utc; - var utc = new d3_date(); - utc._ = date; - return local(utc); - } finally { - d3_date = Date; + return d3_selection(subgroups); + }; + function d3_selection_filter(selector) { + return function() { + return d3_selectMatches(this, selector); + }; + } + d3_selectionPrototype.order = function() { + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; } } - format.parse = function(string) { - try { - d3_date = d3_date_utc; - var date = local.parse(string); - return date && date._; - } finally { - d3_date = Date; - } - }; - format.toString = local.toString; - return format; + } + return this; + }; + d3_selectionPrototype.sort = function(comparator) { + comparator = d3_selection_sortComparator.apply(this, arguments); + for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); + return this.order(); + }; + function d3_selection_sortComparator(comparator) { + if (!arguments.length) comparator = d3_ascending; + return function(a, b) { + return a && b ? comparator(a.__data__, b.__data__) : !a - !b; }; - d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; - var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); - locale_periods.forEach(function(p, i) { - d3_time_periodLookup.set(p.toLowerCase(), i); + } + d3_selectionPrototype.each = function(callback) { + return d3_selection_each(this, function(node, i, j) { + callback.call(node, node.__data__, i, j); }); - var d3_time_formats = { - a: function(d) { - return locale_shortDays[d.getDay()]; - }, - A: function(d) { - return locale_days[d.getDay()]; - }, - b: function(d) { - return locale_shortMonths[d.getMonth()]; - }, - B: function(d) { - return locale_months[d.getMonth()]; - }, - c: d3_time_format(locale_dateTime), - d: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - e: function(d, p) { - return d3_time_formatPad(d.getDate(), p, 2); - }, - H: function(d, p) { - return d3_time_formatPad(d.getHours(), p, 2); - }, - I: function(d, p) { - return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); - }, - j: function(d, p) { - return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); - }, - L: function(d, p) { - return d3_time_formatPad(d.getMilliseconds(), p, 3); - }, - m: function(d, p) { - return d3_time_formatPad(d.getMonth() + 1, p, 2); - }, - M: function(d, p) { - return d3_time_formatPad(d.getMinutes(), p, 2); - }, - p: function(d) { - return locale_periods[+(d.getHours() >= 12)]; - }, - S: function(d, p) { - return d3_time_formatPad(d.getSeconds(), p, 2); - }, - U: function(d, p) { - return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); - }, - w: function(d) { - return d.getDay(); - }, - W: function(d, p) { - return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); - }, - x: d3_time_format(locale_date), - X: d3_time_format(locale_time), - y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 100, p, 2); - }, - Y: function(d, p) { - return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); - }, - Z: d3_time_zone, - "%": function() { - return "%"; + }; + function d3_selection_each(groups, callback) { + for (var j = 0, m = groups.length; j < m; j++) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { + if (node = group[i]) callback(node, i, j); } - }; - var d3_time_parsers = { - a: d3_time_parseWeekdayAbbrev, - A: d3_time_parseWeekday, - b: d3_time_parseMonthAbbrev, - B: d3_time_parseMonth, - c: d3_time_parseLocaleFull, - d: d3_time_parseDay, - e: d3_time_parseDay, - H: d3_time_parseHour24, - I: d3_time_parseHour24, - j: d3_time_parseDayOfYear, - L: d3_time_parseMilliseconds, - m: d3_time_parseMonthNumber, - M: d3_time_parseMinutes, - p: d3_time_parseAmPm, - S: d3_time_parseSeconds, - U: d3_time_parseWeekNumberSunday, - w: d3_time_parseWeekdayNumber, - W: d3_time_parseWeekNumberMonday, - x: d3_time_parseLocaleDate, - X: d3_time_parseLocaleTime, - y: d3_time_parseYear, - Y: d3_time_parseFullYear, - Z: d3_time_parseZone, - "%": d3_time_parseLiteralPercent - }; - function d3_time_parseWeekdayAbbrev(date, string, i) { - d3_time_dayAbbrevRe.lastIndex = 0; - var n = d3_time_dayAbbrevRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; } - function d3_time_parseWeekday(date, string, i) { - d3_time_dayRe.lastIndex = 0; - var n = d3_time_dayRe.exec(string.slice(i)); - return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + return groups; + } + d3_selectionPrototype.call = function(callback) { + var args = d3_array(arguments); + callback.apply(args[0] = this, args); + return this; + }; + d3_selectionPrototype.empty = function() { + return !this.node(); + }; + d3_selectionPrototype.node = function() { + for (var j = 0, m = this.length; j < m; j++) { + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + var node = group[i]; + if (node) return node; + } } - function d3_time_parseMonthAbbrev(date, string, i) { - d3_time_monthAbbrevRe.lastIndex = 0; - var n = d3_time_monthAbbrevRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + return null; + }; + d3_selectionPrototype.size = function() { + var n = 0; + d3_selection_each(this, function() { + ++n; + }); + return n; + }; + function d3_selection_enter(selection) { + d3_subclass(selection, d3_selection_enterPrototype); + return selection; + } + var d3_selection_enterPrototype = []; + d3.selection.enter = d3_selection_enter; + d3.selection.enter.prototype = d3_selection_enterPrototype; + d3_selection_enterPrototype.append = d3_selectionPrototype.append; + d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; + d3_selection_enterPrototype.node = d3_selectionPrototype.node; + d3_selection_enterPrototype.call = d3_selectionPrototype.call; + d3_selection_enterPrototype.size = d3_selectionPrototype.size; + d3_selection_enterPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, upgroup, group, node; + for (var j = -1, m = this.length; ++j < m; ) { + upgroup = (group = this[j]).update; + subgroups.push(subgroup = []); + subgroup.parentNode = group.parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); + subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } } - function d3_time_parseMonth(date, string, i) { - d3_time_monthRe.lastIndex = 0; - var n = d3_time_monthRe.exec(string.slice(i)); - return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + return d3_selection(subgroups); + }; + d3_selection_enterPrototype.insert = function(name, before) { + if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); + return d3_selectionPrototype.insert.call(this, name, before); + }; + function d3_selection_enterInsertBefore(enter) { + var i0, j0; + return function(d, i, j) { + var group = enter[j].update, n = group.length, node; + if (j != j0) j0 = j, i0 = 0; + if (i >= i0) i0 = i + 1; + while (!(node = group[i0]) && ++i0 < n) ; + return node; + }; + } + d3.select = function(node) { + var group; + if (typeof node === "string") { + group = [ d3_select(node, d3_document) ]; + group.parentNode = d3_document.documentElement; + } else { + group = [ node ]; + group.parentNode = d3_documentElement(node); } - function d3_time_parseLocaleFull(date, string, i) { - return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + return d3_selection([ group ]); + }; + d3.selectAll = function(nodes) { + var group; + if (typeof nodes === "string") { + group = d3_array(d3_selectAll(nodes, d3_document)); + group.parentNode = d3_document.documentElement; + } else { + group = d3_array(nodes); + group.parentNode = null; } - function d3_time_parseLocaleDate(date, string, i) { - return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + return d3_selection([ group ]); + }; + d3_selectionPrototype.on = function(type, listener, capture) { + var n = arguments.length; + if (n < 3) { + if (typeof type !== "string") { + if (n < 2) listener = false; + for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); + return this; + } + if (n < 2) return (n = this.node()["__on" + type]) && n._; + capture = false; } - function d3_time_parseLocaleTime(date, string, i) { - return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + return this.each(d3_selection_on(type, listener, capture)); + }; + function d3_selection_on(type, listener, capture) { + var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; + if (i > 0) type = type.slice(0, i); + var filter = d3_selection_onFilters.get(type); + if (filter) type = filter, wrap = d3_selection_onFilter; + function onRemove() { + var l = this[name]; + if (l) { + this.removeEventListener(type, l, l.$); + delete this[name]; + } } - function d3_time_parseAmPm(date, string, i) { - var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); - return n == null ? -1 : (date.p = n, i); + function onAdd() { + var l = wrap(listener, d3_array(arguments)); + onRemove.call(this); + this.addEventListener(type, this[name] = l, l.$ = capture); + l._ = listener; } - return d3_time_format; - } - var d3_time_formatPads = { - "-": "", - _: " ", - "0": "0" - }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; - function d3_time_formatPad(value, fill, width) { - var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; - return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); - } - function d3_time_formatRe(names) { - return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); - } - function d3_time_formatLookup(names) { - var map = new d3_Map(), i = -1, n = names.length; - while (++i < n) map.set(names[i].toLowerCase(), i); - return map; - } - function d3_time_parseWeekdayNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 1)); - return n ? (date.w = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberSunday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.U = +n[0], i + n[0].length) : -1; - } - function d3_time_parseWeekNumberMonday(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i)); - return n ? (date.W = +n[0], i + n[0].length) : -1; - } - function d3_time_parseFullYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 4)); - return n ? (date.y = +n[0], i + n[0].length) : -1; - } - function d3_time_parseYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; - } - function d3_time_parseZone(date, string, i) { - return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, - i + 5) : -1; - } - function d3_time_expandYear(d) { - return d + (d > 68 ? 1900 : 2e3); - } - function d3_time_parseMonthNumber(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.m = n[0] - 1, i + n[0].length) : -1; - } - function d3_time_parseDay(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.d = +n[0], i + n[0].length) : -1; - } - function d3_time_parseDayOfYear(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.j = +n[0], i + n[0].length) : -1; - } - function d3_time_parseHour24(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.H = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMinutes(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.M = +n[0], i + n[0].length) : -1; - } - function d3_time_parseSeconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 2)); - return n ? (date.S = +n[0], i + n[0].length) : -1; - } - function d3_time_parseMilliseconds(date, string, i) { - d3_time_numberRe.lastIndex = 0; - var n = d3_time_numberRe.exec(string.slice(i, i + 3)); - return n ? (date.L = +n[0], i + n[0].length) : -1; + function removeAll() { + var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; + for (var name in this) { + if (match = name.match(re)) { + var l = this[name]; + this.removeEventListener(match[1], l, l.$); + delete this[name]; + } + } + } + return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; } - function d3_time_zone(d) { - var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; - return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + var d3_selection_onFilters = d3.map({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }); + if (d3_document) { + d3_selection_onFilters.forEach(function(k) { + if ("on" + k in d3_document) d3_selection_onFilters.remove(k); + }); } - function d3_time_parseLiteralPercent(date, string, i) { - d3_time_percentRe.lastIndex = 0; - var n = d3_time_percentRe.exec(string.slice(i, i + 1)); - return n ? i + n[0].length : -1; + function d3_selection_onListener(listener, argumentz) { + return function(e) { + var o = d3.event; + d3.event = e; + argumentz[0] = this.__data__; + try { + listener.apply(this, argumentz); + } finally { + d3.event = o; + } + }; } - function d3_time_formatMulti(formats) { - var n = formats.length, i = -1; - while (++i < n) formats[i][0] = this(formats[i][0]); - return function(date) { - var i = 0, f = formats[i]; - while (!f[1](date)) f = formats[++i]; - return f[0](date); + function d3_selection_onFilter(listener, argumentz) { + var l = d3_selection_onListener(listener, argumentz); + return function(e) { + var target = this, related = e.relatedTarget; + if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { + l.call(target, e); + } }; } - d3.locale = function(locale) { - return { - numberFormat: d3_locale_numberFormat(locale), - timeFormat: d3_locale_timeFormat(locale) + var d3_event_dragSelect, d3_event_dragId = 0; + function d3_event_dragSuppress(node) { + var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); + if (d3_event_dragSelect == null) { + d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect"); + } + if (d3_event_dragSelect) { + var style = d3_documentElement(node).style, select = style[d3_event_dragSelect]; + style[d3_event_dragSelect] = "none"; + } + return function(suppressClick) { + w.on(name, null); + if (d3_event_dragSelect) style[d3_event_dragSelect] = select; + if (suppressClick) { + var off = function() { + w.on(click, null); + }; + w.on(click, function() { + d3_eventPreventDefault(); + off(); + }, true); + setTimeout(off, 0); + } }; + } + d3.mouse = function(container) { + return d3_mousePoint(container, d3_eventSource()); }; - var d3_locale_enUS = d3.locale({ - decimal: ".", - thousands: ",", - grouping: [ 3 ], - currency: [ "$", "" ], - dateTime: "%a %b %e %X %Y", - date: "%m/%d/%Y", - time: "%H:%M:%S", - periods: [ "AM", "PM" ], - days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], - shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], - months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], - shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] - }); - d3.format = d3_locale_enUS.numberFormat; - d3.geo = {}; - function d3_adder() {} - d3_adder.prototype = { - s: 0, - t: 0, - add: function(y) { - d3_adderSum(y, this.t, d3_adderTemp); - d3_adderSum(d3_adderTemp.s, this.s, this); - if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; - }, - reset: function() { - this.s = this.t = 0; - }, - valueOf: function() { - return this.s; + var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0; + function d3_mousePoint(container, e) { + if (e.changedTouches) e = e.changedTouches[0]; + var svg = container.ownerSVGElement || container; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + if (d3_mouse_bug44083 < 0) { + var window = d3_window(container); + if (window.scrollX || window.scrollY) { + svg = d3.select("body").append("svg").style({ + position: "absolute", + top: 0, + left: 0, + margin: 0, + padding: 0, + border: "none" + }, "important"); + var ctm = svg[0][0].getScreenCTM(); + d3_mouse_bug44083 = !(ctm.f || ctm.e); + svg.remove(); + } + } + if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, + point.y = e.clientY; + point = point.matrixTransform(container.getScreenCTM().inverse()); + return [ point.x, point.y ]; } - }; - var d3_adderTemp = new d3_adder(); - function d3_adderSum(a, b, o) { - var x = o.s = a + b, bv = x - a, av = x - bv; - o.t = a - av + (b - bv); + var rect = container.getBoundingClientRect(); + return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; } - d3.geo.stream = function(object, listener) { - if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { - d3_geo_streamObjectType[object.type](object, listener); - } else { - d3_geo_streamGeometry(object, listener); + d3.touch = function(container, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; + if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return d3_mousePoint(container, touch); + } } }; - function d3_geo_streamGeometry(geometry, listener) { - if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { - d3_geo_streamGeometryType[geometry.type](geometry, listener); - } - } - var d3_geo_streamObjectType = { - Feature: function(feature, listener) { - d3_geo_streamGeometry(feature.geometry, listener); - }, - FeatureCollection: function(object, listener) { - var features = object.features, i = -1, n = features.length; - while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); + d3.behavior.drag = function() { + var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend"); + function drag() { + this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); } - }; - var d3_geo_streamGeometryType = { - Sphere: function(object, listener) { - listener.sphere(); - }, - Point: function(object, listener) { - object = object.coordinates; - listener.point(object[0], object[1], object[2]); - }, - MultiPoint: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); - }, - LineString: function(object, listener) { - d3_geo_streamLine(object.coordinates, listener, 0); - }, - MultiLineString: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); - }, - Polygon: function(object, listener) { - d3_geo_streamPolygon(object.coordinates, listener); - }, - MultiPolygon: function(object, listener) { - var coordinates = object.coordinates, i = -1, n = coordinates.length; - while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); - }, - GeometryCollection: function(object, listener) { - var geometries = object.geometries, i = -1, n = geometries.length; - while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + function dragstart(id, position, subject, move, end) { + return function() { + var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId); + if (origin) { + dragOffset = origin.apply(that, arguments); + dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; + } else { + dragOffset = [ 0, 0 ]; + } + dispatch({ + type: "dragstart" + }); + function moved() { + var position1 = position(parent, dragId), dx, dy; + if (!position1) return; + dx = position1[0] - position0[0]; + dy = position1[1] - position0[1]; + dragged |= dx | dy; + position0 = position1; + dispatch({ + type: "drag", + x: position1[0] + dragOffset[0], + y: position1[1] + dragOffset[1], + dx: dx, + dy: dy + }); + } + function ended() { + if (!position(parent, dragId)) return; + dragSubject.on(move + dragName, null).on(end + dragName, null); + dragRestore(dragged); + dispatch({ + type: "dragend" + }); + } + }; } + drag.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return drag; + }; + return d3.rebind(drag, event, "on"); }; - function d3_geo_streamLine(coordinates, listener, closed) { - var i = -1, n = coordinates.length - closed, coordinate; - listener.lineStart(); - while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); - listener.lineEnd(); - } - function d3_geo_streamPolygon(coordinates, listener) { - var i = -1, n = coordinates.length; - listener.polygonStart(); - while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); - listener.polygonEnd(); + function d3_behavior_dragTouchId() { + return d3.event.changedTouches[0].identifier; } - d3.geo.area = function(object) { - d3_geo_areaSum = 0; - d3.geo.stream(object, d3_geo_area); - return d3_geo_areaSum; - }; - var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); - var d3_geo_area = { - sphere: function() { - d3_geo_areaSum += 4 * π; - }, - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_areaRingSum.reset(); - d3_geo_area.lineStart = d3_geo_areaRingStart; - }, - polygonEnd: function() { - var area = 2 * d3_geo_areaRingSum; - d3_geo_areaSum += area < 0 ? 4 * π + area : area; - d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; - } + d3.touches = function(container, touches) { + if (arguments.length < 2) touches = d3_eventSource().touches; + return touches ? d3_array(touches).map(function(touch) { + var point = d3_mousePoint(container, touch); + point.identifier = touch.identifier; + return point; + }) : []; }; - function d3_geo_areaRingStart() { - var λ00, φ00, λ0, cosφ0, sinφ0; - d3_geo_area.point = function(λ, φ) { - d3_geo_area.point = nextPoint; - λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), - sinφ0 = Math.sin(φ); - }; - function nextPoint(λ, φ) { - λ *= d3_radians; - φ = φ * d3_radians / 2 + π / 4; - var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); - d3_geo_areaRingSum.add(Math.atan2(v, u)); - λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; - } - d3_geo_area.lineEnd = function() { - nextPoint(λ00, φ00); - }; - } - function d3_geo_cartesian(spherical) { - var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); - return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; + var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π; + function d3_sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; } - function d3_geo_cartesianDot(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + function d3_cross2d(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); } - function d3_geo_cartesianCross(a, b) { - return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; + function d3_acos(x) { + return x > 1 ? 0 : x < -1 ? π : Math.acos(x); } - function d3_geo_cartesianAdd(a, b) { - a[0] += b[0]; - a[1] += b[1]; - a[2] += b[2]; + function d3_asin(x) { + return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x); } - function d3_geo_cartesianScale(vector, k) { - return [ vector[0] * k, vector[1] * k, vector[2] * k ]; + function d3_sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; } - function d3_geo_cartesianNormalize(d) { - var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); - d[0] /= l; - d[1] /= l; - d[2] /= l; + function d3_cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; } - function d3_geo_spherical(cartesian) { - return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; + function d3_tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); } - function d3_geo_sphericalEqual(a, b) { - return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + function d3_haversin(x) { + return (x = Math.sin(x / 2)) * x; } - d3.geo.bounds = function() { - var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; - var bound = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - bound.point = ringPoint; - bound.lineStart = ringStart; - bound.lineEnd = ringEnd; - dλSum = 0; - d3_geo_area.polygonStart(); - }, - polygonEnd: function() { - d3_geo_area.polygonEnd(); - bound.point = point; - bound.lineStart = lineStart; - bound.lineEnd = lineEnd; - if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; - range[0] = λ0, range[1] = λ1; - } - }; - function point(λ, φ) { - ranges.push(range = [ λ0 = λ, λ1 = λ ]); - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - function linePoint(λ, φ) { - var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); - if (p0) { - var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); - d3_geo_cartesianNormalize(inflection); - inflection = d3_geo_spherical(inflection); - var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; - if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = inflection[1] * d3_degrees; - if (φi > φ1) φ1 = φi; - } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { - var φi = -inflection[1] * d3_degrees; - if (φi < φ0) φ0 = φi; - } else { - if (φ < φ0) φ0 = φ; - if (φ > φ1) φ1 = φ; - } - if (antimeridian) { - if (λ < λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } else { - if (λ1 >= λ0) { - if (λ < λ0) λ0 = λ; - if (λ > λ1) λ1 = λ; - } else { - if (λ > λ_) { - if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; - } else { - if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; - } - } - } - } else { - point(λ, φ); - } - p0 = p, λ_ = λ; - } - function lineStart() { - bound.point = linePoint; - } - function lineEnd() { - range[0] = λ0, range[1] = λ1; - bound.point = point; - p0 = null; - } - function ringPoint(λ, φ) { - if (p0) { - var dλ = λ - λ_; - dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; - } else λ__ = λ, φ__ = φ; - d3_geo_area.point(λ, φ); - linePoint(λ, φ); - } - function ringStart() { - d3_geo_area.lineStart(); - } - function ringEnd() { - ringPoint(λ__, φ__); - d3_geo_area.lineEnd(); - if (abs(dλSum) > ε) λ0 = -(λ1 = 180); - range[0] = λ0, range[1] = λ1; - p0 = null; - } - function angle(λ0, λ1) { - return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4; + d3.interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S; + if (d2 < ε2) { + S = Math.log(w1 / w0) / ρ; + i = function(t) { + return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ]; + }; + } else { + var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / ρ; + i = function(t) { + var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0)); + return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ]; + }; } - function compareRanges(a, b) { - return a[0] - b[0]; + i.duration = S * 1e3; + return i; + }; + d3.behavior.zoom = function() { + var view = { + x: 0, + y: 0, + k: 1 + }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; + if (!d3_behavior_zoomWheel) { + d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); + }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return d3.event.wheelDelta; + }, "mousewheel") : (d3_behavior_zoomDelta = function() { + return -d3.event.detail; + }, "MozMousePixelScroll"); } - function withinRange(x, range) { - return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + function zoom(g) { + g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); } - return function(feature) { - φ1 = λ1 = -(λ0 = φ0 = Infinity); - ranges = []; - d3.geo.stream(feature, bound); - var n = ranges.length; - if (n) { - ranges.sort(compareRanges); - for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { - b = ranges[i]; - if (withinRange(b[0], a) || withinRange(b[1], a)) { - if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; - if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; - } else { - merged.push(a = b); - } - } - var best = -Infinity, dλ; - for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { - b = merged[i]; - if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + zoom.event = function(g) { + g.each(function() { + var dispatch = event.of(this, arguments), view1 = view; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.zoom", function() { + view = this.__chart__ || { + x: 0, + y: 0, + k: 1 + }; + zoomstarted(dispatch); + }).tween("zoom:zoom", function() { + var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); + return function(t) { + var l = i(t), k = dx / l[2]; + this.__chart__ = view = { + x: cx - l[0] * k, + y: cy - l[1] * k, + k: k + }; + zoomed(dispatch); + }; + }).each("interrupt.zoom", function() { + zoomended(dispatch); + }).each("end.zoom", function() { + zoomended(dispatch); + }); + } else { + this.__chart__ = view; + zoomstarted(dispatch); + zoomed(dispatch); + zoomended(dispatch); } - } - ranges = range = null; - return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }); }; - }(); - d3.geo.centroid = function(object) { - d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, d3_geo_centroid); - var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; - if (m < ε2) { - x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; - if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; - m = x * x + y * y + z * z; - if (m < ε2) return [ NaN, NaN ]; - } - return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; - }; - var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; - var d3_geo_centroid = { - sphere: d3_noop, - point: d3_geo_centroidPoint, - lineStart: d3_geo_centroidLineStart, - lineEnd: d3_geo_centroidLineEnd, - polygonStart: function() { - d3_geo_centroid.lineStart = d3_geo_centroidRingStart; - }, - polygonEnd: function() { - d3_geo_centroid.lineStart = d3_geo_centroidLineStart; - } - }; - function d3_geo_centroidPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); - } - function d3_geo_centroidPointXYZ(x, y, z) { - ++d3_geo_centroidW0; - d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; - d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; - d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; - } - function d3_geo_centroidLineStart() { - var x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroid.point = nextPoint; - d3_geo_centroidPointXYZ(x0, y0, z0); + zoom.translate = function(_) { + if (!arguments.length) return [ view.x, view.y ]; + view = { + x: +_[0], + y: +_[1], + k: view.k + }; + rescale(); + return zoom; }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_centroidLineEnd() { - d3_geo_centroid.point = d3_geo_centroidPoint; - } - function d3_geo_centroidRingStart() { - var λ00, φ00, x0, y0, z0; - d3_geo_centroid.point = function(λ, φ) { - λ00 = λ, φ00 = φ; - d3_geo_centroid.point = nextPoint; - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians); - x0 = cosφ * Math.cos(λ); - y0 = cosφ * Math.sin(λ); - z0 = Math.sin(φ); - d3_geo_centroidPointXYZ(x0, y0, z0); + zoom.scale = function(_) { + if (!arguments.length) return view.k; + view = { + x: view.x, + y: view.y, + k: null + }; + scaleTo(+_); + rescale(); + return zoom; }; - d3_geo_centroid.lineEnd = function() { - nextPoint(λ00, φ00); - d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; - d3_geo_centroid.point = d3_geo_centroidPoint; + zoom.scaleExtent = function(_) { + if (!arguments.length) return scaleExtent; + scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; + return zoom; + }; + zoom.center = function(_) { + if (!arguments.length) return center; + center = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.size = function(_) { + if (!arguments.length) return size; + size = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.duration = function(_) { + if (!arguments.length) return duration; + duration = +_; + return zoom; + }; + zoom.x = function(z) { + if (!arguments.length) return x1; + x1 = z; + x0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + zoom.y = function(z) { + if (!arguments.length) return y1; + y1 = z; + y0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; }; - function nextPoint(λ, φ) { - λ *= d3_radians; - var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); - d3_geo_centroidX2 += v * cx; - d3_geo_centroidY2 += v * cy; - d3_geo_centroidZ2 += v * cz; - d3_geo_centroidW1 += w; - d3_geo_centroidX1 += w * (x0 + (x0 = x)); - d3_geo_centroidY1 += w * (y0 + (y0 = y)); - d3_geo_centroidZ1 += w * (z0 + (z0 = z)); - d3_geo_centroidPointXYZ(x0, y0, z0); - } - } - function d3_geo_compose(a, b) { - function compose(x, y) { - return x = a(x, y), b(x[0], x[1]); + function location(p) { + return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; } - if (a.invert && b.invert) compose.invert = function(x, y) { - return x = b.invert(x, y), x && a.invert(x[0], x[1]); - }; - return compose; - } - function d3_true() { - return true; - } - function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { - var subject = [], clip = []; - segments.forEach(function(segment) { - if ((n = segment.length - 1) <= 0) return; - var n, p0 = segment[0], p1 = segment[n]; - if (d3_geo_sphericalEqual(p0, p1)) { - listener.lineStart(); - for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); - listener.lineEnd(); - return; - } - var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); - a.o = b; - subject.push(a); - clip.push(b); - a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); - b = new d3_geo_clipPolygonIntersection(p1, null, a, true); - a.o = b; - subject.push(a); - clip.push(b); - }); - clip.sort(compare); - d3_geo_clipPolygonLinkCircular(subject); - d3_geo_clipPolygonLinkCircular(clip); - if (!subject.length) return; - for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { - clip[i].e = entry = !entry; + function point(l) { + return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; } - var start = subject[0], points, point; - while (1) { - var current = start, isSubject = true; - while (current.v) if ((current = current.n) === start) return; - points = current.z; - listener.lineStart(); - do { - current.v = current.o.v = true; - if (current.e) { - if (isSubject) { - for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.n.x, 1, listener); - } - current = current.n; - } else { - if (isSubject) { - points = current.p.z; - for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); - } else { - interpolate(current.x, current.p.x, -1, listener); - } - current = current.p; - } - current = current.o; - points = current.z; - isSubject = !isSubject; - } while (!current.v); - listener.lineEnd(); + function scaleTo(s) { + view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); } - } - function d3_geo_clipPolygonLinkCircular(array) { - if (!(n = array.length)) return; - var n, i = 0, a = array[0], b; - while (++i < n) { - a.n = b = array[i]; - b.p = a; - a = b; + function translateTo(p, l) { + l = point(l); + view.x += p[0] - l[0]; + view.y += p[1] - l[1]; } - a.n = b = array[0]; - b.p = a; - } - function d3_geo_clipPolygonIntersection(point, points, other, entry) { - this.x = point; - this.z = points; - this.o = other; - this.e = entry; - this.v = false; - this.n = this.p = null; - } - function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { - return function(rotate, listener) { - var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - clip.point = pointRing; - clip.lineStart = ringStart; - clip.lineEnd = ringEnd; - segments = []; - polygon = []; - }, - polygonEnd: function() { - clip.point = point; - clip.lineStart = lineStart; - clip.lineEnd = lineEnd; - segments = d3.merge(segments); - var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); - if (segments.length) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); - } else if (clipStartInside) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (polygonStarted) listener.polygonEnd(), polygonStarted = false; - segments = polygon = null; - }, - sphere: function() { - listener.polygonStart(); - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - listener.polygonEnd(); - } + function zoomTo(that, p, l, k) { + that.__chart__ = { + x: view.x, + y: view.y, + k: view.k }; - function point(λ, φ) { - var point = rotate(λ, φ); - if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); - } - function pointLine(λ, φ) { - var point = rotate(λ, φ); - line.point(point[0], point[1]); + scaleTo(Math.pow(2, k)); + translateTo(center0 = p, l); + that = d3.select(that); + if (duration > 0) that = that.transition().duration(duration); + that.call(zoom.event); + } + function rescale() { + if (x1) x1.domain(x0.range().map(function(x) { + return (x - view.x) / view.k; + }).map(x0.invert)); + if (y1) y1.domain(y0.range().map(function(y) { + return (y - view.y) / view.k; + }).map(y0.invert)); + } + function zoomstarted(dispatch) { + if (!zooming++) dispatch({ + type: "zoomstart" + }); + } + function zoomed(dispatch) { + rescale(); + dispatch({ + type: "zoom", + scale: view.k, + translate: [ view.x, view.y ] + }); + } + function zoomended(dispatch) { + if (!--zooming) dispatch({ + type: "zoomend" + }), center0 = null; + } + function mousedowned() { + var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that); + d3_selection_interrupt.call(that); + zoomstarted(dispatch); + function moved() { + dragged = 1; + translateTo(d3.mouse(that), location0); + zoomed(dispatch); } - function lineStart() { - clip.point = pointLine; - line.lineStart(); + function ended() { + subject.on(mousemove, null).on(mouseup, null); + dragRestore(dragged); + zoomended(dispatch); } - function lineEnd() { - clip.point = point; - line.lineEnd(); + } + function touchstarted() { + var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that); + started(); + zoomstarted(dispatch); + subject.on(mousedown, null).on(touchstart, started); + function relocate() { + var touches = d3.touches(that); + scale0 = view.k; + touches.forEach(function(t) { + if (t.identifier in locations0) locations0[t.identifier] = location(t); + }); + return touches; } - var segments; - var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; - function pointRing(λ, φ) { - ring.push([ λ, φ ]); - var point = rotate(λ, φ); - ringListener.point(point[0], point[1]); + function started() { + var target = d3.event.target; + d3.select(target).on(touchmove, moved).on(touchend, ended); + targets.push(target); + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + locations0[changed[i].identifier] = null; + } + var touches = relocate(), now = Date.now(); + if (touches.length === 1) { + if (now - touchtime < 500) { + var p = touches[0]; + zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1); + d3_eventPreventDefault(); + } + touchtime = now; + } else if (touches.length > 1) { + var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; + distance0 = dx * dx + dy * dy; + } } - function ringStart() { - ringListener.lineStart(); - ring = []; + function moved() { + var touches = d3.touches(that), p0, l0, p1, l1; + d3_selection_interrupt.call(that); + for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { + p1 = touches[i]; + if (l1 = locations0[p1.identifier]) { + if (l0) break; + p0 = p1, l0 = l1; + } + } + if (l1) { + var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); + p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; + l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; + scaleTo(scale1 * scale0); + } + touchtime = null; + translateTo(p0, l0); + zoomed(dispatch); } - function ringEnd() { - pointRing(ring[0][0], ring[0][1]); - ringListener.lineEnd(); - var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; - ring.pop(); - polygon.push(ring); - ring = null; - if (!n) return; - if (clean & 1) { - segment = ringSegments[0]; - var n = segment.length - 1, i = -1, point; - if (n > 0) { - if (!polygonStarted) listener.polygonStart(), polygonStarted = true; - listener.lineStart(); - while (++i < n) listener.point((point = segment[i])[0], point[1]); - listener.lineEnd(); + function ended() { + if (d3.event.touches.length) { + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + delete locations0[changed[i].identifier]; + } + for (var identifier in locations0) { + return void relocate(); } - return; } - if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); - segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + d3.selectAll(targets).on(zoomName, null); + subject.on(mousedown, mousedowned).on(touchstart, touchstarted); + dragRestore(); + zoomended(dispatch); } - return clip; - }; + } + function mousewheeled() { + var dispatch = event.of(this, arguments); + if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), + translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch); + mousewheelTimer = setTimeout(function() { + mousewheelTimer = null; + zoomended(dispatch); + }, 50); + d3_eventPreventDefault(); + scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); + translateTo(center0, translate0); + zoomed(dispatch); + } + function dblclicked() { + var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2; + zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1); + } + return d3.rebind(zoom, event, "on"); + }; + var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel; + d3.color = d3_color; + function d3_color() {} + d3_color.prototype.toString = function() { + return this.rgb() + ""; + }; + d3.hsl = d3_hsl; + function d3_hsl(h, s, l) { + return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); } - function d3_geo_clipSegmentLength1(segment) { - return segment.length > 1; + var d3_hslPrototype = d3_hsl.prototype = new d3_color(); + d3_hslPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, this.l / k); + }; + d3_hslPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, k * this.l); + }; + d3_hslPrototype.rgb = function() { + return d3_hsl_rgb(this.h, this.s, this.l); + }; + function d3_hsl_rgb(h, s, l) { + var m1, m2; + h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; + s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; + l = l < 0 ? 0 : l > 1 ? 1 : l; + m2 = l <= .5 ? l * (1 + s) : l + s - l * s; + m1 = 2 * l - m2; + function v(h) { + if (h > 360) h -= 360; else if (h < 0) h += 360; + if (h < 60) return m1 + (m2 - m1) * h / 60; + if (h < 180) return m2; + if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; + return m1; + } + function vv(h) { + return Math.round(v(h) * 255); + } + return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); } - function d3_geo_clipBufferListener() { - var lines = [], line; - return { - lineStart: function() { - lines.push(line = []); - }, - point: function(λ, φ) { - line.push([ λ, φ ]); - }, - lineEnd: d3_noop, - buffer: function() { - var buffer = lines; - lines = []; - line = null; - return buffer; - }, - rejoin: function() { - if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); - } - }; + d3.hcl = d3_hcl; + function d3_hcl(h, c, l) { + return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); } - function d3_geo_clipSort(a, b) { - return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); + var d3_hclPrototype = d3_hcl.prototype = new d3_color(); + d3_hclPrototype.brighter = function(k) { + return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.darker = function(k) { + return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.rgb = function() { + return d3_hcl_lab(this.h, this.c, this.l).rgb(); + }; + function d3_hcl_lab(h, c, l) { + if (isNaN(h)) h = 0; + if (isNaN(c)) c = 0; + return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); } - var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); - function d3_geo_clipAntimeridianLine(listener) { - var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; - return { - lineStart: function() { - listener.lineStart(); - clean = 1; - }, - point: function(λ1, φ1) { - var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); - if (abs(dλ - π) < ε) { - listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - listener.point(λ1, φ0); - clean = 0; - } else if (sλ0 !== sλ1 && dλ >= π) { - if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; - if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; - φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); - listener.point(sλ0, φ0); - listener.lineEnd(); - listener.lineStart(); - listener.point(sλ1, φ0); - clean = 0; - } - listener.point(λ0 = λ1, φ0 = φ1); - sλ0 = sλ1; - }, - lineEnd: function() { - listener.lineEnd(); - λ0 = φ0 = NaN; - }, - clean: function() { - return 2 - clean; - } - }; + d3.lab = d3_lab; + function d3_lab(l, a, b) { + return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); } - function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { - var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); - return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; + var d3_lab_K = 18; + var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; + var d3_labPrototype = d3_lab.prototype = new d3_color(); + d3_labPrototype.brighter = function(k) { + return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.darker = function(k) { + return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.rgb = function() { + return d3_lab_rgb(this.l, this.a, this.b); + }; + function d3_lab_rgb(l, a, b) { + var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; + x = d3_lab_xyz(x) * d3_lab_X; + y = d3_lab_xyz(y) * d3_lab_Y; + z = d3_lab_xyz(z) * d3_lab_Z; + return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); } - function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { - var φ; - if (from == null) { - φ = direction * halfπ; - listener.point(-π, φ); - listener.point(0, φ); - listener.point(π, φ); - listener.point(π, 0); - listener.point(π, -φ); - listener.point(0, -φ); - listener.point(-π, -φ); - listener.point(-π, 0); - listener.point(-π, φ); - } else if (abs(from[0] - to[0]) > ε) { - var s = from[0] < to[0] ? π : -π; - φ = direction * s / 2; - listener.point(-s, φ); - listener.point(0, φ); - listener.point(s, φ); - } else { - listener.point(to[0], to[1]); - } + function d3_lab_hcl(l, a, b) { + return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); + } + function d3_lab_xyz(x) { + return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; + } + function d3_xyz_lab(x) { + return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; + } + function d3_xyz_rgb(r) { + return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); + } + d3.rgb = d3_rgb; + function d3_rgb(r, g, b) { + return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); + } + function d3_rgbNumber(value) { + return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); } - function d3_geo_pointInPolygon(point, polygon) { - var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; - d3_geo_areaRingSum.reset(); - for (var i = 0, n = polygon.length; i < n; ++i) { - var ring = polygon[i], m = ring.length; - if (!m) continue; - var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; - while (true) { - if (j === m) j = 0; - point = ring[j]; - var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; - d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); - polarAngle += antimeridian ? dλ + sdλ * τ : dλ; - if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { - var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); - d3_geo_cartesianNormalize(arc); - var intersection = d3_geo_cartesianCross(meridianNormal, arc); - d3_geo_cartesianNormalize(intersection); - var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); - if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { - winding += antimeridian ^ dλ >= 0 ? 1 : -1; - } + function d3_rgbString(value) { + return d3_rgbNumber(value) + ""; + } + var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); + d3_rgbPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + var r = this.r, g = this.g, b = this.b, i = 30; + if (!r && !g && !b) return new d3_rgb(i, i, i); + if (r && r < i) r = i; + if (g && g < i) g = i; + if (b && b < i) b = i; + return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + }; + d3_rgbPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_rgb(k * this.r, k * this.g, k * this.b); + }; + d3_rgbPrototype.hsl = function() { + return d3_rgb_hsl(this.r, this.g, this.b); + }; + d3_rgbPrototype.toString = function() { + return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + }; + function d3_rgb_hex(v) { + return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); + } + function d3_rgb_parse(format, rgb, hsl) { + var r = 0, g = 0, b = 0, m1, m2, color; + m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase()); + if (m1) { + m2 = m1[2].split(","); + switch (m1[1]) { + case "hsl": + { + return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); + } + + case "rgb": + { + return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); } - if (!j++) break; - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; } } - return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; - } - function d3_geo_clipCircle(radius) { - var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); - return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); - function visible(λ, φ) { - return Math.cos(λ) * Math.cos(φ) > cr; - } - function clipLine(listener) { - var point0, c0, v0, v00, clean; - return { - lineStart: function() { - v00 = v0 = false; - clean = 1; - }, - point: function(λ, φ) { - var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; - if (!point0 && (v00 = v0 = v)) listener.lineStart(); - if (v !== v0) { - point2 = intersect(point0, point1); - if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { - point1[0] += ε; - point1[1] += ε; - v = visible(point1[0], point1[1]); - } - } - if (v !== v0) { - clean = 0; - if (v) { - listener.lineStart(); - point2 = intersect(point1, point0); - listener.point(point2[0], point2[1]); - } else { - point2 = intersect(point0, point1); - listener.point(point2[0], point2[1]); - listener.lineEnd(); - } - point0 = point2; - } else if (notHemisphere && point0 && smallRadius ^ v) { - var t; - if (!(c & c0) && (t = intersect(point1, point0, true))) { - clean = 0; - if (smallRadius) { - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - } else { - listener.point(t[1][0], t[1][1]); - listener.lineEnd(); - listener.lineStart(); - listener.point(t[0][0], t[0][1]); - } - } - } - if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { - listener.point(point1[0], point1[1]); - } - point0 = point1, v0 = v, c0 = c; - }, - lineEnd: function() { - if (v0) listener.lineEnd(); - point0 = null; - }, - clean: function() { - return clean | (v00 && v0) << 1; - } - }; + if (color = d3_rgb_names.get(format)) { + return rgb(color.r, color.g, color.b); } - function intersect(a, b, two) { - var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); - var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; - if (!determinant) return !two && a; - var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); - d3_geo_cartesianAdd(A, B); - var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); - if (t2 < 0) return; - var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); - d3_geo_cartesianAdd(q, A); - q = d3_geo_spherical(q); - if (!two) return q; - var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; - if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; - var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; - if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; - if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { - var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); - d3_geo_cartesianAdd(q1, A); - return [ q, d3_geo_spherical(q1) ]; + if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) { + if (format.length === 4) { + r = (color & 3840) >> 4; + r = r >> 4 | r; + g = color & 240; + g = g >> 4 | g; + b = color & 15; + b = b << 4 | b; + } else if (format.length === 7) { + r = (color & 16711680) >> 16; + g = (color & 65280) >> 8; + b = color & 255; } } - function code(λ, φ) { - var r = smallRadius ? radius : π - radius, code = 0; - if (λ < -r) code |= 1; else if (λ > r) code |= 2; - if (φ < -r) code |= 4; else if (φ > r) code |= 8; - return code; + return rgb(r, g, b); + } + function d3_rgb_hsl(r, g, b) { + var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; + if (d) { + s = l < .5 ? d / (max + min) : d / (2 - max - min); + if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; + h *= 60; + } else { + h = NaN; + s = l > 0 && l < 1 ? 0 : h; } + return new d3_hsl(h, s, l); } - function d3_geom_clipLine(x0, y0, x1, y1) { - return function(line) { - var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; - r = x0 - ax; - if (!dx && r > 0) return; - r /= dx; - if (dx < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dx > 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } - r = x1 - ax; - if (!dx && r < 0) return; - r /= dx; - if (dx < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dx > 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } - r = y0 - ay; - if (!dy && r > 0) return; - r /= dy; - if (dy < 0) { - if (r < t0) return; - if (r < t1) t1 = r; - } else if (dy > 0) { - if (r > t1) return; - if (r > t0) t0 = r; + function d3_rgb_lab(r, g, b) { + r = d3_rgb_xyz(r); + g = d3_rgb_xyz(g); + b = d3_rgb_xyz(b); + var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); + return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); + } + function d3_rgb_xyz(r) { + return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); + } + function d3_rgb_parseNumber(c) { + var f = parseFloat(c); + return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; + } + var d3_rgb_names = d3.map({ + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + rebeccapurple: 6697881, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }); + d3_rgb_names.forEach(function(key, value) { + d3_rgb_names.set(key, d3_rgbNumber(value)); + }); + function d3_functor(v) { + return typeof v === "function" ? v : function() { + return v; + }; + } + d3.functor = d3_functor; + d3.xhr = d3_xhrType(d3_identity); + function d3_xhrType(response) { + return function(url, mimeType, callback) { + if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, + mimeType = null; + return d3_xhr(url, mimeType, response, callback); + }; + } + function d3_xhr(url, mimeType, response, callback) { + var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; + if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); + "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { + request.readyState > 3 && respond(); + }; + function respond() { + var status = request.status, result; + if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { + try { + result = response.call(xhr, request); + } catch (e) { + dispatch.error.call(xhr, e); + return; + } + dispatch.load.call(xhr, result); + } else { + dispatch.error.call(xhr, request); } - r = y1 - ay; - if (!dy && r < 0) return; - r /= dy; - if (dy < 0) { - if (r > t1) return; - if (r > t0) t0 = r; - } else if (dy > 0) { - if (r < t0) return; - if (r < t1) t1 = r; + } + request.onprogress = function(event) { + var o = d3.event; + d3.event = event; + try { + dispatch.progress.call(xhr, request); + } finally { + d3.event = o; } - if (t0 > 0) line.a = { - x: ax + t0 * dx, - y: ay + t0 * dy - }; - if (t1 < 1) line.b = { - x: ax + t1 * dx, - y: ay + t1 * dy + }; + xhr.header = function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers[name]; + if (value == null) delete headers[name]; else headers[name] = value + ""; + return xhr; + }; + xhr.mimeType = function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return xhr; + }; + xhr.responseType = function(value) { + if (!arguments.length) return responseType; + responseType = value; + return xhr; + }; + xhr.response = function(value) { + response = value; + return xhr; + }; + [ "get", "post" ].forEach(function(method) { + xhr[method] = function() { + return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); }; - return line; + }); + xhr.send = function(method, data, callback) { + if (arguments.length === 2 && typeof data === "function") callback = data, data = null; + request.open(method, url, true); + if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; + if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); + if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); + if (responseType != null) request.responseType = responseType; + if (callback != null) xhr.on("error", callback).on("load", function(request) { + callback(null, request); + }); + dispatch.beforesend.call(xhr, request); + request.send(data == null ? null : data); + return xhr; + }; + xhr.abort = function() { + request.abort(); + return xhr; }; + d3.rebind(xhr, dispatch, "on"); + return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); } - var d3_geo_clipExtentMAX = 1e9; - d3.geo.clipExtent = function() { - var x0, y0, x1, y1, stream, clip, clipExtent = { - stream: function(output) { - if (stream) stream.valid = false; - stream = clip(output); - stream.valid = true; - return stream; - }, - extent: function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); - if (stream) stream.valid = false, stream = null; - return clipExtent; - } + function d3_xhr_fixCallback(callback) { + return callback.length === 1 ? function(error, request) { + callback(error == null ? request : null); + } : callback; + } + function d3_xhrHasResponse(request) { + var type = request.responseType; + return type && type !== "text" ? request.response : request.responseText; + } + d3.dsv = function(delimiter, mimeType) { + var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); + function dsv(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); + xhr.row = function(_) { + return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; + }; + return xhr; + } + function response(request) { + return dsv.parse(request.responseText); + } + function typedResponse(f) { + return function(request) { + return dsv.parse(request.responseText, f); + }; + } + dsv.parse = function(text, f) { + var o; + return dsv.parseRows(text, function(row, i) { + if (o) return o(row, i - 1); + var a = new Function("d", "return {" + row.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); + o = f ? function(row, i) { + return f(a(row), i); + } : a; + }); }; - return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); - }; - function d3_geo_clipExtent(x0, y0, x1, y1) { - return function(listener) { - var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; - var clip = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - listener = bufferListener; - segments = []; - polygon = []; - clean = true; - }, - polygonEnd: function() { - listener = listener_; - segments = d3.merge(segments); - var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; - if (inside || visible) { - listener.polygonStart(); - if (inside) { - listener.lineStart(); - interpolate(null, null, 1, listener); - listener.lineEnd(); - } - if (visible) { - d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + dsv.parseRows = function(text, f) { + var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; + function token() { + if (I >= N) return EOF; + if (eol) return eol = false, EOL; + var j = I; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; } - listener.polygonEnd(); } - segments = polygon = ring = null; - } - }; - function insidePolygon(p) { - var wn = 0, n = polygon.length, y = p[1]; - for (var i = 0; i < n; ++i) { - for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { - b = v[j]; - if (a[1] <= y) { - if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; - } else { - if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; - } - a = b; + I = i + 2; + var c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; } + return text.slice(j + 1, i).replace(/""/g, '"'); } - return wn !== 0; - } - function interpolate(from, to, direction, listener) { - var a = 0, a1 = 0; - if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { - do { - listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); - } while ((a = (a + direction + 4) % 4) !== a1); - } else { - listener.point(to[0], to[1]); + while (I < N) { + var c = text.charCodeAt(I++), k = 1; + if (c === 10) eol = true; else if (c === 13) { + eol = true; + if (text.charCodeAt(I) === 10) ++I, ++k; + } else if (c !== delimiterCode) continue; + return text.slice(j, I - k); } + return text.slice(j); } - function pointVisible(x, y) { - return x0 <= x && x <= x1 && y0 <= y && y <= y1; - } - function point(x, y) { - if (pointVisible(x, y)) listener.point(x, y); - } - var x__, y__, v__, x_, y_, v_, first, clean; - function lineStart() { - clip.point = linePoint; - if (polygon) polygon.push(ring = []); - first = true; - v_ = false; - x_ = y_ = NaN; - } - function lineEnd() { - if (segments) { - linePoint(x__, y__); - if (v__ && v_) bufferListener.rejoin(); - segments.push(bufferListener.buffer()); + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); } - clip.point = point; - if (v_) listener.lineEnd(); + if (f && (a = f(a, n++)) == null) continue; + rows.push(a); } - function linePoint(x, y) { - x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); - y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); - var v = pointVisible(x, y); - if (polygon) ring.push([ x, y ]); - if (first) { - x__ = x, y__ = y, v__ = v; - first = false; - if (v) { - listener.lineStart(); - listener.point(x, y); - } - } else { - if (v && v_) listener.point(x, y); else { - var l = { - a: { - x: x_, - y: y_ - }, - b: { - x: x, - y: y - } - }; - if (clipLine(l)) { - if (!v_) { - listener.lineStart(); - listener.point(l.a.x, l.a.y); - } - listener.point(l.b.x, l.b.y); - if (!v) listener.lineEnd(); - clean = false; - } else if (v) { - listener.lineStart(); - listener.point(x, y); - clean = false; - } + return rows; + }; + dsv.format = function(rows) { + if (Array.isArray(rows[0])) return dsv.formatRows(rows); + var fieldSet = new d3_Set(), fields = []; + rows.forEach(function(row) { + for (var field in row) { + if (!fieldSet.has(field)) { + fields.push(fieldSet.add(field)); } } - x_ = x, y_ = y, v_ = v; - } - return clip; + }); + return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { + return fields.map(function(field) { + return formatValue(row[field]); + }).join(delimiter); + })).join("\n"); }; - function corner(p, direction) { - return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; - } - function compare(a, b) { - return comparePoints(a.x, b.x); + dsv.formatRows = function(rows) { + return rows.map(formatRow).join("\n"); + }; + function formatRow(row) { + return row.map(formatValue).join(delimiter); } - function comparePoints(a, b) { - var ca = corner(a, 1), cb = corner(b, 1); - return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; + function formatValue(text) { + return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; } - } - function d3_geo_conic(projectAt) { - var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); - p.parallels = function(_) { - if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; - return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); + return dsv; + }; + d3.csv = d3.dsv(",", "text/csv"); + d3.tsv = d3.dsv(" ", "text/tab-separated-values"); + var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { + setTimeout(callback, 17); + }; + d3.timer = function() { + d3_timer.apply(this, arguments); + }; + function d3_timer(callback, delay, then) { + var n = arguments.length; + if (n < 2) delay = 0; + if (n < 3) then = Date.now(); + var time = then + delay, timer = { + c: callback, + t: time, + n: null }; - return p; + if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; + d3_timer_queueTail = timer; + if (!d3_timer_interval) { + d3_timer_timeout = clearTimeout(d3_timer_timeout); + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + return timer; } - function d3_geo_conicEqualArea(φ0, φ1) { - var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; - function forward(λ, φ) { - var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; - return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; + function d3_timer_step() { + var now = d3_timer_mark(), delay = d3_timer_sweep() - now; + if (delay > 24) { + if (isFinite(delay)) { + clearTimeout(d3_timer_timeout); + d3_timer_timeout = setTimeout(d3_timer_step, delay); + } + d3_timer_interval = 0; + } else { + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); } - forward.invert = function(x, y) { - var ρ0_y = ρ0 - y; - return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; - }; - return forward; } - (d3.geo.conicEqualArea = function() { - return d3_geo_conic(d3_geo_conicEqualArea); - }).raw = d3_geo_conicEqualArea; - d3.geo.albers = function() { - return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); + d3.timer.flush = function() { + d3_timer_mark(); + d3_timer_sweep(); }; - d3.geo.albersUsa = function() { - var lower48 = d3.geo.albers(); - var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); - var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); - var point, pointStream = { - point: function(x, y) { - point = [ x, y ]; + function d3_timer_mark() { + var now = Date.now(), timer = d3_timer_queueHead; + while (timer) { + if (now >= timer.t && timer.c(now - timer.t)) timer.c = null; + timer = timer.n; + } + return now; + } + function d3_timer_sweep() { + var t0, t1 = d3_timer_queueHead, time = Infinity; + while (t1) { + if (t1.c) { + if (t1.t < time) time = t1.t; + t1 = (t0 = t1).n; + } else { + t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; } - }, lower48Point, alaskaPoint, hawaiiPoint; - function albersUsa(coordinates) { - var x = coordinates[0], y = coordinates[1]; - point = null; - (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); - return point; } - albersUsa.invert = function(coordinates) { - var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; - return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); - }; - albersUsa.stream = function(stream) { - var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); - return { - point: function(x, y) { - lower48Stream.point(x, y); - alaskaStream.point(x, y); - hawaiiStream.point(x, y); - }, - sphere: function() { - lower48Stream.sphere(); - alaskaStream.sphere(); - hawaiiStream.sphere(); - }, - lineStart: function() { - lower48Stream.lineStart(); - alaskaStream.lineStart(); - hawaiiStream.lineStart(); - }, - lineEnd: function() { - lower48Stream.lineEnd(); - alaskaStream.lineEnd(); - hawaiiStream.lineEnd(); - }, - polygonStart: function() { - lower48Stream.polygonStart(); - alaskaStream.polygonStart(); - hawaiiStream.polygonStart(); - }, - polygonEnd: function() { - lower48Stream.polygonEnd(); - alaskaStream.polygonEnd(); - hawaiiStream.polygonEnd(); - } - }; - }; - albersUsa.precision = function(_) { - if (!arguments.length) return lower48.precision(); - lower48.precision(_); - alaska.precision(_); - hawaii.precision(_); - return albersUsa; - }; - albersUsa.scale = function(_) { - if (!arguments.length) return lower48.scale(); - lower48.scale(_); - alaska.scale(_ * .35); - hawaii.scale(_); - return albersUsa.translate(lower48.translate()); - }; - albersUsa.translate = function(_) { - if (!arguments.length) return lower48.translate(); - var k = lower48.scale(), x = +_[0], y = +_[1]; - lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; - alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; - return albersUsa; - }; - return albersUsa.scale(1070); + d3_timer_queueTail = t0; + return time; + } + function d3_format_precision(x, p) { + return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); + } + d3.round = function(x, n) { + return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); }; - var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { - point: d3_noop, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: function() { - d3_geo_pathAreaPolygon = 0; - d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; - }, - polygonEnd: function() { - d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; - d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); + var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); + d3.formatPrefix = function(value, precision) { + var i = 0; + if (value = +value) { + if (value < 0) value *= -1; + if (precision) value = d3.round(value, d3_format_precision(value, precision)); + i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); + i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); } + return d3_formatPrefixes[8 + i / 3]; }; - function d3_geo_pathAreaRingStart() { - var x00, y00, x0, y0; - d3_geo_pathArea.point = function(x, y) { - d3_geo_pathArea.point = nextPoint; - x00 = x0 = x, y00 = y0 = y; - }; - function nextPoint(x, y) { - d3_geo_pathAreaPolygon += y0 * x - x0 * y; - x0 = x, y0 = y; - } - d3_geo_pathArea.lineEnd = function() { - nextPoint(x00, y00); + function d3_formatPrefix(d, i) { + var k = Math.pow(10, abs(8 - i) * 3); + return { + scale: i > 8 ? function(d) { + return d / k; + } : function(d) { + return d * k; + }, + symbol: d }; } - var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; - var d3_geo_pathBounds = { - point: d3_geo_pathBoundsPoint, - lineStart: d3_noop, - lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop - }; - function d3_geo_pathBoundsPoint(x, y) { - if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; - if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; - if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; - if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; - } - function d3_geo_pathBuffer() { - var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointCircle = d3_geo_pathBufferCircle(_); - return stream; - }, - result: function() { - if (buffer.length) { - var result = buffer.join(""); - buffer = []; - return result; + function d3_locale_numberFormat(locale) { + var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) { + var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0; + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = locale_grouping[j = (j + 1) % locale_grouping.length]; + } + return t.reverse().join(locale_thousands); + } : d3_identity; + return function(specifier) { + var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true; + if (precision) precision = +precision.substring(1); + if (zfill || fill === "0" && align === "=") { + zfill = fill = "0"; + align = "="; + } + switch (type) { + case "n": + comma = true; + type = "g"; + break; + + case "%": + scale = 100; + suffix = "%"; + type = "f"; + break; + + case "p": + scale = 100; + suffix = "%"; + type = "r"; + break; + + case "b": + case "o": + case "x": + case "X": + if (symbol === "#") prefix = "0" + type.toLowerCase(); + + case "c": + exponent = false; + + case "d": + integer = true; + precision = 0; + break; + + case "s": + scale = -1; + type = "r"; + break; + } + if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; + if (type == "r" && !precision) type = "g"; + if (precision != null) { + if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); + } + type = d3_format_types.get(type) || d3_format_typeDefault; + var zcomma = zfill && comma; + return function(value) { + var fullSuffix = suffix; + if (integer && value % 1) return ""; + var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign; + if (scale < 0) { + var unit = d3.formatPrefix(value, precision); + value = unit.scale(value); + fullSuffix = unit.symbol + suffix; + } else { + value *= scale; + } + value = type(value, precision); + var i = value.lastIndexOf("."), before, after; + if (i < 0) { + var j = exponent ? value.lastIndexOf("e") : -1; + if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j); + } else { + before = value.substring(0, i); + after = locale_decimal + value.substring(i + 1); } - } + if (!zfill && comma) before = formatGroup(before, Infinity); + var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; + if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity); + negative += prefix; + value = before + after; + return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; + }; }; - function point(x, y) { - buffer.push("M", x, ",", y, pointCircle); - } - function pointLineStart(x, y) { - buffer.push("M", x, ",", y); - stream.point = pointLine; - } - function pointLine(x, y) { - buffer.push("L", x, ",", y); - } - function lineEnd() { - stream.point = point; - } - function lineEndPolygon() { - buffer.push("Z"); - } - return stream; - } - function d3_geo_pathBufferCircle(radius) { - return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; } - var d3_geo_pathCentroid = { - point: d3_geo_pathCentroidPoint, - lineStart: d3_geo_pathCentroidLineStart, - lineEnd: d3_geo_pathCentroidLineEnd, - polygonStart: function() { - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; + var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; + var d3_format_types = d3.map({ + b: function(x) { + return x.toString(2); }, - polygonEnd: function() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; - d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; - } - }; - function d3_geo_pathCentroidPoint(x, y) { - d3_geo_centroidX0 += x; - d3_geo_centroidY0 += y; - ++d3_geo_centroidZ0; - } - function d3_geo_pathCentroidLineStart() { - var x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); + c: function(x) { + return String.fromCharCode(x); + }, + o: function(x) { + return x.toString(8); + }, + x: function(x) { + return x.toString(16); + }, + X: function(x) { + return x.toString(16).toUpperCase(); + }, + g: function(x, p) { + return x.toPrecision(p); + }, + e: function(x, p) { + return x.toExponential(p); + }, + f: function(x, p) { + return x.toFixed(p); + }, + r: function(x, p) { + return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); } + }); + function d3_format_typeDefault(x) { + return x + ""; } - function d3_geo_pathCentroidLineEnd() { - d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; - } - function d3_geo_pathCentroidRingStart() { - var x00, y00, x0, y0; - d3_geo_pathCentroid.point = function(x, y) { - d3_geo_pathCentroid.point = nextPoint; - d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); - }; - function nextPoint(x, y) { - var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); - d3_geo_centroidX1 += z * (x0 + x) / 2; - d3_geo_centroidY1 += z * (y0 + y) / 2; - d3_geo_centroidZ1 += z; - z = y0 * x - x0 * y; - d3_geo_centroidX2 += z * (x0 + x); - d3_geo_centroidY2 += z * (y0 + y); - d3_geo_centroidZ2 += z * 3; - d3_geo_pathCentroidPoint(x0 = x, y0 = y); - } - d3_geo_pathCentroid.lineEnd = function() { - nextPoint(x00, y00); - }; + var d3_time = d3.time = {}, d3_date = Date; + function d3_date_utc() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); } - function d3_geo_pathContext(context) { - var pointRadius = 4.5; - var stream = { - point: point, - lineStart: function() { - stream.point = pointLineStart; - }, - lineEnd: lineEnd, - polygonStart: function() { - stream.lineEnd = lineEndPolygon; - }, - polygonEnd: function() { - stream.lineEnd = lineEnd; - stream.point = point; - }, - pointRadius: function(_) { - pointRadius = _; - return stream; - }, - result: d3_noop - }; - function point(x, y) { - context.moveTo(x + pointRadius, y); - context.arc(x, y, pointRadius, 0, τ); - } - function pointLineStart(x, y) { - context.moveTo(x, y); - stream.point = pointLine; - } - function pointLine(x, y) { - context.lineTo(x, y); - } - function lineEnd() { - stream.point = point; + d3_date_utc.prototype = { + getDate: function() { + return this._.getUTCDate(); + }, + getDay: function() { + return this._.getUTCDay(); + }, + getFullYear: function() { + return this._.getUTCFullYear(); + }, + getHours: function() { + return this._.getUTCHours(); + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds(); + }, + getMinutes: function() { + return this._.getUTCMinutes(); + }, + getMonth: function() { + return this._.getUTCMonth(); + }, + getSeconds: function() { + return this._.getUTCSeconds(); + }, + getTime: function() { + return this._.getTime(); + }, + getTimezoneOffset: function() { + return 0; + }, + valueOf: function() { + return this._.valueOf(); + }, + setDate: function() { + d3_time_prototype.setUTCDate.apply(this._, arguments); + }, + setDay: function() { + d3_time_prototype.setUTCDay.apply(this._, arguments); + }, + setFullYear: function() { + d3_time_prototype.setUTCFullYear.apply(this._, arguments); + }, + setHours: function() { + d3_time_prototype.setUTCHours.apply(this._, arguments); + }, + setMilliseconds: function() { + d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); + }, + setMinutes: function() { + d3_time_prototype.setUTCMinutes.apply(this._, arguments); + }, + setMonth: function() { + d3_time_prototype.setUTCMonth.apply(this._, arguments); + }, + setSeconds: function() { + d3_time_prototype.setUTCSeconds.apply(this._, arguments); + }, + setTime: function() { + d3_time_prototype.setTime.apply(this._, arguments); } - function lineEndPolygon() { - context.closePath(); + }; + var d3_time_prototype = Date.prototype; + function d3_time_interval(local, step, number) { + function round(date) { + var d0 = local(date), d1 = offset(d0, 1); + return date - d0 < d1 - date ? d0 : d1; } - return stream; - } - function d3_geo_resample(project) { - var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; - function resample(stream) { - return (maxDepth ? resampleRecursive : resampleNone)(stream); + function ceil(date) { + step(date = local(new d3_date(date - 1)), 1); + return date; } - function resampleNone(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - }); + function offset(date, k) { + step(date = new d3_date(+date), k); + return date; } - function resampleRecursive(stream) { - var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; - var resample = { - point: point, - lineStart: lineStart, - lineEnd: lineEnd, - polygonStart: function() { - stream.polygonStart(); - resample.lineStart = ringStart; - }, - polygonEnd: function() { - stream.polygonEnd(); - resample.lineStart = lineStart; + function range(t0, t1, dt) { + var time = ceil(t0), times = []; + if (dt > 1) { + while (time < t1) { + if (!(number(time) % dt)) times.push(new Date(+time)); + step(time, 1); } - }; - function point(x, y) { - x = project(x, y); - stream.point(x[0], x[1]); - } - function lineStart() { - x0 = NaN; - resample.point = linePoint; - stream.lineStart(); - } - function linePoint(λ, φ) { - var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); - resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); - stream.point(x0, y0); - } - function lineEnd() { - resample.point = point; - stream.lineEnd(); - } - function ringStart() { - lineStart(); - resample.point = ringPoint; - resample.lineEnd = ringEnd; - } - function ringPoint(λ, φ) { - linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; - resample.point = linePoint; - } - function ringEnd() { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); - resample.lineEnd = lineEnd; - lineEnd(); + } else { + while (time < t1) times.push(new Date(+time)), step(time, 1); } - return resample; + return times; } - function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { - var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; - if (d2 > 4 * δ2 && depth--) { - var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; - if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { - resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); - stream.point(x2, y2); - resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); - } + function range_utc(t0, t1, dt) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = t0; + return range(utc, t1, dt); + } finally { + d3_date = Date; } } - resample.precision = function(_) { - if (!arguments.length) return Math.sqrt(δ2); - maxDepth = (δ2 = _ * _) > 0 && 16; - return resample; - }; - return resample; + local.floor = local; + local.round = round; + local.ceil = ceil; + local.offset = offset; + local.range = range; + var utc = local.utc = d3_time_interval_utc(local); + utc.floor = utc; + utc.round = d3_time_interval_utc(round); + utc.ceil = d3_time_interval_utc(ceil); + utc.offset = d3_time_interval_utc(offset); + utc.range = range_utc; + return local; } - d3.geo.path = function() { - var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; - function path(object) { - if (object) { - if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); - if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); - d3.geo.stream(object, cacheStream); + function d3_time_interval_utc(method) { + return function(date, k) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = date; + return method(utc, k)._; + } finally { + d3_date = Date; } - return contextStream.result(); - } - path.area = function(object) { - d3_geo_pathAreaSum = 0; - d3.geo.stream(object, projectStream(d3_geo_pathArea)); - return d3_geo_pathAreaSum; - }; - path.centroid = function(object) { - d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; - d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); - return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; - }; - path.bounds = function(object) { - d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); - d3.geo.stream(object, projectStream(d3_geo_pathBounds)); - return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; - }; - path.projection = function(_) { - if (!arguments.length) return projection; - projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; - return reset(); - }; - path.context = function(_) { - if (!arguments.length) return context; - contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); - if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); - return reset(); - }; - path.pointRadius = function(_) { - if (!arguments.length) return pointRadius; - pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); - return path; }; - function reset() { - cacheStream = null; - return path; - } - return path.projection(d3.geo.albersUsa()).context(null); + } + d3_time.year = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setMonth(0, 1); + return date; + }, function(date, offset) { + date.setFullYear(date.getFullYear() + offset); + }, function(date) { + return date.getFullYear(); + }); + d3_time.years = d3_time.year.range; + d3_time.years.utc = d3_time.year.utc.range; + d3_time.day = d3_time_interval(function(date) { + var day = new d3_date(2e3, 0); + day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + return day; + }, function(date, offset) { + date.setDate(date.getDate() + offset); + }, function(date) { + return date.getDate() - 1; + }); + d3_time.days = d3_time.day.range; + d3_time.days.utc = d3_time.day.utc.range; + d3_time.dayOfYear = function(date) { + var year = d3_time.year(date); + return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); }; - function d3_geo_pathProjectStream(project) { - var resample = d3_geo_resample(function(x, y) { - return project([ x * d3_degrees, y * d3_degrees ]); + [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { + i = 7 - i; + var interval = d3_time[day] = d3_time_interval(function(date) { + (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); + return date; + }, function(date, offset) { + date.setDate(date.getDate() + Math.floor(offset) * 7); + }, function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); }); - return function(stream) { - return d3_geo_projectionRadians(resample(stream)); + d3_time[day + "s"] = interval.range; + d3_time[day + "s"].utc = interval.utc.range; + d3_time[day + "OfYear"] = function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); }; - } - d3.geo.transform = function(methods) { - return { - stream: function(stream) { - var transform = new d3_geo_transform(stream); - for (var k in methods) transform[k] = methods[k]; - return transform; + }); + d3_time.week = d3_time.sunday; + d3_time.weeks = d3_time.sunday.range; + d3_time.weeks.utc = d3_time.sunday.utc.range; + d3_time.weekOfYear = d3_time.sundayOfYear; + function d3_locale_timeFormat(locale) { + var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; + function d3_time_format(template) { + var n = template.length; + function format(date) { + var string = [], i = -1, j = 0, c, p, f; + while (++i < n) { + if (template.charCodeAt(i) === 37) { + string.push(template.slice(j, i)); + if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); + if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); + string.push(c); + j = i + 1; + } + } + string.push(template.slice(j, i)); + return string.join(""); } - }; - }; - function d3_geo_transform(stream) { - this.stream = stream; - } - d3_geo_transform.prototype = { - point: function(x, y) { - this.stream.point(x, y); - }, - sphere: function() { - this.stream.sphere(); - }, - lineStart: function() { - this.stream.lineStart(); - }, - lineEnd: function() { - this.stream.lineEnd(); - }, - polygonStart: function() { - this.stream.polygonStart(); - }, - polygonEnd: function() { - this.stream.polygonEnd(); + format.parse = function(string) { + var d = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0, + Z: null + }, i = d3_time_parse(d, template, string, 0); + if (i != string.length) return null; + if ("p" in d) d.H = d.H % 12 + d.p * 12; + var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); + if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "W" in d ? 1 : 0; + date.setFullYear(d.y, 0, 1); + date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); + } else date.setFullYear(d.y, d.m, d.d); + date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L); + return localZ ? date._ : date; + }; + format.toString = function() { + return template; + }; + return format; + } + function d3_time_parse(date, template, string, j) { + var c, p, t, i = 0, n = template.length, m = string.length; + while (i < n) { + if (j >= m) return -1; + c = template.charCodeAt(i++); + if (c === 37) { + t = template.charAt(i++); + p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; + if (!p || (j = p(date, string, j)) < 0) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + return j; } - }; - function d3_geo_transformPoint(stream, point) { - return { - point: point, - sphere: function() { - stream.sphere(); + d3_time_format.utc = function(template) { + var local = d3_time_format(template); + function format(date) { + try { + d3_date = d3_date_utc; + var utc = new d3_date(); + utc._ = date; + return local(utc); + } finally { + d3_date = Date; + } + } + format.parse = function(string) { + try { + d3_date = d3_date_utc; + var date = local.parse(string); + return date && date._; + } finally { + d3_date = Date; + } + }; + format.toString = local.toString; + return format; + }; + d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; + var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); + locale_periods.forEach(function(p, i) { + d3_time_periodLookup.set(p.toLowerCase(), i); + }); + var d3_time_formats = { + a: function(d) { + return locale_shortDays[d.getDay()]; }, - lineStart: function() { - stream.lineStart(); + A: function(d) { + return locale_days[d.getDay()]; }, - lineEnd: function() { - stream.lineEnd(); + b: function(d) { + return locale_shortMonths[d.getMonth()]; }, - polygonStart: function() { - stream.polygonStart(); + B: function(d) { + return locale_months[d.getMonth()]; }, - polygonEnd: function() { - stream.polygonEnd(); + c: d3_time_format(locale_dateTime), + d: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + e: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + H: function(d, p) { + return d3_time_formatPad(d.getHours(), p, 2); + }, + I: function(d, p) { + return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); + }, + j: function(d, p) { + return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); + }, + L: function(d, p) { + return d3_time_formatPad(d.getMilliseconds(), p, 3); + }, + m: function(d, p) { + return d3_time_formatPad(d.getMonth() + 1, p, 2); + }, + M: function(d, p) { + return d3_time_formatPad(d.getMinutes(), p, 2); + }, + p: function(d) { + return locale_periods[+(d.getHours() >= 12)]; + }, + S: function(d, p) { + return d3_time_formatPad(d.getSeconds(), p, 2); + }, + U: function(d, p) { + return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); + }, + w: function(d) { + return d.getDay(); + }, + W: function(d, p) { + return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); + }, + x: d3_time_format(locale_date), + X: d3_time_format(locale_time), + y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 100, p, 2); + }, + Y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); + }, + Z: d3_time_zone, + "%": function() { + return "%"; } }; - } - d3.geo.projection = d3_geo_projection; - d3.geo.projectionMutator = d3_geo_projectionMutator; - function d3_geo_projection(project) { - return d3_geo_projectionMutator(function() { - return project; - })(); - } - function d3_geo_projectionMutator(projectAt) { - var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { - x = project(x, y); - return [ x[0] * k + δx, δy - x[1] * k ]; - }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; - function projection(point) { - point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); - return [ point[0] * k + δx, δy - point[1] * k ]; + var d3_time_parsers = { + a: d3_time_parseWeekdayAbbrev, + A: d3_time_parseWeekday, + b: d3_time_parseMonthAbbrev, + B: d3_time_parseMonth, + c: d3_time_parseLocaleFull, + d: d3_time_parseDay, + e: d3_time_parseDay, + H: d3_time_parseHour24, + I: d3_time_parseHour24, + j: d3_time_parseDayOfYear, + L: d3_time_parseMilliseconds, + m: d3_time_parseMonthNumber, + M: d3_time_parseMinutes, + p: d3_time_parseAmPm, + S: d3_time_parseSeconds, + U: d3_time_parseWeekNumberSunday, + w: d3_time_parseWeekdayNumber, + W: d3_time_parseWeekNumberMonday, + x: d3_time_parseLocaleDate, + X: d3_time_parseLocaleTime, + y: d3_time_parseYear, + Y: d3_time_parseFullYear, + Z: d3_time_parseZone, + "%": d3_time_parseLiteralPercent + }; + function d3_time_parseWeekdayAbbrev(date, string, i) { + d3_time_dayAbbrevRe.lastIndex = 0; + var n = d3_time_dayAbbrevRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; } - function invert(point) { - point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); - return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; + function d3_time_parseWeekday(date, string, i) { + d3_time_dayRe.lastIndex = 0; + var n = d3_time_dayRe.exec(string.slice(i)); + return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; } - projection.stream = function(output) { - if (stream) stream.valid = false; - stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); - stream.valid = true; - return stream; - }; - projection.clipAngle = function(_) { - if (!arguments.length) return clipAngle; - preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); - return invalidate(); - }; - projection.clipExtent = function(_) { - if (!arguments.length) return clipExtent; - clipExtent = _; - postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; - return invalidate(); - }; - projection.scale = function(_) { - if (!arguments.length) return k; - k = +_; - return reset(); - }; - projection.translate = function(_) { - if (!arguments.length) return [ x, y ]; - x = +_[0]; - y = +_[1]; - return reset(); - }; - projection.center = function(_) { - if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; - λ = _[0] % 360 * d3_radians; - φ = _[1] % 360 * d3_radians; - return reset(); - }; - projection.rotate = function(_) { - if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; - δλ = _[0] % 360 * d3_radians; - δφ = _[1] % 360 * d3_radians; - δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; - return reset(); - }; - d3.rebind(projection, projectResample, "precision"); - function reset() { - projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); - var center = project(λ, φ); - δx = x - center[0] * k; - δy = y + center[1] * k; - return invalidate(); + function d3_time_parseMonthAbbrev(date, string, i) { + d3_time_monthAbbrevRe.lastIndex = 0; + var n = d3_time_monthAbbrevRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; } - function invalidate() { - if (stream) stream.valid = false, stream = null; - return projection; + function d3_time_parseMonth(date, string, i) { + d3_time_monthRe.lastIndex = 0; + var n = d3_time_monthRe.exec(string.slice(i)); + return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; } - return function() { - project = projectAt.apply(this, arguments); - projection.invert = project.invert && invert; - return reset(); - }; + function d3_time_parseLocaleFull(date, string, i) { + return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + } + function d3_time_parseLocaleDate(date, string, i) { + return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + } + function d3_time_parseLocaleTime(date, string, i) { + return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + } + function d3_time_parseAmPm(date, string, i) { + var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase()); + return n == null ? -1 : (date.p = n, i); + } + return d3_time_format; } - function d3_geo_projectionRadians(stream) { - return d3_geo_transformPoint(stream, function(x, y) { - stream.point(x * d3_radians, y * d3_radians); - }); + var d3_time_formatPads = { + "-": "", + _: " ", + "0": "0" + }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; + function d3_time_formatPad(value, fill, width) { + var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); } - function d3_geo_equirectangular(λ, φ) { - return [ λ, φ ]; + function d3_time_formatRe(names) { + return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); } - (d3.geo.equirectangular = function() { - return d3_geo_projection(d3_geo_equirectangular); - }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; - d3.geo.rotation = function(rotate) { - rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); - function forward(coordinates) { - coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - } - forward.invert = function(coordinates) { - coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); - return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; - }; - return forward; - }; - function d3_geo_identityRotation(λ, φ) { - return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + function d3_time_formatLookup(names) { + var map = new d3_Map(), i = -1, n = names.length; + while (++i < n) map.set(names[i].toLowerCase(), i); + return map; } - d3_geo_identityRotation.invert = d3_geo_equirectangular; - function d3_geo_rotation(δλ, δφ, δγ) { - return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; + function d3_time_parseWeekdayNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 1)); + return n ? (date.w = +n[0], i + n[0].length) : -1; } - function d3_geo_forwardRotationλ(δλ) { - return function(λ, φ) { - return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; - }; + function d3_time_parseWeekNumberSunday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.U = +n[0], i + n[0].length) : -1; } - function d3_geo_rotationλ(δλ) { - var rotation = d3_geo_forwardRotationλ(δλ); - rotation.invert = d3_geo_forwardRotationλ(-δλ); - return rotation; + function d3_time_parseWeekNumberMonday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i)); + return n ? (date.W = +n[0], i + n[0].length) : -1; } - function d3_geo_rotationφγ(δφ, δγ) { - var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); - function rotation(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; - return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; - } - rotation.invert = function(λ, φ) { - var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; - return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; - }; - return rotation; + function d3_time_parseFullYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 4)); + return n ? (date.y = +n[0], i + n[0].length) : -1; } - d3.geo.circle = function() { - var origin = [ 0, 0 ], angle, precision = 6, interpolate; - function circle() { - var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; - interpolate(null, null, 1, { - point: function(x, y) { - ring.push(x = rotate(x, y)); - x[0] *= d3_degrees, x[1] *= d3_degrees; - } - }); - return { - type: "Polygon", - coordinates: [ ring ] - }; - } - circle.origin = function(x) { - if (!arguments.length) return origin; - origin = x; - return circle; - }; - circle.angle = function(x) { - if (!arguments.length) return angle; - interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); - return circle; - }; - circle.precision = function(_) { - if (!arguments.length) return precision; - interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); - return circle; - }; - return circle.angle(90); - }; - function d3_geo_circleInterpolate(radius, precision) { - var cr = Math.cos(radius), sr = Math.sin(radius); - return function(from, to, direction, listener) { - var step = direction * precision; - if (from != null) { - from = d3_geo_circleAngle(cr, from); - to = d3_geo_circleAngle(cr, to); - if (direction > 0 ? from < to : from > to) from += direction * τ; - } else { - from = radius + direction * τ; - to = radius - .5 * step; - } - for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { - listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); - } - }; + function d3_time_parseYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; } - function d3_geo_circleAngle(cr, point) { - var a = d3_geo_cartesian(point); - a[0] -= cr; - d3_geo_cartesianNormalize(a); - var angle = d3_acos(-a[1]); - return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + function d3_time_parseZone(date, string, i) { + return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, + i + 5) : -1; } - d3.geo.distance = function(a, b) { - var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; - return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); - }; - d3.geo.graticule = function() { - var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; - function graticule() { - return { - type: "MultiLineString", - coordinates: lines() - }; - } - function lines() { - return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { - return abs(x % DX) > ε; - }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { - return abs(y % DY) > ε; - }).map(y)); - } - graticule.lines = function() { - return lines().map(function(coordinates) { - return { - type: "LineString", - coordinates: coordinates - }; - }); - }; - graticule.outline = function() { - return { - type: "Polygon", - coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] - }; - }; - graticule.extent = function(_) { - if (!arguments.length) return graticule.minorExtent(); - return graticule.majorExtent(_).minorExtent(_); - }; - graticule.majorExtent = function(_) { - if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; - X0 = +_[0][0], X1 = +_[1][0]; - Y0 = +_[0][1], Y1 = +_[1][1]; - if (X0 > X1) _ = X0, X0 = X1, X1 = _; - if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; - return graticule.precision(precision); - }; - graticule.minorExtent = function(_) { - if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; - x0 = +_[0][0], x1 = +_[1][0]; - y0 = +_[0][1], y1 = +_[1][1]; - if (x0 > x1) _ = x0, x0 = x1, x1 = _; - if (y0 > y1) _ = y0, y0 = y1, y1 = _; - return graticule.precision(precision); - }; - graticule.step = function(_) { - if (!arguments.length) return graticule.minorStep(); - return graticule.majorStep(_).minorStep(_); - }; - graticule.majorStep = function(_) { - if (!arguments.length) return [ DX, DY ]; - DX = +_[0], DY = +_[1]; - return graticule; - }; - graticule.minorStep = function(_) { - if (!arguments.length) return [ dx, dy ]; - dx = +_[0], dy = +_[1]; - return graticule; - }; - graticule.precision = function(_) { - if (!arguments.length) return precision; - precision = +_; - x = d3_geo_graticuleX(y0, y1, 90); - y = d3_geo_graticuleY(x0, x1, precision); - X = d3_geo_graticuleX(Y0, Y1, 90); - Y = d3_geo_graticuleY(X0, X1, precision); - return graticule; - }; - return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); - }; - function d3_geo_graticuleX(y0, y1, dy) { - var y = d3.range(y0, y1 - ε, dy).concat(y1); - return function(x) { - return y.map(function(y) { - return [ x, y ]; - }); - }; + function d3_time_expandYear(d) { + return d + (d > 68 ? 1900 : 2e3); } - function d3_geo_graticuleY(x0, x1, dx) { - var x = d3.range(x0, x1 - ε, dx).concat(x1); - return function(y) { - return x.map(function(x) { - return [ x, y ]; - }); + function d3_time_parseMonthNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.m = n[0] - 1, i + n[0].length) : -1; + } + function d3_time_parseDay(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.d = +n[0], i + n[0].length) : -1; + } + function d3_time_parseDayOfYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.j = +n[0], i + n[0].length) : -1; + } + function d3_time_parseHour24(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.H = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMinutes(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.M = +n[0], i + n[0].length) : -1; + } + function d3_time_parseSeconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 2)); + return n ? (date.S = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMilliseconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.slice(i, i + 3)); + return n ? (date.L = +n[0], i + n[0].length) : -1; + } + function d3_time_zone(d) { + var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60; + return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + } + function d3_time_parseLiteralPercent(date, string, i) { + d3_time_percentRe.lastIndex = 0; + var n = d3_time_percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; + } + function d3_time_formatMulti(formats) { + var n = formats.length, i = -1; + while (++i < n) formats[i][0] = this(formats[i][0]); + return function(date) { + var i = 0, f = formats[i]; + while (!f[1](date)) f = formats[++i]; + return f[0](date); }; } - function d3_source(d) { - return d.source; + d3.locale = function(locale) { + return { + numberFormat: d3_locale_numberFormat(locale), + timeFormat: d3_locale_timeFormat(locale) + }; + }; + var d3_locale_enUS = d3.locale({ + decimal: ".", + thousands: ",", + grouping: [ 3 ], + currency: [ "$", "" ], + dateTime: "%a %b %e %X %Y", + date: "%m/%d/%Y", + time: "%H:%M:%S", + periods: [ "AM", "PM" ], + days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ], + shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ] + }); + d3.format = d3_locale_enUS.numberFormat; + d3.geo = {}; + function d3_adder() {} + d3_adder.prototype = { + s: 0, + t: 0, + add: function(y) { + d3_adderSum(y, this.t, d3_adderTemp); + d3_adderSum(d3_adderTemp.s, this.s, this); + if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; + }, + reset: function() { + this.s = this.t = 0; + }, + valueOf: function() { + return this.s; + } + }; + var d3_adderTemp = new d3_adder(); + function d3_adderSum(a, b, o) { + var x = o.s = a + b, bv = x - a, av = x - bv; + o.t = a - av + (b - bv); } - function d3_target(d) { - return d.target; + d3.geo.stream = function(object, listener) { + if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { + d3_geo_streamObjectType[object.type](object, listener); + } else { + d3_geo_streamGeometry(object, listener); + } + }; + function d3_geo_streamGeometry(geometry, listener) { + if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { + d3_geo_streamGeometryType[geometry.type](geometry, listener); + } } - d3.geo.greatArc = function() { - var source = d3_source, source_, target = d3_target, target_; - function greatArc() { - return { - type: "LineString", - coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] - }; + var d3_geo_streamObjectType = { + Feature: function(feature, listener) { + d3_geo_streamGeometry(feature.geometry, listener); + }, + FeatureCollection: function(object, listener) { + var features = object.features, i = -1, n = features.length; + while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); } - greatArc.distance = function() { - return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); - }; - greatArc.source = function(_) { - if (!arguments.length) return source; - source = _, source_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.target = function(_) { - if (!arguments.length) return target; - target = _, target_ = typeof _ === "function" ? null : _; - return greatArc; - }; - greatArc.precision = function() { - return arguments.length ? greatArc : 0; - }; - return greatArc; }; - d3.geo.interpolate = function(source, target) { - return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + var d3_geo_streamGeometryType = { + Sphere: function(object, listener) { + listener.sphere(); + }, + Point: function(object, listener) { + object = object.coordinates; + listener.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); + }, + LineString: function(object, listener) { + d3_geo_streamLine(object.coordinates, listener, 0); + }, + MultiLineString: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); + }, + Polygon: function(object, listener) { + d3_geo_streamPolygon(object.coordinates, listener); + }, + MultiPolygon: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); + }, + GeometryCollection: function(object, listener) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + } }; - function d3_geo_interpolate(x0, y0, x1, y1) { - var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); - var interpolate = d ? function(t) { - var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; - return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; - } : function() { - return [ x0 * d3_degrees, y0 * d3_degrees ]; - }; - interpolate.distance = d; - return interpolate; + function d3_geo_streamLine(coordinates, listener, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + listener.lineStart(); + while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); + listener.lineEnd(); } - d3.geo.length = function(object) { - d3_geo_lengthSum = 0; - d3.geo.stream(object, d3_geo_length); - return d3_geo_lengthSum; + function d3_geo_streamPolygon(coordinates, listener) { + var i = -1, n = coordinates.length; + listener.polygonStart(); + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); + listener.polygonEnd(); + } + d3.geo.area = function(object) { + d3_geo_areaSum = 0; + d3.geo.stream(object, d3_geo_area); + return d3_geo_areaSum; }; - var d3_geo_lengthSum; - var d3_geo_length = { - sphere: d3_noop, + var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); + var d3_geo_area = { + sphere: function() { + d3_geo_areaSum += 4 * π; + }, point: d3_noop, - lineStart: d3_geo_lengthLineStart, + lineStart: d3_noop, lineEnd: d3_noop, - polygonStart: d3_noop, - polygonEnd: d3_noop + polygonStart: function() { + d3_geo_areaRingSum.reset(); + d3_geo_area.lineStart = d3_geo_areaRingStart; + }, + polygonEnd: function() { + var area = 2 * d3_geo_areaRingSum; + d3_geo_areaSum += area < 0 ? 4 * π + area : area; + d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; + } }; - function d3_geo_lengthLineStart() { - var λ0, sinφ0, cosφ0; - d3_geo_length.point = function(λ, φ) { - λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); - d3_geo_length.point = nextPoint; - }; - d3_geo_length.lineEnd = function() { - d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + function d3_geo_areaRingStart() { + var λ00, φ00, λ0, cosφ0, sinφ0; + d3_geo_area.point = function(λ, φ) { + d3_geo_area.point = nextPoint; + λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), + sinφ0 = Math.sin(φ); }; function nextPoint(λ, φ) { - var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); - d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); - λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; - } - } - function d3_geo_azimuthal(scale, angle) { - function azimuthal(λ, φ) { - var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); - return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + λ *= d3_radians; + φ = φ * d3_radians / 2 + π / 4; + var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); + d3_geo_areaRingSum.add(Math.atan2(v, u)); + λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; } - azimuthal.invert = function(x, y) { - var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); - return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; + d3_geo_area.lineEnd = function() { + nextPoint(λ00, φ00); }; - return azimuthal; } - var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { - return Math.sqrt(2 / (1 + cosλcosφ)); - }, function(ρ) { - return 2 * Math.asin(ρ / 2); - }); - (d3.geo.azimuthalEqualArea = function() { - return d3_geo_projection(d3_geo_azimuthalEqualArea); - }).raw = d3_geo_azimuthalEqualArea; - var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { - var c = Math.acos(cosλcosφ); - return c && c / Math.sin(c); - }, d3_identity); - (d3.geo.azimuthalEquidistant = function() { - return d3_geo_projection(d3_geo_azimuthalEquidistant); - }).raw = d3_geo_azimuthalEquidistant; - function d3_geo_conicConformal(φ0, φ1) { - var cosφ0 = Math.cos(φ0), t = function(φ) { - return Math.tan(π / 4 + φ / 2); - }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; - if (!n) return d3_geo_mercator; - function forward(λ, φ) { - if (F > 0) { - if (φ < -halfπ + ε) φ = -halfπ + ε; - } else { - if (φ > halfπ - ε) φ = halfπ - ε; - } - var ρ = F / Math.pow(t(φ), n); - return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); - return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; - }; - return forward; + function d3_geo_cartesian(spherical) { + var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); + return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; } - (d3.geo.conicConformal = function() { - return d3_geo_conic(d3_geo_conicConformal); - }).raw = d3_geo_conicConformal; - function d3_geo_conicEquidistant(φ0, φ1) { - var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; - if (abs(n) < ε) return d3_geo_equirectangular; - function forward(λ, φ) { - var ρ = G - φ; - return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; - } - forward.invert = function(x, y) { - var ρ0_y = G - y; - return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; - }; - return forward; + function d3_geo_cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } - (d3.geo.conicEquidistant = function() { - return d3_geo_conic(d3_geo_conicEquidistant); - }).raw = d3_geo_conicEquidistant; - var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / cosλcosφ; - }, Math.atan); - (d3.geo.gnomonic = function() { - return d3_geo_projection(d3_geo_gnomonic); - }).raw = d3_geo_gnomonic; - function d3_geo_mercator(λ, φ) { - return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; + function d3_geo_cartesianCross(a, b) { + return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; } - d3_geo_mercator.invert = function(x, y) { - return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; - }; - function d3_geo_mercatorProjection(project) { - var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; - m.scale = function() { - var v = scale.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.translate = function() { - var v = translate.apply(m, arguments); - return v === m ? clipAuto ? m.clipExtent(null) : m : v; - }; - m.clipExtent = function(_) { - var v = clipExtent.apply(m, arguments); - if (v === m) { - if (clipAuto = _ == null) { - var k = π * scale(), t = translate(); - clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); - } - } else if (clipAuto) { - v = null; - } - return v; - }; - return m.clipExtent(null); + function d3_geo_cartesianAdd(a, b) { + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; } - (d3.geo.mercator = function() { - return d3_geo_mercatorProjection(d3_geo_mercator); - }).raw = d3_geo_mercator; - var d3_geo_orthographic = d3_geo_azimuthal(function() { - return 1; - }, Math.asin); - (d3.geo.orthographic = function() { - return d3_geo_projection(d3_geo_orthographic); - }).raw = d3_geo_orthographic; - var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { - return 1 / (1 + cosλcosφ); - }, function(ρ) { - return 2 * Math.atan(ρ); - }); - (d3.geo.stereographic = function() { - return d3_geo_projection(d3_geo_stereographic); - }).raw = d3_geo_stereographic; - function d3_geo_transverseMercator(λ, φ) { - return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; + function d3_geo_cartesianScale(vector, k) { + return [ vector[0] * k, vector[1] * k, vector[2] * k ]; } - d3_geo_transverseMercator.invert = function(x, y) { - return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; - }; - (d3.geo.transverseMercator = function() { - var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; - projection.center = function(_) { - return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); - }; - projection.rotate = function(_) { - return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), - [ _[0], _[1], _[2] - 90 ]); - }; - return rotate([ 0, 0, 90 ]); - }).raw = d3_geo_transverseMercator; - d3.geom = {}; - function d3_geom_pointX(d) { - return d[0]; + function d3_geo_cartesianNormalize(d) { + var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l; + d[1] /= l; + d[2] /= l; } - function d3_geom_pointY(d) { - return d[1]; + function d3_geo_spherical(cartesian) { + return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; } - d3.geom.hull = function(vertices) { - var x = d3_geom_pointX, y = d3_geom_pointY; - if (arguments.length) return hull(vertices); - function hull(data) { - if (data.length < 3) return []; - var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; - for (i = 0; i < n; i++) { - points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + function d3_geo_sphericalEqual(a, b) { + return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + } + d3.geo.bounds = function() { + var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; + var bound = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + bound.point = ringPoint; + bound.lineStart = ringStart; + bound.lineEnd = ringEnd; + dλSum = 0; + d3_geo_area.polygonStart(); + }, + polygonEnd: function() { + d3_geo_area.polygonEnd(); + bound.point = point; + bound.lineStart = lineStart; + bound.lineEnd = lineEnd; + if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; + range[0] = λ0, range[1] = λ1; } - points.sort(d3_geom_hullOrder); - for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); - var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); - var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; - for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); - for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); - return polygon; - } - hull.x = function(_) { - return arguments.length ? (x = _, hull) : x; }; - hull.y = function(_) { - return arguments.length ? (y = _, hull) : y; - }; - return hull; - }; - function d3_geom_hullUpper(points) { - var n = points.length, hull = [ 0, 1 ], hs = 2; - for (var i = 2; i < n; i++) { - while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; - hull[hs++] = i; + function point(λ, φ) { + ranges.push(range = [ λ0 = λ, λ1 = λ ]); + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; } - return hull.slice(0, hs); - } - function d3_geom_hullOrder(a, b) { - return a[0] - b[0] || a[1] - b[1]; - } - d3.geom.polygon = function(coordinates) { - d3_subclass(coordinates, d3_geom_polygonPrototype); - return coordinates; - }; - var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; - d3_geom_polygonPrototype.area = function() { - var i = -1, n = this.length, a, b = this[n - 1], area = 0; - while (++i < n) { - a = b; - b = this[i]; - area += a[1] * b[0] - a[0] * b[1]; + function linePoint(λ, φ) { + var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); + if (p0) { + var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); + d3_geo_cartesianNormalize(inflection); + inflection = d3_geo_spherical(inflection); + var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; + if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = inflection[1] * d3_degrees; + if (φi > φ1) φ1 = φi; + } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = -inflection[1] * d3_degrees; + if (φi < φ0) φ0 = φi; + } else { + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + if (antimeridian) { + if (λ < λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } else { + if (λ1 >= λ0) { + if (λ < λ0) λ0 = λ; + if (λ > λ1) λ1 = λ; + } else { + if (λ > λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } + } + } else { + point(λ, φ); + } + p0 = p, λ_ = λ; } - return area * .5; - }; - d3_geom_polygonPrototype.centroid = function(k) { - var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; - if (!arguments.length) k = -1 / (6 * this.area()); - while (++i < n) { - a = b; - b = this[i]; - c = a[0] * b[1] - b[0] * a[1]; - x += (a[0] + b[0]) * c; - y += (a[1] + b[1]) * c; + function lineStart() { + bound.point = linePoint; } - return [ x * k, y * k ]; - }; - d3_geom_polygonPrototype.clip = function(subject) { - var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; - while (++i < n) { - input = subject.slice(); - subject.length = 0; - b = this[i]; - c = input[(m = input.length - closed) - 1]; - j = -1; - while (++j < m) { - d = input[j]; - if (d3_geom_polygonInside(d, a, b)) { - if (!d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); + function lineEnd() { + range[0] = λ0, range[1] = λ1; + bound.point = point; + p0 = null; + } + function ringPoint(λ, φ) { + if (p0) { + var dλ = λ - λ_; + dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; + } else λ__ = λ, φ__ = φ; + d3_geo_area.point(λ, φ); + linePoint(λ, φ); + } + function ringStart() { + d3_geo_area.lineStart(); + } + function ringEnd() { + ringPoint(λ__, φ__); + d3_geo_area.lineEnd(); + if (abs(dλSum) > ε) λ0 = -(λ1 = 180); + range[0] = λ0, range[1] = λ1; + p0 = null; + } + function angle(λ0, λ1) { + return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + } + function compareRanges(a, b) { + return a[0] - b[0]; + } + function withinRange(x, range) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + return function(feature) { + φ1 = λ1 = -(λ0 = φ0 = Infinity); + ranges = []; + d3.geo.stream(feature, bound); + var n = ranges.length; + if (n) { + ranges.sort(compareRanges); + for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { + b = ranges[i]; + if (withinRange(b[0], a) || withinRange(b[1], a)) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); } - subject.push(d); - } else if (d3_geom_polygonInside(c, a, b)) { - subject.push(d3_geom_polygonIntersect(c, d, a, b)); } - c = d; + var best = -Infinity, dλ; + for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { + b = merged[i]; + if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + } } - if (closed) subject.push(subject[0]); - a = b; + ranges = range = null; + return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }; + }(); + d3.geo.centroid = function(object) { + d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, d3_geo_centroid); + var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; + if (m < ε2) { + x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; + if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; + m = x * x + y * y + z * z; + if (m < ε2) return [ NaN, NaN ]; } - return subject; + return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; }; - function d3_geom_polygonInside(p, a, b) { - return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); - } - function d3_geom_polygonIntersect(c, d, a, b) { - var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); - return [ x1 + ua * x21, y1 + ua * y21 ]; - } - function d3_geom_polygonClosed(coordinates) { - var a = coordinates[0], b = coordinates[coordinates.length - 1]; - return !(a[0] - b[0] || a[1] - b[1]); + var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; + var d3_geo_centroid = { + sphere: d3_noop, + point: d3_geo_centroidPoint, + lineStart: d3_geo_centroidLineStart, + lineEnd: d3_geo_centroidLineEnd, + polygonStart: function() { + d3_geo_centroid.lineStart = d3_geo_centroidRingStart; + }, + polygonEnd: function() { + d3_geo_centroid.lineStart = d3_geo_centroidLineStart; + } + }; + function d3_geo_centroidPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); } - var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; - function d3_geom_voronoiBeach() { - d3_geom_voronoiRedBlackNode(this); - this.edge = this.site = this.circle = null; + function d3_geo_centroidPointXYZ(x, y, z) { + ++d3_geo_centroidW0; + d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; + d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; + d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; } - function d3_geom_voronoiCreateBeach(site) { - var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); - beach.site = site; - return beach; + function d3_geo_centroidLineStart() { + var x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroid.point = nextPoint; + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } } - function d3_geom_voronoiDetachBeach(beach) { - d3_geom_voronoiDetachCircle(beach); - d3_geom_voronoiBeaches.remove(beach); - d3_geom_voronoiBeachPool.push(beach); - d3_geom_voronoiRedBlackNode(beach); + function d3_geo_centroidLineEnd() { + d3_geo_centroid.point = d3_geo_centroidPoint; } - function d3_geom_voronoiRemoveBeach(beach) { - var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { - x: x, - y: y - }, previous = beach.P, next = beach.N, disappearing = [ beach ]; - d3_geom_voronoiDetachBeach(beach); - var lArc = previous; - while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { - previous = lArc.P; - disappearing.unshift(lArc); - d3_geom_voronoiDetachBeach(lArc); - lArc = previous; - } - disappearing.unshift(lArc); - d3_geom_voronoiDetachCircle(lArc); - var rArc = next; - while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { - next = rArc.N; - disappearing.push(rArc); - d3_geom_voronoiDetachBeach(rArc); - rArc = next; + function d3_geo_centroidRingStart() { + var λ00, φ00, x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ00 = λ, φ00 = φ; + d3_geo_centroid.point = nextPoint; + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + d3_geo_centroid.lineEnd = function() { + nextPoint(λ00, φ00); + d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; + d3_geo_centroid.point = d3_geo_centroidPoint; + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); + d3_geo_centroidX2 += v * cx; + d3_geo_centroidY2 += v * cy; + d3_geo_centroidZ2 += v * cz; + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); } - disappearing.push(rArc); - d3_geom_voronoiDetachCircle(rArc); - var nArcs = disappearing.length, iArc; - for (iArc = 1; iArc < nArcs; ++iArc) { - rArc = disappearing[iArc]; - lArc = disappearing[iArc - 1]; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + function d3_geo_compose(a, b) { + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); } - lArc = disappearing[0]; - rArc = disappearing[nArcs - 1]; - rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + return compose; } - function d3_geom_voronoiAddBeach(site) { - var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; - while (node) { - dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; - if (dxl > ε) node = node.L; else { - dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); - if (dxr > ε) { - if (!node.R) { - lArc = node; - break; + function d3_true() { + return true; + } + function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { + var subject = [], clip = []; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n]; + if (d3_geo_sphericalEqual(p0, p1)) { + listener.lineStart(); + for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); + listener.lineEnd(); + return; + } + var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); + a.o = b; + subject.push(a); + clip.push(b); + a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); + b = new d3_geo_clipPolygonIntersection(p1, null, a, true); + a.o = b; + subject.push(a); + clip.push(b); + }); + clip.sort(compare); + d3_geo_clipPolygonLinkCircular(subject); + d3_geo_clipPolygonLinkCircular(clip); + if (!subject.length) return; + for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { + clip[i].e = entry = !entry; + } + var start = subject[0], points, point; + while (1) { + var current = start, isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + listener.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, listener); } - node = node.R; + current = current.n; } else { - if (dxl > -ε) { - lArc = node.P; - rArc = node; - } else if (dxr > -ε) { - lArc = node; - rArc = node.N; + if (isSubject) { + points = current.p.z; + for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); } else { - lArc = rArc = node; + interpolate(current.x, current.p.x, -1, listener); } - break; + current = current.p; } - } - } - var newArc = d3_geom_voronoiCreateBeach(site); - d3_geom_voronoiBeaches.insert(lArc, newArc); - if (!lArc && !rArc) return; - if (lArc === rArc) { - d3_geom_voronoiDetachCircle(lArc); - rArc = d3_geom_voronoiCreateBeach(lArc.site); - d3_geom_voronoiBeaches.insert(newArc, rArc); - newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - return; - } - if (!rArc) { - newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); - return; + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + listener.lineEnd(); } - d3_geom_voronoiDetachCircle(lArc); - d3_geom_voronoiDetachCircle(rArc); - var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { - x: (cy * hb - by * hc) / d + ax, - y: (bx * hc - cx * hb) / d + ay - }; - d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); - newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); - rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); - d3_geom_voronoiAttachCircle(lArc); - d3_geom_voronoiAttachCircle(rArc); - } - function d3_geom_voronoiLeftBreakPoint(arc, directrix) { - var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; - if (!pby2) return rfocx; - var lArc = arc.P; - if (!lArc) return -Infinity; - site = lArc.site; - var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; - if (!plby2) return lfocx; - var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; - if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; - return (rfocx + lfocx) / 2; } - function d3_geom_voronoiRightBreakPoint(arc, directrix) { - var rArc = arc.N; - if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); - var site = arc.site; - return site.y === directrix ? site.x : Infinity; + function d3_geo_clipPolygonLinkCircular(array) { + if (!(n = array.length)) return; + var n, i = 0, a = array[0], b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; } - function d3_geom_voronoiCell(site) { - this.site = site; - this.edges = []; + function d3_geo_clipPolygonIntersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; + this.e = entry; + this.v = false; + this.n = this.p = null; } - d3_geom_voronoiCell.prototype.prepare = function() { - var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; - while (iHalfEdge--) { - edge = halfEdges[iHalfEdge].edge; - if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); - } - halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); - return halfEdges.length; - }; - function d3_geom_voronoiCloseCells(extent) { - var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; - while (iCell--) { - cell = cells[iCell]; - if (!cell || !cell.prepare()) continue; - halfEdges = cell.edges; - nHalfEdges = halfEdges.length; - iHalfEdge = 0; - while (iHalfEdge < nHalfEdges) { - end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; - start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; - if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { - halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { - x: x0, - y: abs(x2 - x0) < ε ? y2 : y1 - } : abs(y3 - y1) < ε && x1 - x3 > ε ? { - x: abs(y2 - y1) < ε ? x2 : x1, - y: y1 - } : abs(x3 - x1) < ε && y3 - y0 > ε ? { - x: x1, - y: abs(x2 - x1) < ε ? y2 : y0 - } : abs(y3 - y0) < ε && x3 - x0 > ε ? { - x: abs(y2 - y0) < ε ? x2 : x0, - y: y0 - } : null), cell.site, null)); - ++nHalfEdges; + function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { + return function(rotate, listener) { + var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3.merge(segments); + var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); + if (segments.length) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); + } else if (clipStartInside) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (polygonStarted) listener.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + listener.polygonStart(); + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + listener.polygonEnd(); } + }; + function point(λ, φ) { + var point = rotate(λ, φ); + if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); } - } + function pointLine(λ, φ) { + var point = rotate(λ, φ); + line.point(point[0], point[1]); + } + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + var segments; + var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; + function pointRing(λ, φ) { + ring.push([ λ, φ ]); + var point = rotate(λ, φ); + ringListener.point(point[0], point[1]); + } + function ringStart() { + ringListener.lineStart(); + ring = []; + } + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringListener.lineEnd(); + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; + ring.pop(); + polygon.push(ring); + ring = null; + if (!n) return; + if (clean & 1) { + segment = ringSegments[0]; + var n = segment.length - 1, i = -1, point; + if (n > 0) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + while (++i < n) listener.point((point = segment[i])[0], point[1]); + listener.lineEnd(); + } + return; + } + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + } + return clip; + }; } - function d3_geom_voronoiHalfEdgeOrder(a, b) { - return b.angle - a.angle; + function d3_geo_clipSegmentLength1(segment) { + return segment.length > 1; } - function d3_geom_voronoiCircle() { - d3_geom_voronoiRedBlackNode(this); - this.x = this.y = this.arc = this.site = this.cy = null; + function d3_geo_clipBufferListener() { + var lines = [], line; + return { + lineStart: function() { + lines.push(line = []); + }, + point: function(λ, φ) { + line.push([ λ, φ ]); + }, + lineEnd: d3_noop, + buffer: function() { + var buffer = lines; + lines = []; + line = null; + return buffer; + }, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + } + }; } - function d3_geom_voronoiAttachCircle(arc) { - var lArc = arc.P, rArc = arc.N; - if (!lArc || !rArc) return; - var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; - if (lSite === rSite) return; - var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; - var d = 2 * (ax * cy - ay * cx); - if (d >= -ε2) return; - var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; - var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); - circle.arc = arc; - circle.site = cSite; - circle.x = x + bx; - circle.y = cy + Math.sqrt(x * x + y * y); - circle.cy = cy; - arc.circle = circle; - var before = null, node = d3_geom_voronoiCircles._; - while (node) { - if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { - if (node.L) node = node.L; else { - before = node.P; - break; - } - } else { - if (node.R) node = node.R; else { - before = node; - break; + function d3_geo_clipSort(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]); + } + var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]); + function d3_geo_clipAntimeridianLine(listener) { + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; + return { + lineStart: function() { + listener.lineStart(); + clean = 1; + }, + point: function(λ1, φ1) { + var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0); + if (abs(dλ - π) < ε) { + listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + listener.point(λ1, φ0); + clean = 0; + } else if (sλ0 !== sλ1 && dλ >= π) { + if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; + if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; + φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + clean = 0; } + listener.point(λ0 = λ1, φ0 = φ1); + sλ0 = sλ1; + }, + lineEnd: function() { + listener.lineEnd(); + λ0 = φ0 = NaN; + }, + clean: function() { + return 2 - clean; } - } - d3_geom_voronoiCircles.insert(before, circle); - if (!before) d3_geom_voronoiFirstCircle = circle; + }; } - function d3_geom_voronoiDetachCircle(arc) { - var circle = arc.circle; - if (circle) { - if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; - d3_geom_voronoiCircles.remove(circle); - d3_geom_voronoiCirclePool.push(circle); - d3_geom_voronoiRedBlackNode(circle); - arc.circle = null; - } + function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { + var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); + return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; } - function d3_geom_voronoiClipEdges(extent) { - var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; - while (i--) { - e = edges[i]; - if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { - e.a = e.b = null; - edges.splice(i, 1); - } + function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { + var φ; + if (from == null) { + φ = direction * halfπ; + listener.point(-π, φ); + listener.point(0, φ); + listener.point(π, φ); + listener.point(π, 0); + listener.point(π, -φ); + listener.point(0, -φ); + listener.point(-π, -φ); + listener.point(-π, 0); + listener.point(-π, φ); + } else if (abs(from[0] - to[0]) > ε) { + var s = from[0] < to[0] ? π : -π; + φ = direction * s / 2; + listener.point(-s, φ); + listener.point(0, φ); + listener.point(s, φ); + } else { + listener.point(to[0], to[1]); } } - function d3_geom_voronoiConnectEdge(edge, extent) { - var vb = edge.b; - if (vb) return true; - var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; - if (ry === ly) { - if (fx < x0 || fx >= x1) return; - if (lx > rx) { - if (!va) va = { - x: fx, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: fx, - y: y1 - }; - } else { - if (!va) va = { - x: fx, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: fx, - y: y0 - }; - } - } else { - fm = (lx - rx) / (ry - ly); - fb = fy - fm * fx; - if (fm < -1 || fm > 1) { - if (lx > rx) { - if (!va) va = { - x: (y0 - fb) / fm, - y: y0 - }; else if (va.y >= y1) return; - vb = { - x: (y1 - fb) / fm, - y: y1 - }; - } else { - if (!va) va = { - x: (y1 - fb) / fm, - y: y1 - }; else if (va.y < y0) return; - vb = { - x: (y0 - fb) / fm, - y: y0 - }; - } - } else { - if (ly < ry) { - if (!va) va = { - x: x0, - y: fm * x0 + fb - }; else if (va.x >= x1) return; - vb = { - x: x1, - y: fm * x1 + fb - }; - } else { - if (!va) va = { - x: x1, - y: fm * x1 + fb - }; else if (va.x < x0) return; - vb = { - x: x0, - y: fm * x0 + fb - }; + function d3_geo_pointInPolygon(point, polygon) { + var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; + d3_geo_areaRingSum.reset(); + for (var i = 0, n = polygon.length; i < n; ++i) { + var ring = polygon[i], m = ring.length; + if (!m) continue; + var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; + while (true) { + if (j === m) j = 0; + point = ring[j]; + var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ; + d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); + polarAngle += antimeridian ? dλ + sdλ * τ : dλ; + if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { + var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); + d3_geo_cartesianNormalize(arc); + var intersection = d3_geo_cartesianCross(meridianNormal, arc); + d3_geo_cartesianNormalize(intersection); + var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); + if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { + winding += antimeridian ^ dλ >= 0 ? 1 : -1; + } } + if (!j++) break; + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; } } - edge.a = va; - edge.b = vb; - return true; - } - function d3_geom_voronoiEdge(lSite, rSite) { - this.l = lSite; - this.r = rSite; - this.a = this.b = null; - } - function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, rSite); - d3_geom_voronoiEdges.push(edge); - if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); - if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); - d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); - d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); - return edge; - } - function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { - var edge = new d3_geom_voronoiEdge(lSite, null); - edge.a = va; - edge.b = vb; - d3_geom_voronoiEdges.push(edge); - return edge; + return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; } - function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { - if (!edge.a && !edge.b) { - edge.a = vertex; - edge.l = lSite; - edge.r = rSite; - } else if (edge.l === rSite) { - edge.b = vertex; - } else { - edge.a = vertex; + function d3_geo_clipCircle(radius) { + var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); + return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]); + function visible(λ, φ) { + return Math.cos(λ) * Math.cos(φ) > cr; } - } - function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { - var va = edge.a, vb = edge.b; - this.edge = edge; - this.site = lSite; - this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); - } - d3_geom_voronoiHalfEdge.prototype = { - start: function() { - return this.edge.l === this.site ? this.edge.a : this.edge.b; - }, - end: function() { - return this.edge.l === this.site ? this.edge.b : this.edge.a; + function clipLine(listener) { + var point0, c0, v0, v00, clean; + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(λ, φ) { + var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0; + if (!point0 && (v00 = v0 = v)) listener.lineStart(); + if (v !== v0) { + point2 = intersect(point0, point1); + if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { + point1[0] += ε; + point1[1] += ε; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + listener.lineStart(); + point2 = intersect(point1, point0); + listener.point(point2[0], point2[1]); + } else { + point2 = intersect(point0, point1); + listener.point(point2[0], point2[1]); + listener.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + } else { + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { + listener.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) listener.lineEnd(); + point0 = null; + }, + clean: function() { + return clean | (v00 && v0) << 1; + } + }; + } + function intersect(a, b, two) { + var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); + var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; + if (!determinant) return !two && a; + var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); + d3_geo_cartesianAdd(A, B); + var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); + if (t2 < 0) return; + var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); + d3_geo_cartesianAdd(q, A); + q = d3_geo_spherical(q); + if (!two) return q; + var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; + if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; + var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε; + if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; + if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) { + var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); + d3_geo_cartesianAdd(q1, A); + return [ q, d3_geo_spherical(q1) ]; + } + } + function code(λ, φ) { + var r = smallRadius ? radius : π - radius, code = 0; + if (λ < -r) code |= 1; else if (λ > r) code |= 2; + if (φ < -r) code |= 4; else if (φ > r) code |= 8; + return code; } - }; - function d3_geom_voronoiRedBlackTree() { - this._ = null; } - function d3_geom_voronoiRedBlackNode(node) { - node.U = node.C = node.L = node.R = node.P = node.N = null; + function d3_geom_clipLine(x0, y0, x1, y1) { + return function(line) { + var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + if (t0 > 0) line.a = { + x: ax + t0 * dx, + y: ay + t0 * dy + }; + if (t1 < 1) line.b = { + x: ax + t1 * dx, + y: ay + t1 * dy + }; + return line; + }; } - d3_geom_voronoiRedBlackTree.prototype = { - insert: function(after, node) { - var parent, grandpa, uncle; - if (after) { - node.P = after; - node.N = after.N; - if (after.N) after.N.P = node; - after.N = node; - if (after.R) { - after = after.R; - while (after.L) after = after.L; - after.L = node; - } else { - after.R = node; - } - parent = after; - } else if (this._) { - after = d3_geom_voronoiRedBlackFirst(this._); - node.P = null; - node.N = after; - after.P = after.L = node; - parent = after; - } else { - node.P = node.N = null; - this._ = node; - parent = null; + var d3_geo_clipExtentMAX = 1e9; + d3.geo.clipExtent = function() { + var x0, y0, x1, y1, stream, clip, clipExtent = { + stream: function(output) { + if (stream) stream.valid = false; + stream = clip(output); + stream.valid = true; + return stream; + }, + extent: function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); + if (stream) stream.valid = false, stream = null; + return clipExtent; } - node.L = node.R = null; - node.U = parent; - node.C = true; - after = node; - while (parent && parent.C) { - grandpa = parent.U; - if (parent === grandpa.L) { - uncle = grandpa.R; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.R) { - d3_geom_voronoiRedBlackRotateLeft(this, parent); - after = parent; - parent = after.U; + }; + return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); + }; + function d3_geo_clipExtent(x0, y0, x1, y1) { + return function(listener) { + var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + listener = bufferListener; + segments = []; + polygon = []; + clean = true; + }, + polygonEnd: function() { + listener = listener_; + segments = d3.merge(segments); + var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; + if (inside || visible) { + listener.polygonStart(); + if (inside) { + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateRight(this, grandpa); + if (visible) { + d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + } + listener.polygonEnd(); } - } else { - uncle = grandpa.L; - if (uncle && uncle.C) { - parent.C = uncle.C = false; - grandpa.C = true; - after = grandpa; - } else { - if (after === parent.L) { - d3_geom_voronoiRedBlackRotateRight(this, parent); - after = parent; - parent = after.U; + segments = polygon = ring = null; + } + }; + function insidePolygon(p) { + var wn = 0, n = polygon.length, y = p[1]; + for (var i = 0; i < n; ++i) { + for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { + b = v[j]; + if (a[1] <= y) { + if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; + } else { + if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; } - parent.C = false; - grandpa.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, grandpa); + a = b; } } - parent = after.U; - } - this._.C = false; - }, - remove: function(node) { - if (node.N) node.N.P = node.P; - if (node.P) node.P.N = node.N; - node.N = node.P = null; - var parent = node.U, sibling, left = node.L, right = node.R, next, red; - if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); - if (parent) { - if (parent.L === node) parent.L = next; else parent.R = next; - } else { - this._ = next; + return wn !== 0; } - if (left && right) { - red = next.C; - next.C = node.C; - next.L = left; - left.U = next; - if (next !== right) { - parent = next.U; - next.U = node.U; - node = next.R; - parent.L = node; - next.R = right; - right.U = next; + function interpolate(from, to, direction, listener) { + var a = 0, a1 = 0; + if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { + do { + listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + } while ((a = (a + direction + 4) % 4) !== a1); } else { - next.U = parent; - parent = next; - node = next.R; + listener.point(to[0], to[1]); } - } else { - red = node.C; - node = next; } - if (node) node.U = parent; - if (red) return; - if (node && node.C) { - node.C = false; - return; + function pointVisible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; } - do { - if (node === this._) break; - if (node === parent.L) { - sibling = parent.R; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - sibling = parent.R; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.R || !sibling.R.C) { - sibling.L.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateRight(this, sibling); - sibling = parent.R; - } - sibling.C = parent.C; - parent.C = sibling.R.C = false; - d3_geom_voronoiRedBlackRotateLeft(this, parent); - node = this._; - break; + function point(x, y) { + if (pointVisible(x, y)) listener.point(x, y); + } + var x__, y__, v__, x_, y_, v_, first, clean; + function lineStart() { + clip.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferListener.rejoin(); + segments.push(bufferListener.buffer()); + } + clip.point = point; + if (v_) listener.lineEnd(); + } + function linePoint(x, y) { + x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); + y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); + var v = pointVisible(x, y); + if (polygon) ring.push([ x, y ]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + listener.lineStart(); + listener.point(x, y); } } else { - sibling = parent.L; - if (sibling.C) { - sibling.C = false; - parent.C = true; - d3_geom_voronoiRedBlackRotateRight(this, parent); - sibling = parent.L; - } - if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { - if (!sibling.L || !sibling.L.C) { - sibling.R.C = false; - sibling.C = true; - d3_geom_voronoiRedBlackRotateLeft(this, sibling); - sibling = parent.L; + if (v && v_) listener.point(x, y); else { + var l = { + a: { + x: x_, + y: y_ + }, + b: { + x: x, + y: y + } + }; + if (clipLine(l)) { + if (!v_) { + listener.lineStart(); + listener.point(l.a.x, l.a.y); + } + listener.point(l.b.x, l.b.y); + if (!v) listener.lineEnd(); + clean = false; + } else if (v) { + listener.lineStart(); + listener.point(x, y); + clean = false; } - sibling.C = parent.C; - parent.C = sibling.L.C = false; - d3_geom_voronoiRedBlackRotateRight(this, parent); - node = this._; - break; } } - sibling.C = true; - node = parent; - parent = parent.U; - } while (!node.C); - if (node) node.C = false; + x_ = x, y_ = y, v_ = v; + } + return clip; + }; + function corner(p, direction) { + return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; } - }; - function d3_geom_voronoiRedBlackRotateLeft(tree, node) { - var p = node, q = node.R, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; + function compare(a, b) { + return comparePoints(a.x, b.x); } - q.U = parent; - p.U = q; - p.R = q.L; - if (p.R) p.R.U = p; - q.L = p; - } - function d3_geom_voronoiRedBlackRotateRight(tree, node) { - var p = node, q = node.L, parent = p.U; - if (parent) { - if (parent.L === p) parent.L = q; else parent.R = q; - } else { - tree._ = q; + function comparePoints(a, b) { + var ca = corner(a, 1), cb = corner(b, 1); + return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; } - q.U = parent; - p.U = q; - p.L = q.R; - if (p.L) p.L.U = p; - q.R = p; - } - function d3_geom_voronoiRedBlackFirst(node) { - while (node.L) node = node.L; - return node; } - function d3_geom_voronoi(sites, bbox) { - var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; - d3_geom_voronoiEdges = []; - d3_geom_voronoiCells = new Array(sites.length); - d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); - d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); - while (true) { - circle = d3_geom_voronoiFirstCircle; - if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { - if (site.x !== x0 || site.y !== y0) { - d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); - d3_geom_voronoiAddBeach(site); - x0 = site.x, y0 = site.y; - } - site = sites.pop(); - } else if (circle) { - d3_geom_voronoiRemoveBeach(circle.arc); - } else { - break; - } - } - if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); - var diagram = { - cells: d3_geom_voronoiCells, - edges: d3_geom_voronoiEdges + function d3_geo_conic(projectAt) { + var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); + p.parallels = function(_) { + if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ]; + return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180); }; - d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; - return diagram; - } - function d3_geom_voronoiVertexOrder(a, b) { - return b.y - a.y || b.x - a.x; + return p; } - d3.geom.voronoi = function(points) { - var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; - if (points) return voronoi(points); - function voronoi(data) { - var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; - d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { - var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { - var s = e.start(); - return [ s.x, s.y ]; - }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; - polygon.point = data[i]; - }); - return polygons; - } - function sites(data) { - return data.map(function(d, i) { - return { - x: Math.round(fx(d, i) / ε) * ε, - y: Math.round(fy(d, i) / ε) * ε, - i: i - }; - }); + function d3_geo_conicEqualArea(φ0, φ1) { + var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n; + function forward(λ, φ) { + var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; + return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ]; } - voronoi.links = function(data) { - return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { - return edge.l && edge.r; - }).map(function(edge) { - return { - source: data[edge.l.i], - target: data[edge.r.i] - }; - }); - }; - voronoi.triangles = function(data) { - var triangles = []; - d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { - var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; - while (++j < m) { - e0 = e1; - s0 = s1; - e1 = edges[j].edge; - s1 = e1.l === site ? e1.r : e1.l; - if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { - triangles.push([ data[i], data[s0.i], data[s1.i] ]); - } - } - }); - return triangles; - }; - voronoi.x = function(_) { - return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; - }; - voronoi.y = function(_) { - return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; - }; - voronoi.clipExtent = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; - clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; - return voronoi; - }; - voronoi.size = function(_) { - if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; - return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + forward.invert = function(x, y) { + var ρ0_y = ρ0 - y; + return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ]; }; - return voronoi; - }; - var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; - function d3_geom_voronoiTriangleArea(a, b, c) { - return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); + return forward; } - d3.geom.delaunay = function(vertices) { - return d3.geom.voronoi().triangles(vertices); + (d3.geo.conicEqualArea = function() { + return d3_geo_conic(d3_geo_conicEqualArea); + }).raw = d3_geo_conicEqualArea; + d3.geo.albers = function() { + return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); }; - d3.geom.quadtree = function(points, x1, y1, x2, y2) { - var x = d3_geom_pointX, y = d3_geom_pointY, compat; - if (compat = arguments.length) { - x = d3_geom_quadtreeCompatX; - y = d3_geom_quadtreeCompatY; - if (compat === 3) { - y2 = y1; - x2 = x1; - y1 = x1 = 0; + d3.geo.albersUsa = function() { + var lower48 = d3.geo.albers(); + var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); + var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); + var point, pointStream = { + point: function(x, y) { + point = [ x, y ]; } - return quadtree(points); + }, lower48Point, alaskaPoint, hawaiiPoint; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + point = null; + (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); + return point; } - function quadtree(data) { - var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; - if (x1 != null) { - x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; - } else { - x2_ = y2_ = -(x1_ = y1_ = Infinity); - xs = [], ys = []; - n = data.length; - if (compat) for (i = 0; i < n; ++i) { - d = data[i]; - if (d.x < x1_) x1_ = d.x; - if (d.y < y1_) y1_ = d.y; - if (d.x > x2_) x2_ = d.x; - if (d.y > y2_) y2_ = d.y; - xs.push(d.x); - ys.push(d.y); - } else for (i = 0; i < n; ++i) { - var x_ = +fx(d = data[i], i), y_ = +fy(d, i); - if (x_ < x1_) x1_ = x_; - if (y_ < y1_) y1_ = y_; - if (x_ > x2_) x2_ = x_; - if (y_ > y2_) y2_ = y_; - xs.push(x_); - ys.push(y_); - } - } - var dx = x2_ - x1_, dy = y2_ - y1_; - if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; - function insert(n, d, x, y, x1, y1, x2, y2) { - if (isNaN(x) || isNaN(y)) return; - if (n.leaf) { - var nx = n.x, ny = n.y; - if (nx != null) { - if (abs(nx - x) + abs(ny - y) < .01) { - insertChild(n, d, x, y, x1, y1, x2, y2); - } else { - var nPoint = n.point; - n.x = n.y = n.point = null; - insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); - insertChild(n, d, x, y, x1, y1, x2, y2); - } - } else { - n.x = x, n.y = y, n.point = d; - } - } else { - insertChild(n, d, x, y, x1, y1, x2, y2); + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; + return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); + }; + albersUsa.stream = function(stream) { + var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); + return { + point: function(x, y) { + lower48Stream.point(x, y); + alaskaStream.point(x, y); + hawaiiStream.point(x, y); + }, + sphere: function() { + lower48Stream.sphere(); + alaskaStream.sphere(); + hawaiiStream.sphere(); + }, + lineStart: function() { + lower48Stream.lineStart(); + alaskaStream.lineStart(); + hawaiiStream.lineStart(); + }, + lineEnd: function() { + lower48Stream.lineEnd(); + alaskaStream.lineEnd(); + hawaiiStream.lineEnd(); + }, + polygonStart: function() { + lower48Stream.polygonStart(); + alaskaStream.polygonStart(); + hawaiiStream.polygonStart(); + }, + polygonEnd: function() { + lower48Stream.polygonEnd(); + alaskaStream.polygonEnd(); + hawaiiStream.polygonEnd(); } - } - function insertChild(n, d, x, y, x1, y1, x2, y2) { - var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; - n.leaf = false; - n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); - if (right) x1 = xm; else x2 = xm; - if (below) y1 = ym; else y2 = ym; - insert(n, d, x, y, x1, y1, x2, y2); - } - var root = d3_geom_quadtreeNode(); - root.add = function(d) { - insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); - }; - root.visit = function(f) { - d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); - }; - root.find = function(point) { - return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); }; - i = -1; - if (x1 == null) { - while (++i < n) { - insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); - } - --i; - } else data.forEach(root.add); - xs = ys = data = d = null; - return root; - } - quadtree.x = function(_) { - return arguments.length ? (x = _, quadtree) : x; - }; - quadtree.y = function(_) { - return arguments.length ? (y = _, quadtree) : y; - }; - quadtree.extent = function(_) { - if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], - y2 = +_[1][1]; - return quadtree; - }; - quadtree.size = function(_) { - if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; - if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; - return quadtree; }; - return quadtree; - }; - function d3_geom_quadtreeCompatX(d) { - return d.x; - } - function d3_geom_quadtreeCompatY(d) { - return d.y; - } - function d3_geom_quadtreeNode() { - return { - leaf: true, - nodes: [], - point: null, - x: null, - y: null + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + return albersUsa; }; - } - function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { - if (!f(node, x1, y1, x2, y2)) { - var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; - if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); - if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); - if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); - if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); - } - } - function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { - var minDistance2 = Infinity, closestPoint; - (function find(node, x1, y1, x2, y2) { - if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; - if (point = node.point) { - var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; - if (distance2 < minDistance2) { - var distance = Math.sqrt(minDistance2 = distance2); - x0 = x - distance, y0 = y - distance; - x3 = x + distance, y3 = y + distance; - closestPoint = point; - } - } - var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; - for (var i = below << 1 | right, j = i + 4; i < j; ++i) { - if (node = children[i & 3]) switch (i & 3) { - case 0: - find(node, x1, y1, xm, ym); - break; - - case 1: - find(node, xm, y1, x2, ym); - break; - - case 2: - find(node, x1, ym, xm, y2); - break; - - case 3: - find(node, xm, ym, x2, y2); - break; - } - } - })(root, x0, y0, x3, y3); - return closestPoint; - } - d3.interpolateRgb = d3_interpolateRgb; - function d3_interpolateRgb(a, b) { - a = d3.rgb(a); - b = d3.rgb(b); - var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; - return function(t) { - return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * .35); + hawaii.scale(_); + return albersUsa.translate(lower48.translate()); }; - } - d3.interpolateObject = d3_interpolateObject; - function d3_interpolateObject(a, b) { - var i = {}, c = {}, k; - for (k in a) { - if (k in b) { - i[k] = d3_interpolate(a[k], b[k]); - } else { - c[k] = a[k]; - } + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; + alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + return albersUsa; + }; + return albersUsa.scale(1070); + }; + var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_pathAreaPolygon = 0; + d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; + }, + polygonEnd: function() { + d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; + d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); } - for (k in b) { - if (!(k in a)) { - c[k] = b[k]; - } + }; + function d3_geo_pathAreaRingStart() { + var x00, y00, x0, y0; + d3_geo_pathArea.point = function(x, y) { + d3_geo_pathArea.point = nextPoint; + x00 = x0 = x, y00 = y0 = y; + }; + function nextPoint(x, y) { + d3_geo_pathAreaPolygon += y0 * x - x0 * y; + x0 = x, y0 = y; } - return function(t) { - for (k in i) c[k] = i[k](t); - return c; + d3_geo_pathArea.lineEnd = function() { + nextPoint(x00, y00); }; } - d3.interpolateNumber = d3_interpolateNumber; - function d3_interpolateNumber(a, b) { - a = +a, b = +b; - return function(t) { - return a * (1 - t) + b * t; - }; + var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; + var d3_geo_pathBounds = { + point: d3_geo_pathBoundsPoint, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_pathBoundsPoint(x, y) { + if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; + if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; + if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; + if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; } - d3.interpolateString = d3_interpolateString; - function d3_interpolateString(a, b) { - var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; - a = a + "", b = b + ""; - while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { - if ((bs = bm.index) > bi) { - bs = b.slice(bi, bs); - if (s[i]) s[i] += bs; else s[++i] = bs; - } - if ((am = am[0]) === (bm = bm[0])) { - if (s[i]) s[i] += bm; else s[++i] = bm; - } else { - s[++i] = null; - q.push({ - i: i, - x: d3_interpolateNumber(am, bm) - }); + function d3_geo_pathBuffer() { + var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointCircle = d3_geo_pathBufferCircle(_); + return stream; + }, + result: function() { + if (buffer.length) { + var result = buffer.join(""); + buffer = []; + return result; + } } - bi = d3_interpolate_numberB.lastIndex; + }; + function point(x, y) { + buffer.push("M", x, ",", y, pointCircle); } - if (bi < b.length) { - bs = b.slice(bi); - if (s[i]) s[i] += bs; else s[++i] = bs; + function pointLineStart(x, y) { + buffer.push("M", x, ",", y); + stream.point = pointLine; } - return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { - return b(t) + ""; - }) : function() { - return b; - } : (b = q.length, function(t) { - for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); - return s.join(""); - }); - } - var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); - d3.interpolate = d3_interpolate; - function d3_interpolate(a, b) { - var i = d3.interpolators.length, f; - while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; - return f; + function pointLine(x, y) { + buffer.push("L", x, ",", y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + buffer.push("Z"); + } + return stream; } - d3.interpolators = [ function(a, b) { - var t = typeof b; - return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); - } ]; - d3.interpolateArray = d3_interpolateArray; - function d3_interpolateArray(a, b) { - var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; - for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); - for (;i < na; ++i) c[i] = a[i]; - for (;i < nb; ++i) c[i] = b[i]; - return function(t) { - for (i = 0; i < n0; ++i) c[i] = x[i](t); - return c; - }; + function d3_geo_pathBufferCircle(radius) { + return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; } - var d3_ease_default = function() { - return d3_identity; - }; - var d3_ease = d3.map({ - linear: d3_ease_default, - poly: d3_ease_poly, - quad: function() { - return d3_ease_quad; - }, - cubic: function() { - return d3_ease_cubic; - }, - sin: function() { - return d3_ease_sin; - }, - exp: function() { - return d3_ease_exp; - }, - circle: function() { - return d3_ease_circle; + var d3_geo_pathCentroid = { + point: d3_geo_pathCentroidPoint, + lineStart: d3_geo_pathCentroidLineStart, + lineEnd: d3_geo_pathCentroidLineEnd, + polygonStart: function() { + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; }, - elastic: d3_ease_elastic, - back: d3_ease_back, - bounce: function() { - return d3_ease_bounce; - } - }); - var d3_ease_mode = d3.map({ - "in": d3_identity, - out: d3_ease_reverse, - "in-out": d3_ease_reflect, - "out-in": function(f) { - return d3_ease_reflect(d3_ease_reverse(f)); + polygonEnd: function() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; + d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; } - }); - d3.ease = function(name) { - var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; - t = d3_ease.get(t) || d3_ease_default; - m = d3_ease_mode.get(m) || d3_identity; - return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); }; - function d3_ease_clamp(f) { - return function(t) { - return t <= 0 ? 0 : t >= 1 ? 1 : f(t); - }; - } - function d3_ease_reverse(f) { - return function(t) { - return 1 - f(1 - t); - }; + function d3_geo_pathCentroidPoint(x, y) { + d3_geo_centroidX0 += x; + d3_geo_centroidY0 += y; + ++d3_geo_centroidZ0; } - function d3_ease_reflect(f) { - return function(t) { - return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); + function d3_geo_pathCentroidLineStart() { + var x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } } - function d3_ease_quad(t) { - return t * t; - } - function d3_ease_cubic(t) { - return t * t * t; - } - function d3_ease_cubicInOut(t) { - if (t <= 0) return 0; - if (t >= 1) return 1; - var t2 = t * t, t3 = t2 * t; - return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + function d3_geo_pathCentroidLineEnd() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; } - function d3_ease_poly(e) { - return function(t) { - return Math.pow(t, e); + function d3_geo_pathCentroidRingStart() { + var x00, y00, x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); }; - } - function d3_ease_sin(t) { - return 1 - Math.cos(t * halfπ); - } - function d3_ease_exp(t) { - return Math.pow(2, 10 * (t - 1)); - } - function d3_ease_circle(t) { - return 1 - Math.sqrt(1 - t * t); - } - function d3_ease_elastic(a, p) { - var s; - if (arguments.length < 2) p = .45; - if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; - return function(t) { - return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + z = y0 * x - x0 * y; + d3_geo_centroidX2 += z * (x0 + x); + d3_geo_centroidY2 += z * (y0 + y); + d3_geo_centroidZ2 += z * 3; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + d3_geo_pathCentroid.lineEnd = function() { + nextPoint(x00, y00); }; } - function d3_ease_back(s) { - if (!s) s = 1.70158; - return function(t) { - return t * t * ((s + 1) * t - s); + function d3_geo_pathContext(context) { + var pointRadius = 4.5; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointRadius = _; + return stream; + }, + result: d3_noop }; + function point(x, y) { + context.moveTo(x + pointRadius, y); + context.arc(x, y, pointRadius, 0, τ); + } + function pointLineStart(x, y) { + context.moveTo(x, y); + stream.point = pointLine; + } + function pointLine(x, y) { + context.lineTo(x, y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + context.closePath(); + } + return stream; } - function d3_ease_bounce(t) { - return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; - } - d3.interpolateHcl = d3_interpolateHcl; - function d3_interpolateHcl(a, b) { - a = d3.hcl(a); - b = d3.hcl(b); - var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; - if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + function d3_geo_resample(project) { + var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; + function resample(stream) { + return (maxDepth ? resampleRecursive : resampleNone)(stream); + } + function resampleNone(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + }); + } + function resampleRecursive(stream) { + var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; + var resample = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + stream.polygonStart(); + resample.lineStart = ringStart; + }, + polygonEnd: function() { + stream.polygonEnd(); + resample.lineStart = lineStart; + } + }; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + function lineStart() { + x0 = NaN; + resample.point = linePoint; + stream.lineStart(); + } + function linePoint(λ, φ) { + var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); + resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + function lineEnd() { + resample.point = point; + stream.lineEnd(); + } + function ringStart() { + lineStart(); + resample.point = ringPoint; + resample.lineEnd = ringEnd; + } + function ringPoint(λ, φ) { + linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resample.point = linePoint; + } + function ringEnd() { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); + resample.lineEnd = lineEnd; + lineEnd(); + } + return resample; + } + function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; + if (d2 > 4 * δ2 && depth--) { + var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); + } + } + } + resample.precision = function(_) { + if (!arguments.length) return Math.sqrt(δ2); + maxDepth = (δ2 = _ * _) > 0 && 16; + return resample; }; + return resample; } - d3.interpolateHsl = d3_interpolateHsl; - function d3_interpolateHsl(a, b) { - a = d3.hsl(a); - b = d3.hsl(b); - var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; - if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; - if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; - return function(t) { - return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + d3.geo.path = function() { + var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); + d3.geo.stream(object, cacheStream); + } + return contextStream.result(); + } + path.area = function(object) { + d3_geo_pathAreaSum = 0; + d3.geo.stream(object, projectStream(d3_geo_pathArea)); + return d3_geo_pathAreaSum; }; - } - d3.interpolateLab = d3_interpolateLab; - function d3_interpolateLab(a, b) { - a = d3.lab(a); - b = d3.lab(b); - var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; - return function(t) { - return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + path.centroid = function(object) { + d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); + return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; }; - } - d3.interpolateRound = d3_interpolateRound; - function d3_interpolateRound(a, b) { - b -= a; - return function(t) { - return Math.round(a + b * t); + path.bounds = function(object) { + d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); + d3.geo.stream(object, projectStream(d3_geo_pathBounds)); + return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; }; - } - d3.transform = function(string) { - var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); - return (d3.transform = function(string) { - if (string != null) { - g.setAttribute("transform", string); - var t = g.transform.baseVal.consolidate(); - } - return new d3_transform(t ? t.matrix : d3_transformIdentity); - })(string); - }; - function d3_transform(m) { - var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; - if (r0[0] * r1[1] < r1[0] * r0[1]) { - r0[0] *= -1; - r0[1] *= -1; - kx *= -1; - kz *= -1; + path.projection = function(_) { + if (!arguments.length) return projection; + projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; + return reset(); + }; + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return reset(); + }; + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + function reset() { + cacheStream = null; + return path; } - this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; - this.translate = [ m.e, m.f ]; - this.scale = [ kx, ky ]; - this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + return path.projection(d3.geo.albersUsa()).context(null); + }; + function d3_geo_pathProjectStream(project) { + var resample = d3_geo_resample(function(x, y) { + return project([ x * d3_degrees, y * d3_degrees ]); + }); + return function(stream) { + return d3_geo_projectionRadians(resample(stream)); + }; } - d3_transform.prototype.toString = function() { - return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + d3.geo.transform = function(methods) { + return { + stream: function(stream) { + var transform = new d3_geo_transform(stream); + for (var k in methods) transform[k] = methods[k]; + return transform; + } + }; }; - function d3_transformDot(a, b) { - return a[0] * b[0] + a[1] * b[1]; + function d3_geo_transform(stream) { + this.stream = stream; } - function d3_transformNormalize(a) { - var k = Math.sqrt(d3_transformDot(a, a)); - if (k) { - a[0] /= k; - a[1] /= k; + d3_geo_transform.prototype = { + point: function(x, y) { + this.stream.point(x, y); + }, + sphere: function() { + this.stream.sphere(); + }, + lineStart: function() { + this.stream.lineStart(); + }, + lineEnd: function() { + this.stream.lineEnd(); + }, + polygonStart: function() { + this.stream.polygonStart(); + }, + polygonEnd: function() { + this.stream.polygonEnd(); } - return k; + }; + function d3_geo_transformPoint(stream, point) { + return { + point: point, + sphere: function() { + stream.sphere(); + }, + lineStart: function() { + stream.lineStart(); + }, + lineEnd: function() { + stream.lineEnd(); + }, + polygonStart: function() { + stream.polygonStart(); + }, + polygonEnd: function() { + stream.polygonEnd(); + } + }; } - function d3_transformCombine(a, b, k) { - a[0] += k * b[0]; - a[1] += k * b[1]; - return a; + d3.geo.projection = d3_geo_projection; + d3.geo.projectionMutator = d3_geo_projectionMutator; + function d3_geo_projection(project) { + return d3_geo_projectionMutator(function() { + return project; + })(); } - var d3_transformIdentity = { - a: 1, - b: 0, - c: 0, - d: 1, - e: 0, - f: 0 - }; - d3.interpolateTransform = d3_interpolateTransform; - function d3_interpolateTransform(a, b) { - var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; - if (ta[0] != tb[0] || ta[1] != tb[1]) { - s.push("translate(", null, ",", null, ")"); - q.push({ - i: 1, - x: d3_interpolateNumber(ta[0], tb[0]) - }, { - i: 3, - x: d3_interpolateNumber(ta[1], tb[1]) - }); - } else if (tb[0] || tb[1]) { - s.push("translate(" + tb + ")"); - } else { - s.push(""); + function d3_geo_projectionMutator(projectAt) { + var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { + x = project(x, y); + return [ x[0] * k + δx, δy - x[1] * k ]; + }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; + function projection(point) { + point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); + return [ point[0] * k + δx, δy - point[1] * k ]; } - if (ra != rb) { - if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; - q.push({ - i: s.push(s.pop() + "rotate(", null, ")") - 2, - x: d3_interpolateNumber(ra, rb) - }); - } else if (rb) { - s.push(s.pop() + "rotate(" + rb + ")"); + function invert(point) { + point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); + return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; } - if (wa != wb) { - q.push({ - i: s.push(s.pop() + "skewX(", null, ")") - 2, - x: d3_interpolateNumber(wa, wb) - }); - } else if (wb) { - s.push(s.pop() + "skewX(" + wb + ")"); + projection.stream = function(output) { + if (stream) stream.valid = false; + stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); + stream.valid = true; + return stream; + }; + projection.clipAngle = function(_) { + if (!arguments.length) return clipAngle; + preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); + return invalidate(); + }; + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; + return invalidate(); + }; + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return reset(); + }; + projection.translate = function(_) { + if (!arguments.length) return [ x, y ]; + x = +_[0]; + y = +_[1]; + return reset(); + }; + projection.center = function(_) { + if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; + λ = _[0] % 360 * d3_radians; + φ = _[1] % 360 * d3_radians; + return reset(); + }; + projection.rotate = function(_) { + if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; + δλ = _[0] % 360 * d3_radians; + δφ = _[1] % 360 * d3_radians; + δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; + return reset(); + }; + d3.rebind(projection, projectResample, "precision"); + function reset() { + projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); + var center = project(λ, φ); + δx = x - center[0] * k; + δy = y + center[1] * k; + return invalidate(); } - if (ka[0] != kb[0] || ka[1] != kb[1]) { - n = s.push(s.pop() + "scale(", null, ",", null, ")"); - q.push({ - i: n - 4, - x: d3_interpolateNumber(ka[0], kb[0]) - }, { - i: n - 2, - x: d3_interpolateNumber(ka[1], kb[1]) - }); - } else if (kb[0] != 1 || kb[1] != 1) { - s.push(s.pop() + "scale(" + kb + ")"); + function invalidate() { + if (stream) stream.valid = false, stream = null; + return projection; } - n = q.length; - return function(t) { - var i = -1, o; - while (++i < n) s[(o = q[i]).i] = o.x(t); - return s.join(""); + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return reset(); }; } - function d3_uninterpolateNumber(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return (x - a) / b; - }; + function d3_geo_projectionRadians(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + stream.point(x * d3_radians, y * d3_radians); + }); } - function d3_uninterpolateClamp(a, b) { - b = (b -= a = +a) || 1 / b; - return function(x) { - return Math.max(0, Math.min(1, (x - a) / b)); - }; + function d3_geo_equirectangular(λ, φ) { + return [ λ, φ ]; } - d3.layout = {}; - d3.layout.bundle = function() { - return function(links) { - var paths = [], i = -1, n = links.length; - while (++i < n) paths.push(d3_layout_bundlePath(links[i])); - return paths; + (d3.geo.equirectangular = function() { + return d3_geo_projection(d3_geo_equirectangular); + }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; + d3.geo.rotation = function(rotate) { + rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); + function forward(coordinates) { + coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + } + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; }; + return forward; }; - function d3_layout_bundlePath(link) { - var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; - while (start !== lca) { - start = start.parent; - points.push(start); - } - var k = points.length; - while (end !== lca) { - points.splice(k, 0, end); - end = end.parent; - } - return points; + function d3_geo_identityRotation(λ, φ) { + return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; } - function d3_layout_bundleAncestors(node) { - var ancestors = [], parent = node.parent; - while (parent != null) { - ancestors.push(node); - node = parent; - parent = parent.parent; - } - ancestors.push(node); - return ancestors; + d3_geo_identityRotation.invert = d3_geo_equirectangular; + function d3_geo_rotation(δλ, δφ, δγ) { + return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; } - function d3_layout_bundleLeastCommonAncestor(a, b) { - if (a === b) return a; - var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; - while (aNode === bNode) { - sharedNode = aNode; - aNode = aNodes.pop(); - bNode = bNodes.pop(); + function d3_geo_forwardRotationλ(δλ) { + return function(λ, φ) { + return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ]; + }; + } + function d3_geo_rotationλ(δλ) { + var rotation = d3_geo_forwardRotationλ(δλ); + rotation.invert = d3_geo_forwardRotationλ(-δλ); + return rotation; + } + function d3_geo_rotationφγ(δφ, δγ) { + var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); + function rotation(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; + return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; } - return sharedNode; + rotation.invert = function(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; + return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; + }; + return rotation; } - d3.layout.chord = function() { - var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; - function relayout() { - var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; - chords = []; - groups = []; - k = 0, i = -1; - while (++i < n) { - x = 0, j = -1; - while (++j < n) { - x += matrix[i][j]; - } - groupSums.push(x); - subgroupIndex.push(d3.range(n)); - k += x; - } - if (sortGroups) { - groupIndex.sort(function(a, b) { - return sortGroups(groupSums[a], groupSums[b]); - }); - } - if (sortSubgroups) { - subgroupIndex.forEach(function(d, i) { - d.sort(function(a, b) { - return sortSubgroups(matrix[i][a], matrix[i][b]); - }); - }); - } - k = (τ - padding * n) / k; - x = 0, i = -1; - while (++i < n) { - x0 = x, j = -1; - while (++j < n) { - var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; - subgroups[di + "-" + dj] = { - index: di, - subindex: dj, - startAngle: a0, - endAngle: a1, - value: v - }; - } - groups[di] = { - index: di, - startAngle: x0, - endAngle: x, - value: (x - x0) / k - }; - x += padding; - } - i = -1; - while (++i < n) { - j = i - 1; - while (++j < n) { - var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; - if (source.value || target.value) { - chords.push(source.value < target.value ? { - source: target, - target: source - } : { - source: source, - target: target - }); - } + d3.geo.circle = function() { + var origin = [ 0, 0 ], angle, precision = 6, interpolate; + function circle() { + var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; + interpolate(null, null, 1, { + point: function(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= d3_degrees, x[1] *= d3_degrees; } - } - if (sortChords) resort(); - } - function resort() { - chords.sort(function(a, b) { - return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); }); + return { + type: "Polygon", + coordinates: [ ring ] + }; } - chord.matrix = function(x) { - if (!arguments.length) return matrix; - n = (matrix = x) && matrix.length; - chords = groups = null; - return chord; - }; - chord.padding = function(x) { - if (!arguments.length) return padding; - padding = x; - chords = groups = null; - return chord; - }; - chord.sortGroups = function(x) { - if (!arguments.length) return sortGroups; - sortGroups = x; - chords = groups = null; - return chord; - }; - chord.sortSubgroups = function(x) { - if (!arguments.length) return sortSubgroups; - sortSubgroups = x; - chords = null; - return chord; + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; }; - chord.sortChords = function(x) { - if (!arguments.length) return sortChords; - sortChords = x; - if (chords) resort(); - return chord; + circle.angle = function(x) { + if (!arguments.length) return angle; + interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); + return circle; }; - chord.chords = function() { - if (!chords) relayout(); - return chords; + circle.precision = function(_) { + if (!arguments.length) return precision; + interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); + return circle; }; - chord.groups = function() { - if (!groups) relayout(); - return groups; + return circle.angle(90); + }; + function d3_geo_circleInterpolate(radius, precision) { + var cr = Math.cos(radius), sr = Math.sin(radius); + return function(from, to, direction, listener) { + var step = direction * precision; + if (from != null) { + from = d3_geo_circleAngle(cr, from); + to = d3_geo_circleAngle(cr, to); + if (direction > 0 ? from < to : from > to) from += direction * τ; + } else { + from = radius + direction * τ; + to = radius - .5 * step; + } + for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { + listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); + } }; - return chord; + } + function d3_geo_circleAngle(cr, point) { + var a = d3_geo_cartesian(point); + a[0] -= cr; + d3_geo_cartesianNormalize(a); + var angle = d3_acos(-a[1]); + return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + } + d3.geo.distance = function(a, b) { + var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; + return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); }; - d3.layout.force = function() { - var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; - function repulse(node) { - return function(quad, x1, _, x2) { - if (quad.point !== node) { - var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; - if (dw * dw / theta2 < dn) { - if (dn < chargeDistance2) { - var k = quad.charge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - return true; - } - if (quad.point && dn && dn < chargeDistance2) { - var k = quad.pointCharge / dn; - node.px -= dx * k; - node.py -= dy * k; - } - } - return !quad.charge; + d3.geo.graticule = function() { + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; + function graticule() { + return { + type: "MultiLineString", + coordinates: lines() }; } - force.tick = function() { - if ((alpha *= .99) < .005) { - event.end({ - type: "end", - alpha: alpha = 0 - }); - return true; - } - var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; - for (i = 0; i < m; ++i) { - o = links[i]; - s = o.source; - t = o.target; - x = t.x - s.x; - y = t.y - s.y; - if (l = x * x + y * y) { - l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; - x *= l; - y *= l; - t.x -= x * (k = s.weight / (t.weight + s.weight)); - t.y -= y * k; - s.x += x * (k = 1 - k); - s.y += y * k; - } - } - if (k = alpha * gravity) { - x = size[0] / 2; - y = size[1] / 2; - i = -1; - if (k) while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * k; - o.y += (y - o.y) * k; - } - } - if (charge) { - d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); - i = -1; - while (++i < n) { - if (!(o = nodes[i]).fixed) { - q.visit(repulse(o)); - } - } - } - i = -1; - while (++i < n) { - o = nodes[i]; - if (o.fixed) { - o.x = o.px; - o.y = o.py; - } else { - o.x -= (o.px - (o.px = o.x)) * friction; - o.y -= (o.py - (o.py = o.y)) * friction; - } - } - event.tick({ - type: "tick", - alpha: alpha + function lines() { + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { + return abs(x % DX) > ε; + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { + return abs(y % DY) > ε; + }).map(y)); + } + graticule.lines = function() { + return lines().map(function(coordinates) { + return { + type: "LineString", + coordinates: coordinates + }; }); }; - force.nodes = function(x) { - if (!arguments.length) return nodes; - nodes = x; - return force; - }; - force.links = function(x) { - if (!arguments.length) return links; - links = x; - return force; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] + }; }; - force.size = function(x) { - if (!arguments.length) return size; - size = x; - return force; + graticule.extent = function(_) { + if (!arguments.length) return graticule.minorExtent(); + return graticule.majorExtent(_).minorExtent(_); }; - force.linkDistance = function(x) { - if (!arguments.length) return linkDistance; - linkDistance = typeof x === "function" ? x : +x; - return force; + graticule.majorExtent = function(_) { + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); }; - force.distance = force.linkDistance; - force.linkStrength = function(x) { - if (!arguments.length) return linkStrength; - linkStrength = typeof x === "function" ? x : +x; - return force; + graticule.minorExtent = function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); }; - force.friction = function(x) { - if (!arguments.length) return friction; - friction = +x; - return force; + graticule.step = function(_) { + if (!arguments.length) return graticule.minorStep(); + return graticule.majorStep(_).minorStep(_); }; - force.charge = function(x) { - if (!arguments.length) return charge; - charge = typeof x === "function" ? x : +x; - return force; + graticule.majorStep = function(_) { + if (!arguments.length) return [ DX, DY ]; + DX = +_[0], DY = +_[1]; + return graticule; }; - force.chargeDistance = function(x) { - if (!arguments.length) return Math.sqrt(chargeDistance2); - chargeDistance2 = x * x; - return force; + graticule.minorStep = function(_) { + if (!arguments.length) return [ dx, dy ]; + dx = +_[0], dy = +_[1]; + return graticule; }; - force.gravity = function(x) { - if (!arguments.length) return gravity; - gravity = +x; - return force; + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = d3_geo_graticuleX(y0, y1, 90); + y = d3_geo_graticuleY(x0, x1, precision); + X = d3_geo_graticuleX(Y0, Y1, 90); + Y = d3_geo_graticuleY(X0, X1, precision); + return graticule; }; - force.theta = function(x) { - if (!arguments.length) return Math.sqrt(theta2); - theta2 = x * x; - return force; + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); + }; + function d3_geo_graticuleX(y0, y1, dy) { + var y = d3.range(y0, y1 - ε, dy).concat(y1); + return function(x) { + return y.map(function(y) { + return [ x, y ]; + }); }; - force.alpha = function(x) { - if (!arguments.length) return alpha; - x = +x; - if (alpha) { - if (x > 0) alpha = x; else alpha = 0; - } else if (x > 0) { - event.start({ - type: "start", - alpha: alpha = x - }); - d3.timer(force.tick); - } - return force; + } + function d3_geo_graticuleY(x0, x1, dx) { + var x = d3.range(x0, x1 - ε, dx).concat(x1); + return function(y) { + return x.map(function(x) { + return [ x, y ]; + }); }; - force.start = function() { - var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; - for (i = 0; i < n; ++i) { - (o = nodes[i]).index = i; - o.weight = 0; - } - for (i = 0; i < m; ++i) { - o = links[i]; - if (typeof o.source == "number") o.source = nodes[o.source]; - if (typeof o.target == "number") o.target = nodes[o.target]; - ++o.source.weight; - ++o.target.weight; - } - for (i = 0; i < n; ++i) { - o = nodes[i]; - if (isNaN(o.x)) o.x = position("x", w); - if (isNaN(o.y)) o.y = position("y", h); - if (isNaN(o.px)) o.px = o.x; - if (isNaN(o.py)) o.py = o.y; - } - distances = []; - if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; - strengths = []; - if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; - charges = []; - if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; - function position(dimension, size) { - if (!neighbors) { - neighbors = new Array(n); - for (j = 0; j < n; ++j) { - neighbors[j] = []; - } - for (j = 0; j < m; ++j) { - var o = links[j]; - neighbors[o.source.index].push(o.target); - neighbors[o.target.index].push(o.source); - } - } - var candidates = neighbors[i], j = -1, l = candidates.length, x; - while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; - return Math.random() * size; - } - return force.resume(); + } + function d3_source(d) { + return d.source; + } + function d3_target(d) { + return d.target; + } + d3.geo.greatArc = function() { + var source = d3_source, source_, target = d3_target, target_; + function greatArc() { + return { + type: "LineString", + coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] + }; + } + greatArc.distance = function() { + return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); }; - force.resume = function() { - return force.alpha(.1); + greatArc.source = function(_) { + if (!arguments.length) return source; + source = _, source_ = typeof _ === "function" ? null : _; + return greatArc; }; - force.stop = function() { - return force.alpha(0); + greatArc.target = function(_) { + if (!arguments.length) return target; + target = _, target_ = typeof _ === "function" ? null : _; + return greatArc; }; - force.drag = function() { - if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); - if (!arguments.length) return drag; - this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); + greatArc.precision = function() { + return arguments.length ? greatArc : 0; }; - function dragmove(d) { - d.px = d3.event.x, d.py = d3.event.y; - force.resume(); - } - return d3.rebind(force, event, "on"); + return greatArc; }; - function d3_layout_forceDragstart(d) { - d.fixed |= 2; - } - function d3_layout_forceDragend(d) { - d.fixed &= ~6; + d3.geo.interpolate = function(source, target) { + return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + }; + function d3_geo_interpolate(x0, y0, x1, y1) { + var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); + var interpolate = d ? function(t) { + var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; + return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; + } : function() { + return [ x0 * d3_degrees, y0 * d3_degrees ]; + }; + interpolate.distance = d; + return interpolate; } - function d3_layout_forceMouseover(d) { - d.fixed |= 4; - d.px = d.x, d.py = d.y; + d3.geo.length = function(object) { + d3_geo_lengthSum = 0; + d3.geo.stream(object, d3_geo_length); + return d3_geo_lengthSum; + }; + var d3_geo_lengthSum; + var d3_geo_length = { + sphere: d3_noop, + point: d3_noop, + lineStart: d3_geo_lengthLineStart, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_lengthLineStart() { + var λ0, sinφ0, cosφ0; + d3_geo_length.point = function(λ, φ) { + λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); + d3_geo_length.point = nextPoint; + }; + d3_geo_length.lineEnd = function() { + d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + }; + function nextPoint(λ, φ) { + var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); + d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; + } } - function d3_layout_forceMouseout(d) { - d.fixed &= ~4; + function d3_geo_azimuthal(scale, angle) { + function azimuthal(λ, φ) { + var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); + return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + } + azimuthal.invert = function(x, y) { + var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c); + return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ]; + }; + return azimuthal; } - function d3_layout_forceAccumulate(quad, alpha, charges) { - var cx = 0, cy = 0; - quad.charge = 0; - if (!quad.leaf) { - var nodes = quad.nodes, n = nodes.length, i = -1, c; - while (++i < n) { - c = nodes[i]; - if (c == null) continue; - d3_layout_forceAccumulate(c, alpha, charges); - quad.charge += c.charge; - cx += c.charge * c.cx; - cy += c.charge * c.cy; + var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { + return Math.sqrt(2 / (1 + cosλcosφ)); + }, function(ρ) { + return 2 * Math.asin(ρ / 2); + }); + (d3.geo.azimuthalEqualArea = function() { + return d3_geo_projection(d3_geo_azimuthalEqualArea); + }).raw = d3_geo_azimuthalEqualArea; + var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { + var c = Math.acos(cosλcosφ); + return c && c / Math.sin(c); + }, d3_identity); + (d3.geo.azimuthalEquidistant = function() { + return d3_geo_projection(d3_geo_azimuthalEquidistant); + }).raw = d3_geo_azimuthalEquidistant; + function d3_geo_conicConformal(φ0, φ1) { + var cosφ0 = Math.cos(φ0), t = function(φ) { + return Math.tan(π / 4 + φ / 2); + }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; + if (!n) return d3_geo_mercator; + function forward(λ, φ) { + if (F > 0) { + if (φ < -halfπ + ε) φ = -halfπ + ε; + } else { + if (φ > halfπ - ε) φ = halfπ - ε; } + var ρ = F / Math.pow(t(φ), n); + return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ]; } - if (quad.point) { - if (!quad.leaf) { - quad.point.x += Math.random() - .5; - quad.point.y += Math.random() - .5; - } - var k = alpha * charges[quad.point.index]; - quad.charge += quad.pointCharge = k; - cx += k * quad.point.x; - cy += k * quad.point.y; + forward.invert = function(x, y) { + var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y); + return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ]; + }; + return forward; + } + (d3.geo.conicConformal = function() { + return d3_geo_conic(d3_geo_conicConformal); + }).raw = d3_geo_conicConformal; + function d3_geo_conicEquidistant(φ0, φ1) { + var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; + if (abs(n) < ε) return d3_geo_equirectangular; + function forward(λ, φ) { + var ρ = G - φ; + return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ]; } - quad.cx = cx / quad.charge; - quad.cy = cy / quad.charge; + forward.invert = function(x, y) { + var ρ0_y = G - y; + return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ]; + }; + return forward; } - var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; - d3.layout.hierarchy = function() { - var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; - function hierarchy(root) { - var stack = [ root ], nodes = [], node; - root.depth = 0; - while ((node = stack.pop()) != null) { - nodes.push(node); - if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { - var n, childs, child; - while (--n >= 0) { - stack.push(child = childs[n]); - child.parent = node; - child.depth = node.depth + 1; - } - if (value) node.value = 0; - node.children = childs; - } else { - if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; - delete node.children; + (d3.geo.conicEquidistant = function() { + return d3_geo_conic(d3_geo_conicEquidistant); + }).raw = d3_geo_conicEquidistant; + var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / cosλcosφ; + }, Math.atan); + (d3.geo.gnomonic = function() { + return d3_geo_projection(d3_geo_gnomonic); + }).raw = d3_geo_gnomonic; + function d3_geo_mercator(λ, φ) { + return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ]; + } + d3_geo_mercator.invert = function(x, y) { + return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ]; + }; + function d3_geo_mercatorProjection(project) { + var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; + m.scale = function() { + var v = scale.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.translate = function() { + var v = translate.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.clipExtent = function(_) { + var v = clipExtent.apply(m, arguments); + if (v === m) { + if (clipAuto = _ == null) { + var k = π * scale(), t = translate(); + clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); } + } else if (clipAuto) { + v = null; } - d3_layout_hierarchyVisitAfter(root, function(node) { - var childs, parent; - if (sort && (childs = node.children)) childs.sort(sort); - if (value && (parent = node.parent)) parent.value += node.value; - }); - return nodes; - } - hierarchy.sort = function(x) { - if (!arguments.length) return sort; - sort = x; - return hierarchy; + return v; }; - hierarchy.children = function(x) { - if (!arguments.length) return children; - children = x; - return hierarchy; + return m.clipExtent(null); + } + (d3.geo.mercator = function() { + return d3_geo_mercatorProjection(d3_geo_mercator); + }).raw = d3_geo_mercator; + var d3_geo_orthographic = d3_geo_azimuthal(function() { + return 1; + }, Math.asin); + (d3.geo.orthographic = function() { + return d3_geo_projection(d3_geo_orthographic); + }).raw = d3_geo_orthographic; + var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / (1 + cosλcosφ); + }, function(ρ) { + return 2 * Math.atan(ρ); + }); + (d3.geo.stereographic = function() { + return d3_geo_projection(d3_geo_stereographic); + }).raw = d3_geo_stereographic; + function d3_geo_transverseMercator(λ, φ) { + return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ]; + } + d3_geo_transverseMercator.invert = function(x, y) { + return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ]; + }; + (d3.geo.transverseMercator = function() { + var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; + projection.center = function(_) { + return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); }; - hierarchy.value = function(x) { - if (!arguments.length) return value; - value = x; - return hierarchy; + projection.rotate = function(_) { + return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), + [ _[0], _[1], _[2] - 90 ]); }; - hierarchy.revalue = function(root) { - if (value) { - d3_layout_hierarchyVisitBefore(root, function(node) { - if (node.children) node.value = 0; - }); - d3_layout_hierarchyVisitAfter(root, function(node) { - var parent; - if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; - if (parent = node.parent) parent.value += node.value; - }); + return rotate([ 0, 0, 90 ]); + }).raw = d3_geo_transverseMercator; + d3.geom = {}; + function d3_geom_pointX(d) { + return d[0]; + } + function d3_geom_pointY(d) { + return d[1]; + } + d3.geom.hull = function(vertices) { + var x = d3_geom_pointX, y = d3_geom_pointY; + if (arguments.length) return hull(vertices); + function hull(data) { + if (data.length < 3) return []; + var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; + for (i = 0; i < n; i++) { + points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + } + points.sort(d3_geom_hullOrder); + for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); + var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); + var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; + for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); + for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); + return polygon; + } + hull.x = function(_) { + return arguments.length ? (x = _, hull) : x; + }; + hull.y = function(_) { + return arguments.length ? (y = _, hull) : y; + }; + return hull; + }; + function d3_geom_hullUpper(points) { + var n = points.length, hull = [ 0, 1 ], hs = 2; + for (var i = 2; i < n; i++) { + while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; + hull[hs++] = i; + } + return hull.slice(0, hs); + } + function d3_geom_hullOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + d3.geom.polygon = function(coordinates) { + d3_subclass(coordinates, d3_geom_polygonPrototype); + return coordinates; + }; + var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; + d3_geom_polygonPrototype.area = function() { + var i = -1, n = this.length, a, b = this[n - 1], area = 0; + while (++i < n) { + a = b; + b = this[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + return area * .5; + }; + d3_geom_polygonPrototype.centroid = function(k) { + var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; + if (!arguments.length) k = -1 / (6 * this.area()); + while (++i < n) { + a = b; + b = this[i]; + c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + return [ x * k, y * k ]; + }; + d3_geom_polygonPrototype.clip = function(subject) { + var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; + while (++i < n) { + input = subject.slice(); + subject.length = 0; + b = this[i]; + c = input[(m = input.length - closed) - 1]; + j = -1; + while (++j < m) { + d = input[j]; + if (d3_geom_polygonInside(d, a, b)) { + if (!d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + subject.push(d); + } else if (d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + c = d; } - return root; - }; - return hierarchy; + if (closed) subject.push(subject[0]); + a = b; + } + return subject; }; - function d3_layout_hierarchyRebind(object, hierarchy) { - d3.rebind(object, hierarchy, "sort", "children", "value"); - object.nodes = object; - object.links = d3_layout_hierarchyLinks; - return object; + function d3_geom_polygonInside(p, a, b) { + return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); } - function d3_layout_hierarchyVisitBefore(node, callback) { - var nodes = [ node ]; - while ((node = nodes.pop()) != null) { - callback(node); - if ((children = node.children) && (n = children.length)) { - var n, children; - while (--n >= 0) nodes.push(children[n]); - } - } + function d3_geom_polygonIntersect(c, d, a, b) { + var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); + return [ x1 + ua * x21, y1 + ua * y21 ]; } - function d3_layout_hierarchyVisitAfter(node, callback) { - var nodes = [ node ], nodes2 = []; - while ((node = nodes.pop()) != null) { - nodes2.push(node); - if ((children = node.children) && (n = children.length)) { - var i = -1, n, children; - while (++i < n) nodes.push(children[i]); - } - } - while ((node = nodes2.pop()) != null) { - callback(node); - } + function d3_geom_polygonClosed(coordinates) { + var a = coordinates[0], b = coordinates[coordinates.length - 1]; + return !(a[0] - b[0] || a[1] - b[1]); } - function d3_layout_hierarchyChildren(d) { - return d.children; + var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; + function d3_geom_voronoiBeach() { + d3_geom_voronoiRedBlackNode(this); + this.edge = this.site = this.circle = null; } - function d3_layout_hierarchyValue(d) { - return d.value; + function d3_geom_voronoiCreateBeach(site) { + var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); + beach.site = site; + return beach; } - function d3_layout_hierarchySort(a, b) { - return b.value - a.value; + function d3_geom_voronoiDetachBeach(beach) { + d3_geom_voronoiDetachCircle(beach); + d3_geom_voronoiBeaches.remove(beach); + d3_geom_voronoiBeachPool.push(beach); + d3_geom_voronoiRedBlackNode(beach); } - function d3_layout_hierarchyLinks(nodes) { - return d3.merge(nodes.map(function(parent) { - return (parent.children || []).map(function(child) { - return { - source: parent, - target: child - }; - }); - })); + function d3_geom_voronoiRemoveBeach(beach) { + var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { + x: x, + y: y + }, previous = beach.P, next = beach.N, disappearing = [ beach ]; + d3_geom_voronoiDetachBeach(beach); + var lArc = previous; + while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { + previous = lArc.P; + disappearing.unshift(lArc); + d3_geom_voronoiDetachBeach(lArc); + lArc = previous; + } + disappearing.unshift(lArc); + d3_geom_voronoiDetachCircle(lArc); + var rArc = next; + while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { + next = rArc.N; + disappearing.push(rArc); + d3_geom_voronoiDetachBeach(rArc); + rArc = next; + } + disappearing.push(rArc); + d3_geom_voronoiDetachCircle(rArc); + var nArcs = disappearing.length, iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); } - d3.layout.partition = function() { - var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; - function position(node, x, dx, dy) { - var children = node.children; - node.x = x; - node.y = node.depth * dy; - node.dx = dx; - node.dy = dy; - if (children && (n = children.length)) { - var i = -1, n, c, d; - dx = node.value ? dx / node.value : 0; - while (++i < n) { - position(c = children[i], x, d = c.value * dx, dy); - x += d; + function d3_geom_voronoiAddBeach(site) { + var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; + while (node) { + dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; + if (dxl > ε) node = node.L; else { + dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); + if (dxr > ε) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -ε) { + lArc = node.P; + rArc = node; + } else if (dxr > -ε) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; } } } - function depth(node) { - var children = node.children, d = 0; - if (children && (n = children.length)) { - var i = -1, n; - while (++i < n) d = Math.max(d, depth(children[i])); - } - return 1 + d; + var newArc = d3_geom_voronoiCreateBeach(site); + d3_geom_voronoiBeaches.insert(lArc, newArc); + if (!lArc && !rArc) return; + if (lArc === rArc) { + d3_geom_voronoiDetachCircle(lArc); + rArc = d3_geom_voronoiCreateBeach(lArc.site); + d3_geom_voronoiBeaches.insert(newArc, rArc); + newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + return; } - function partition(d, i) { - var nodes = hierarchy.call(this, d, i); - position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); - return nodes; + if (!rArc) { + newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + return; } - partition.size = function(x) { - if (!arguments.length) return size; - size = x; - return partition; + d3_geom_voronoiDetachCircle(lArc); + d3_geom_voronoiDetachCircle(rArc); + var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { + x: (cy * hb - by * hc) / d + ax, + y: (bx * hc - cx * hb) / d + ay }; - return d3_layout_hierarchyRebind(partition, hierarchy); - }; - d3.layout.pie = function() { - var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; - function pie(data) { - var n = data.length, values = data.map(function(d, i) { - return +value.call(pie, d, i); - }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), k = (da - n * pa) / d3.sum(values), index = d3.range(n), arcs = [], v; - if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { - return values[j] - values[i]; - } : function(i, j) { - return sort(data[i], data[j]); - }); - index.forEach(function(i) { - arcs[i] = { - data: data[i], - value: v = values[i], - startAngle: a, - endAngle: a += v * k + pa, - padAngle: p - }; - }); - return arcs; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); + rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiLeftBreakPoint(arc, directrix) { + var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; + if (!pby2) return rfocx; + var lArc = arc.P; + if (!lArc) return -Infinity; + site = lArc.site; + var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; + if (!plby2) return lfocx; + var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + return (rfocx + lfocx) / 2; + } + function d3_geom_voronoiRightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); + var site = arc.site; + return site.y === directrix ? site.x : Infinity; + } + function d3_geom_voronoiCell(site) { + this.site = site; + this.edges = []; + } + d3_geom_voronoiCell.prototype.prepare = function() { + var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; + while (iHalfEdge--) { + edge = halfEdges[iHalfEdge].edge; + if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); } - pie.value = function(_) { - if (!arguments.length) return value; - value = _; - return pie; - }; - pie.sort = function(_) { - if (!arguments.length) return sort; - sort = _; - return pie; - }; - pie.startAngle = function(_) { - if (!arguments.length) return startAngle; - startAngle = _; - return pie; - }; - pie.endAngle = function(_) { - if (!arguments.length) return endAngle; - endAngle = _; - return pie; - }; - pie.padAngle = function(_) { - if (!arguments.length) return padAngle; - padAngle = _; - return pie; - }; - return pie; + halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); + return halfEdges.length; }; - var d3_layout_pieSortByValue = {}; - d3.layout.stack = function() { - var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; - function stack(data, index) { - if (!(n = data.length)) return data; - var series = data.map(function(d, i) { - return values.call(stack, d, i); - }); - var points = series.map(function(d) { - return d.map(function(v, i) { - return [ x.call(stack, v, i), y.call(stack, v, i) ]; - }); - }); - var orders = order.call(stack, points, index); - series = d3.permute(series, orders); - points = d3.permute(points, orders); - var offsets = offset.call(stack, points, index); - var m = series[0].length, n, i, j, o; - for (j = 0; j < m; ++j) { - out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); - for (i = 1; i < n; ++i) { - out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + function d3_geom_voronoiCloseCells(extent) { + var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; + while (iCell--) { + cell = cells[iCell]; + if (!cell || !cell.prepare()) continue; + halfEdges = cell.edges; + nHalfEdges = halfEdges.length; + iHalfEdge = 0; + while (iHalfEdge < nHalfEdges) { + end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; + start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; + if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { + halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { + x: x0, + y: abs(x2 - x0) < ε ? y2 : y1 + } : abs(y3 - y1) < ε && x1 - x3 > ε ? { + x: abs(y2 - y1) < ε ? x2 : x1, + y: y1 + } : abs(x3 - x1) < ε && y3 - y0 > ε ? { + x: x1, + y: abs(x2 - x1) < ε ? y2 : y0 + } : abs(y3 - y0) < ε && x3 - x0 > ε ? { + x: abs(y2 - y0) < ε ? x2 : x0, + y: y0 + } : null), cell.site, null)); + ++nHalfEdges; } } - return data; } - stack.values = function(x) { - if (!arguments.length) return values; - values = x; - return stack; - }; - stack.order = function(x) { - if (!arguments.length) return order; - order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; - return stack; - }; - stack.offset = function(x) { - if (!arguments.length) return offset; - offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; - return stack; - }; - stack.x = function(z) { - if (!arguments.length) return x; - x = z; - return stack; - }; - stack.y = function(z) { - if (!arguments.length) return y; - y = z; - return stack; - }; - stack.out = function(z) { - if (!arguments.length) return out; - out = z; - return stack; - }; - return stack; - }; - function d3_layout_stackX(d) { - return d.x; } - function d3_layout_stackY(d) { - return d.y; + function d3_geom_voronoiHalfEdgeOrder(a, b) { + return b.angle - a.angle; } - function d3_layout_stackOut(d, y0, y) { - d.y0 = y0; - d.y = y; + function d3_geom_voronoiCircle() { + d3_geom_voronoiRedBlackNode(this); + this.x = this.y = this.arc = this.site = this.cy = null; } - var d3_layout_stackOrders = d3.map({ - "inside-out": function(data) { - var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { - return max[a] - max[b]; - }), top = 0, bottom = 0, tops = [], bottoms = []; - for (i = 0; i < n; ++i) { - j = index[i]; - if (top < bottom) { - top += sums[j]; - tops.push(j); - } else { - bottom += sums[j]; - bottoms.push(j); + function d3_geom_voronoiAttachCircle(arc) { + var lArc = arc.P, rArc = arc.N; + if (!lArc || !rArc) return; + var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; + if (lSite === rSite) return; + var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; + var d = 2 * (ax * cy - ay * cx); + if (d >= -ε2) return; + var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; + var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = cy + Math.sqrt(x * x + y * y); + circle.cy = cy; + arc.circle = circle; + var before = null, node = d3_geom_voronoiCircles._; + while (node) { + if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { + if (node.L) node = node.L; else { + before = node.P; + break; + } + } else { + if (node.R) node = node.R; else { + before = node; + break; } } - return bottoms.reverse().concat(tops); - }, - reverse: function(data) { - return d3.range(data.length).reverse(); - }, - "default": d3_layout_stackOrderDefault - }); - var d3_layout_stackOffsets = d3.map({ - silhouette: function(data) { - var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o > max) max = o; - sums.push(o); + } + d3_geom_voronoiCircles.insert(before, circle); + if (!before) d3_geom_voronoiFirstCircle = circle; + } + function d3_geom_voronoiDetachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; + d3_geom_voronoiCircles.remove(circle); + d3_geom_voronoiCirclePool.push(circle); + d3_geom_voronoiRedBlackNode(circle); + arc.circle = null; + } + } + function d3_geom_voronoiClipEdges(extent) { + var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; + while (i--) { + e = edges[i]; + if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { + e.a = e.b = null; + edges.splice(i, 1); } - for (j = 0; j < m; ++j) { - y0[j] = (max - sums[j]) / 2; + } + } + function d3_geom_voronoiConnectEdge(edge, extent) { + var vb = edge.b; + if (vb) return true; + var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!va) va = { + x: fx, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: fx, + y: y1 + }; + } else { + if (!va) va = { + x: fx, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: fx, + y: y0 + }; } - return y0; - }, - wiggle: function(data) { - var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; - y0[0] = o = o0 = 0; - for (j = 1; j < m; ++j) { - for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; - for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { - for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { - s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; - } - s2 += s3 * data[i][j][1]; + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!va) va = { + x: (y0 - fb) / fm, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: (y1 - fb) / fm, + y: y1 + }; + } else { + if (!va) va = { + x: (y1 - fb) / fm, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: (y0 - fb) / fm, + y: y0 + }; + } + } else { + if (ly < ry) { + if (!va) va = { + x: x0, + y: fm * x0 + fb + }; else if (va.x >= x1) return; + vb = { + x: x1, + y: fm * x1 + fb + }; + } else { + if (!va) va = { + x: x1, + y: fm * x1 + fb + }; else if (va.x < x0) return; + vb = { + x: x0, + y: fm * x0 + fb + }; } - y0[j] = o -= s1 ? s2 / s1 * dx : 0; - if (o < o0) o0 = o; - } - for (j = 0; j < m; ++j) y0[j] -= o0; - return y0; - }, - expand: function(data) { - var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; - for (j = 0; j < m; ++j) { - for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; - if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; - } - for (j = 0; j < m; ++j) y0[j] = 0; - return y0; - }, - zero: d3_layout_stackOffsetZero - }); - function d3_layout_stackOrderDefault(data) { - return d3.range(data.length); - } - function d3_layout_stackOffsetZero(data) { - var j = -1, m = data[0].length, y0 = []; - while (++j < m) y0[j] = 0; - return y0; - } - function d3_layout_stackMaxIndex(array) { - var i = 1, j = 0, v = array[0][1], k, n = array.length; - for (;i < n; ++i) { - if ((k = array[i][1]) > v) { - j = i; - v = k; } } - return j; + edge.a = va; + edge.b = vb; + return true; } - function d3_layout_stackReduceSum(d) { - return d.reduce(d3_layout_stackSum, 0); + function d3_geom_voronoiEdge(lSite, rSite) { + this.l = lSite; + this.r = rSite; + this.a = this.b = null; } - function d3_layout_stackSum(p, d) { - return p + d[1]; + function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, rSite); + d3_geom_voronoiEdges.push(edge); + if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); + if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); + d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); + d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); + return edge; } - d3.layout.histogram = function() { - var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; - function histogram(data, i) { - var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; - while (++i < m) { - bin = bins[i] = []; - bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); - bin.y = 0; - } - if (m > 0) { - i = -1; - while (++i < n) { - x = values[i]; - if (x >= range[0] && x <= range[1]) { - bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; - bin.y += k; - bin.push(data[i]); - } - } - } - return bins; - } - histogram.value = function(x) { - if (!arguments.length) return valuer; - valuer = x; - return histogram; - }; - histogram.range = function(x) { - if (!arguments.length) return ranger; - ranger = d3_functor(x); - return histogram; - }; - histogram.bins = function(x) { - if (!arguments.length) return binner; - binner = typeof x === "number" ? function(range) { - return d3_layout_histogramBinFixed(range, x); - } : d3_functor(x); - return histogram; - }; - histogram.frequency = function(x) { - if (!arguments.length) return frequency; - frequency = !!x; - return histogram; - }; - return histogram; - }; - function d3_layout_histogramBinSturges(range, values) { - return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); + function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, null); + edge.a = va; + edge.b = vb; + d3_geom_voronoiEdges.push(edge); + return edge; } - function d3_layout_histogramBinFixed(range, n) { - var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; - while (++x <= n) f[x] = m * x + b; - return f; + function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { + if (!edge.a && !edge.b) { + edge.a = vertex; + edge.l = lSite; + edge.r = rSite; + } else if (edge.l === rSite) { + edge.b = vertex; + } else { + edge.a = vertex; + } } - function d3_layout_histogramRange(values) { - return [ d3.min(values), d3.max(values) ]; + function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { + var va = edge.a, vb = edge.b; + this.edge = edge; + this.site = lSite; + this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); } - d3.layout.pack = function() { - var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; - function pack(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { - return radius; - }; - root.x = root.y = 0; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r = +r(d.value); - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - if (padding) { - var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r += dr; - }); - d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); - d3_layout_hierarchyVisitAfter(root, function(d) { - d.r -= dr; - }); - } - d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); - return nodes; + d3_geom_voronoiHalfEdge.prototype = { + start: function() { + return this.edge.l === this.site ? this.edge.a : this.edge.b; + }, + end: function() { + return this.edge.l === this.site ? this.edge.b : this.edge.a; } - pack.size = function(_) { - if (!arguments.length) return size; - size = _; - return pack; - }; - pack.radius = function(_) { - if (!arguments.length) return radius; - radius = _ == null || typeof _ === "function" ? _ : +_; - return pack; - }; - pack.padding = function(_) { - if (!arguments.length) return padding; - padding = +_; - return pack; - }; - return d3_layout_hierarchyRebind(pack, hierarchy); }; - function d3_layout_packSort(a, b) { - return a.value - b.value; - } - function d3_layout_packInsert(a, b) { - var c = a._pack_next; - a._pack_next = b; - b._pack_prev = a; - b._pack_next = c; - c._pack_prev = b; - } - function d3_layout_packSplice(a, b) { - a._pack_next = b; - b._pack_prev = a; + function d3_geom_voronoiRedBlackTree() { + this._ = null; } - function d3_layout_packIntersects(a, b) { - var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; - return .999 * dr * dr > dx * dx + dy * dy; + function d3_geom_voronoiRedBlackNode(node) { + node.U = node.C = node.L = node.R = node.P = node.N = null; } - function d3_layout_packSiblings(node) { - if (!(nodes = node.children) || !(n = nodes.length)) return; - var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; - function bound(node) { - xMin = Math.min(node.x - node.r, xMin); - xMax = Math.max(node.x + node.r, xMax); - yMin = Math.min(node.y - node.r, yMin); - yMax = Math.max(node.y + node.r, yMax); - } - nodes.forEach(d3_layout_packLink); - a = nodes[0]; - a.x = -a.r; - a.y = 0; - bound(a); - if (n > 1) { - b = nodes[1]; - b.x = b.r; - b.y = 0; - bound(b); - if (n > 2) { - c = nodes[2]; - d3_layout_packPlace(a, b, c); - bound(c); - d3_layout_packInsert(a, c); - a._pack_prev = c; - d3_layout_packInsert(c, b); - b = a._pack_next; - for (i = 3; i < n; i++) { - d3_layout_packPlace(a, b, c = nodes[i]); - var isect = 0, s1 = 1, s2 = 1; - for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { - if (d3_layout_packIntersects(j, c)) { - isect = 1; - break; - } - } - if (isect == 1) { - for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { - if (d3_layout_packIntersects(k, c)) { - break; - } + d3_geom_voronoiRedBlackTree.prototype = { + insert: function(after, node) { + var parent, grandpa, uncle; + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = d3_geom_voronoiRedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + d3_geom_voronoiRedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateRight(this, grandpa); } - if (isect) { - if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); - i--; + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; } else { - d3_layout_packInsert(a, c); - b = c; - bound(c); + if (after === parent.L) { + d3_geom_voronoiRedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, grandpa); } } + parent = after.U; } - } - var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; - for (i = 0; i < n; i++) { - c = nodes[i]; - c.x -= cx; - c.y -= cy; - cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); - } - node.r = cr; - nodes.forEach(d3_layout_packUnlink); - } - function d3_layout_packLink(node) { - node._pack_next = node._pack_prev = node; - } - function d3_layout_packUnlink(node) { - delete node._pack_next; - delete node._pack_prev; - } - function d3_layout_packTransform(node, x, y, k) { - var children = node.children; - node.x = x += k * node.x; - node.y = y += k * node.y; - node.r *= k; - if (children) { - var i = -1, n = children.length; - while (++i < n) d3_layout_packTransform(children[i], x, y, k); - } - } - function d3_layout_packPlace(a, b, c) { - var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; - if (db && (dx || dy)) { - var da = b.r + c.r, dc = dx * dx + dy * dy; - da *= da; - db *= db; - var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); - c.x = a.x + x * dx + y * dy; - c.y = a.y + x * dy - y * dx; - } else { - c.x = a.x + db; - c.y = a.y; - } - } - d3.layout.tree = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; - function tree(d, i) { - var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); - d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; - d3_layout_hierarchyVisitBefore(root1, secondWalk); - if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { - var left = root0, right = root0, bottom = root0; - d3_layout_hierarchyVisitBefore(root0, function(node) { - if (node.x < left.x) left = node; - if (node.x > right.x) right = node; - if (node.depth > bottom.depth) bottom = node; - }); - var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); - d3_layout_hierarchyVisitBefore(root0, function(node) { - node.x = (node.x + tx) * kx; - node.y = node.depth * ky; - }); - } - return nodes; - } - function wrapTree(root0) { - var root1 = { - A: null, - children: [ root0 ] - }, queue = [ root1 ], node1; - while ((node1 = queue.pop()) != null) { - for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { - queue.push((children[i] = child = { - _: children[i], - parent: node1, - children: (child = children[i].children) && child.slice() || [], - A: null, - a: null, - z: 0, - m: 0, - c: 0, - s: 0, - t: null, - i: i - }).a = child); - } + this._.C = false; + }, + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + var parent = node.U, sibling, left = node.L, right = node.R, next, red; + if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); + if (parent) { + if (parent.L === node) parent.L = next; else parent.R = next; + } else { + this._ = next; } - return root1.children[0]; - } - function firstWalk(v) { - var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; - if (children.length) { - d3_layout_treeShift(v); - var midpoint = (children[0].z + children[children.length - 1].z) / 2; - if (w) { - v.z = w.z + separation(v._, w._); - v.m = v.z - midpoint; + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; } else { - v.z = midpoint; + next.U = parent; + parent = next; + node = next.R; } - } else if (w) { - v.z = w.z + separation(v._, w._); + } else { + red = node.C; + node = next; } - v.parent.A = apportion(v, w, v.parent.A || siblings[0]); - } - function secondWalk(v) { - v._.x = v.z + v.parent.m; - v.m += v.parent.m; - } - function apportion(v, w, ancestor) { - if (w) { - var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; - while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { - vom = d3_layout_treeLeft(vom); - vop = d3_layout_treeRight(vop); - vop.a = v; - shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); - if (shift > 0) { - d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); - sip += shift; - sop += shift; - } - sim += vim.m; - sip += vip.m; - som += vom.m; - sop += vop.m; - } - if (vim && !d3_layout_treeRight(vop)) { - vop.t = vim; - vop.m += sim - sop; - } - if (vip && !d3_layout_treeLeft(vom)) { - vom.t = vip; - vom.m += sip - som; - ancestor = v; - } + if (node) node.U = parent; + if (red) return; + if (node && node.C) { + node.C = false; + return; } - return ancestor; - } - function sizeNode(node) { - node.x *= size[0]; - node.y = node.depth * size[1]; + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateRight(this, parent); + sibling = parent.L; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + d3_geom_voronoiRedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + if (node) node.C = false; } - tree.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return tree; - }; - tree.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null ? sizeNode : null; - return tree; - }; - tree.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) == null ? null : sizeNode; - return tree; - }; - return d3_layout_hierarchyRebind(tree, hierarchy); }; - function d3_layout_treeSeparation(a, b) { - return a.parent == b.parent ? 1 : 2; - } - function d3_layout_treeLeft(v) { - var children = v.children; - return children.length ? children[0] : v.t; + function d3_geom_voronoiRedBlackRotateLeft(tree, node) { + var p = node, q = node.R, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; } - function d3_layout_treeRight(v) { - var children = v.children, n; - return (n = children.length) ? children[n - 1] : v.t; + function d3_geom_voronoiRedBlackRotateRight(tree, node) { + var p = node, q = node.L, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; } - function d3_layout_treeMove(wm, wp, shift) { - var change = shift / (wp.i - wm.i); - wp.c -= change; - wp.s += shift; - wm.c += change; - wp.z += shift; - wp.m += shift; + function d3_geom_voronoiRedBlackFirst(node) { + while (node.L) node = node.L; + return node; } - function d3_layout_treeShift(v) { - var shift = 0, change = 0, children = v.children, i = children.length, w; - while (--i >= 0) { - w = children[i]; - w.z += shift; - w.m += shift; - shift += w.s + (change += w.c); + function d3_geom_voronoi(sites, bbox) { + var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; + d3_geom_voronoiEdges = []; + d3_geom_voronoiCells = new Array(sites.length); + d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); + d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); + while (true) { + circle = d3_geom_voronoiFirstCircle; + if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { + if (site.x !== x0 || site.y !== y0) { + d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); + d3_geom_voronoiAddBeach(site); + x0 = site.x, y0 = site.y; + } + site = sites.pop(); + } else if (circle) { + d3_geom_voronoiRemoveBeach(circle.arc); + } else { + break; + } } + if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); + var diagram = { + cells: d3_geom_voronoiCells, + edges: d3_geom_voronoiEdges + }; + d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; + return diagram; } - function d3_layout_treeAncestor(vim, v, ancestor) { - return vim.a.parent === v.parent ? vim.a : ancestor; + function d3_geom_voronoiVertexOrder(a, b) { + return b.y - a.y || b.x - a.x; } - d3.layout.cluster = function() { - var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; - function cluster(d, i) { - var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; - d3_layout_hierarchyVisitAfter(root, function(node) { - var children = node.children; - if (children && children.length) { - node.x = d3_layout_clusterX(children); - node.y = d3_layout_clusterY(children); - } else { - node.x = previousNode ? x += separation(node, previousNode) : 0; - node.y = 0; - previousNode = node; - } + d3.geom.voronoi = function(points) { + var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; + if (points) return voronoi(points); + function voronoi(data) { + var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; + d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { + var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { + var s = e.start(); + return [ s.x, s.y ]; + }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; + polygon.point = data[i]; }); - var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; - d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { - node.x = (node.x - root.x) * size[0]; - node.y = (root.y - node.y) * size[1]; - } : function(node) { - node.x = (node.x - x0) / (x1 - x0) * size[0]; - node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + return polygons; + } + function sites(data) { + return data.map(function(d, i) { + return { + x: Math.round(fx(d, i) / ε) * ε, + y: Math.round(fy(d, i) / ε) * ε, + i: i + }; }); - return nodes; } - cluster.separation = function(x) { - if (!arguments.length) return separation; - separation = x; - return cluster; + voronoi.links = function(data) { + return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { + return edge.l && edge.r; + }).map(function(edge) { + return { + source: data[edge.l.i], + target: data[edge.r.i] + }; + }); }; - cluster.size = function(x) { - if (!arguments.length) return nodeSize ? null : size; - nodeSize = (size = x) == null; - return cluster; + voronoi.triangles = function(data) { + var triangles = []; + d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { + var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; + while (++j < m) { + e0 = e1; + s0 = s1; + e1 = edges[j].edge; + s1 = e1.l === site ? e1.r : e1.l; + if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { + triangles.push([ data[i], data[s0.i], data[s1.i] ]); + } + } + }); + return triangles; }; - cluster.nodeSize = function(x) { - if (!arguments.length) return nodeSize ? size : null; - nodeSize = (size = x) != null; - return cluster; + voronoi.x = function(_) { + return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; }; - return d3_layout_hierarchyRebind(cluster, hierarchy); + voronoi.y = function(_) { + return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; + }; + voronoi.clipExtent = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; + clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; + return voronoi; + }; + voronoi.size = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; + return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + }; + return voronoi; }; - function d3_layout_clusterY(children) { - return 1 + d3.max(children, function(child) { - return child.y; - }); - } - function d3_layout_clusterX(children) { - return children.reduce(function(x, child) { - return x + child.x; - }, 0) / children.length; - } - function d3_layout_clusterLeft(node) { - var children = node.children; - return children && children.length ? d3_layout_clusterLeft(children[0]) : node; - } - function d3_layout_clusterRight(node) { - var children = node.children, n; - return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; + function d3_geom_voronoiTriangleArea(a, b, c) { + return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); } - d3.layout.treemap = function() { - var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); - function scale(children, k) { - var i = -1, n = children.length, child, area; - while (++i < n) { - area = (child = children[i]).value * (k < 0 ? 0 : k); - child.area = isNaN(area) || area <= 0 ? 0 : area; + d3.geom.delaunay = function(vertices) { + return d3.geom.voronoi().triangles(vertices); + }; + d3.geom.quadtree = function(points, x1, y1, x2, y2) { + var x = d3_geom_pointX, y = d3_geom_pointY, compat; + if (compat = arguments.length) { + x = d3_geom_quadtreeCompatX; + y = d3_geom_quadtreeCompatY; + if (compat === 3) { + y2 = y1; + x2 = x1; + y1 = x1 = 0; } + return quadtree(points); } - function squarify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while ((n = remaining.length) > 0) { - row.push(child = remaining[n - 1]); - row.area += child.area; - if (mode !== "squarify" || (score = worst(row, u)) <= best) { - remaining.pop(); - best = score; - } else { - row.area -= row.pop().area; - position(row, u, rect, false); - u = Math.min(rect.dx, rect.dy); - row.length = row.area = 0; - best = Infinity; - } - } - if (row.length) { - position(row, u, rect, true); - row.length = row.area = 0; + function quadtree(data) { + var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; + if (x1 != null) { + x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; + } else { + x2_ = y2_ = -(x1_ = y1_ = Infinity); + xs = [], ys = []; + n = data.length; + if (compat) for (i = 0; i < n; ++i) { + d = data[i]; + if (d.x < x1_) x1_ = d.x; + if (d.y < y1_) y1_ = d.y; + if (d.x > x2_) x2_ = d.x; + if (d.y > y2_) y2_ = d.y; + xs.push(d.x); + ys.push(d.y); + } else for (i = 0; i < n; ++i) { + var x_ = +fx(d = data[i], i), y_ = +fy(d, i); + if (x_ < x1_) x1_ = x_; + if (y_ < y1_) y1_ = y_; + if (x_ > x2_) x2_ = x_; + if (y_ > y2_) y2_ = y_; + xs.push(x_); + ys.push(y_); } - children.forEach(squarify); } - } - function stickify(node) { - var children = node.children; - if (children && children.length) { - var rect = pad(node), remaining = children.slice(), child, row = []; - scale(remaining, rect.dx * rect.dy / node.value); - row.area = 0; - while (child = remaining.pop()) { - row.push(child); - row.area += child.area; - if (child.z != null) { - position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); - row.length = row.area = 0; + var dx = x2_ - x1_, dy = y2_ - y1_; + if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; + function insert(n, d, x, y, x1, y1, x2, y2) { + if (isNaN(x) || isNaN(y)) return; + if (n.leaf) { + var nx = n.x, ny = n.y; + if (nx != null) { + if (abs(nx - x) + abs(ny - y) < .01) { + insertChild(n, d, x, y, x1, y1, x2, y2); + } else { + var nPoint = n.point; + n.x = n.y = n.point = null; + insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } else { + n.x = x, n.y = y, n.point = d; } + } else { + insertChild(n, d, x, y, x1, y1, x2, y2); } - children.forEach(stickify); } - } - function worst(row, u) { - var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; - while (++i < n) { - if (!(r = row[i].area)) continue; - if (r < rmin) rmin = r; - if (r > rmax) rmax = r; + function insertChild(n, d, x, y, x1, y1, x2, y2) { + var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right; + n.leaf = false; + n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); + if (right) x1 = xm; else x2 = xm; + if (below) y1 = ym; else y2 = ym; + insert(n, d, x, y, x1, y1, x2, y2); } - s *= s; - u *= u; - return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; - } - function position(row, u, rect, flush) { - var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; - if (u == rect.dx) { - if (flush || v > rect.dy) v = rect.dy; - while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dy = v; - x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); - } - o.z = true; - o.dx += rect.x + rect.dx - x; - rect.y += v; - rect.dy -= v; - } else { - if (flush || v > rect.dx) v = rect.dx; + var root = d3_geom_quadtreeNode(); + root.add = function(d) { + insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); + }; + root.visit = function(f) { + d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); + }; + root.find = function(point) { + return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_); + }; + i = -1; + if (x1 == null) { while (++i < n) { - o = row[i]; - o.x = x; - o.y = y; - o.dx = v; - y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); + insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); } - o.z = false; - o.dy += rect.y + rect.dy - y; - rect.x += v; - rect.dx -= v; - } - } - function treemap(d) { - var nodes = stickies || hierarchy(d), root = nodes[0]; - root.x = 0; - root.y = 0; - root.dx = size[0]; - root.dy = size[1]; - if (stickies) hierarchy.revalue(root); - scale([ root ], root.dx * root.dy / root.value); - (stickies ? stickify : squarify)(root); - if (sticky) stickies = nodes; - return nodes; + --i; + } else data.forEach(root.add); + xs = ys = data = d = null; + return root; } - treemap.size = function(x) { - if (!arguments.length) return size; - size = x; - return treemap; + quadtree.x = function(_) { + return arguments.length ? (x = _, quadtree) : x; }; - treemap.padding = function(x) { - if (!arguments.length) return padding; - function padFunction(node) { - var p = x.call(treemap, node, node.depth); - return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); - } - function padConstant(node) { - return d3_layout_treemapPad(node, x); - } - var type; - pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], - padConstant) : padConstant; - return treemap; + quadtree.y = function(_) { + return arguments.length ? (y = _, quadtree) : y; }; - treemap.round = function(x) { - if (!arguments.length) return round != Number; - round = x ? Math.round : Number; - return treemap; + quadtree.extent = function(_) { + if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], + y2 = +_[1][1]; + return quadtree; }; - treemap.sticky = function(x) { - if (!arguments.length) return sticky; - sticky = x; - stickies = null; - return treemap; + quadtree.size = function(_) { + if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; + return quadtree; }; - treemap.ratio = function(x) { - if (!arguments.length) return ratio; - ratio = x; - return treemap; + return quadtree; + }; + function d3_geom_quadtreeCompatX(d) { + return d.x; + } + function d3_geom_quadtreeCompatY(d) { + return d.y; + } + function d3_geom_quadtreeNode() { + return { + leaf: true, + nodes: [], + point: null, + x: null, + y: null }; - treemap.mode = function(x) { - if (!arguments.length) return mode; - mode = x + ""; - return treemap; + } + function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { + if (!f(node, x1, y1, x2, y2)) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; + if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); + if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); + if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); + if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); + } + } + function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) { + var minDistance2 = Infinity, closestPoint; + (function find(node, x1, y1, x2, y2) { + if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return; + if (point = node.point) { + var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy; + if (distance2 < minDistance2) { + var distance = Math.sqrt(minDistance2 = distance2); + x0 = x - distance, y0 = y - distance; + x3 = x + distance, y3 = y + distance; + closestPoint = point; + } + } + var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym; + for (var i = below << 1 | right, j = i + 4; i < j; ++i) { + if (node = children[i & 3]) switch (i & 3) { + case 0: + find(node, x1, y1, xm, ym); + break; + + case 1: + find(node, xm, y1, x2, ym); + break; + + case 2: + find(node, x1, ym, xm, y2); + break; + + case 3: + find(node, xm, ym, x2, y2); + break; + } + } + })(root, x0, y0, x3, y3); + return closestPoint; + } + d3.interpolateRgb = d3_interpolateRgb; + function d3_interpolateRgb(a, b) { + a = d3.rgb(a); + b = d3.rgb(b); + var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; + return function(t) { + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + }; + } + d3.interpolateObject = d3_interpolateObject; + function d3_interpolateObject(a, b) { + var i = {}, c = {}, k; + for (k in a) { + if (k in b) { + i[k] = d3_interpolate(a[k], b[k]); + } else { + c[k] = a[k]; + } + } + for (k in b) { + if (!(k in a)) { + c[k] = b[k]; + } + } + return function(t) { + for (k in i) c[k] = i[k](t); + return c; }; - return d3_layout_hierarchyRebind(treemap, hierarchy); - }; - function d3_layout_treemapPadNull(node) { - return { - x: node.x, - y: node.y, - dx: node.dx, - dy: node.dy + } + d3.interpolateNumber = d3_interpolateNumber; + function d3_interpolateNumber(a, b) { + a = +a, b = +b; + return function(t) { + return a * (1 - t) + b * t; }; } - function d3_layout_treemapPad(node, padding) { - var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; - if (dx < 0) { - x += dx / 2; - dx = 0; + d3.interpolateString = d3_interpolateString; + function d3_interpolateString(a, b) { + var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a = a + "", b = b + ""; + while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) s[i] += bm; else s[++i] = bm; + } else { + s[++i] = null; + q.push({ + i: i, + x: d3_interpolateNumber(am, bm) + }); + } + bi = d3_interpolate_numberB.lastIndex; } - if (dy < 0) { - y += dy / 2; - dy = 0; + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; else s[++i] = bs; } - return { - x: x, - y: y, - dx: dx, - dy: dy + return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { + return b(t) + ""; + }) : function() { + return b; + } : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); + d3.interpolate = d3_interpolate; + function d3_interpolate(a, b) { + var i = d3.interpolators.length, f; + while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; + return f; + } + d3.interpolators = [ function(a, b) { + var t = typeof b; + return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); + } ]; + d3.interpolateArray = d3_interpolateArray; + function d3_interpolateArray(a, b) { + var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; + for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); + for (;i < na; ++i) c[i] = a[i]; + for (;i < nb; ++i) c[i] = b[i]; + return function(t) { + for (i = 0; i < n0; ++i) c[i] = x[i](t); + return c; }; } - d3.random = { - normal: function(µ, σ) { - var n = arguments.length; - if (n < 2) σ = 1; - if (n < 1) µ = 0; - return function() { - var x, y, r; - do { - x = Math.random() * 2 - 1; - y = Math.random() * 2 - 1; - r = x * x + y * y; - } while (!r || r > 1); - return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); - }; + var d3_ease_default = function() { + return d3_identity; + }; + var d3_ease = d3.map({ + linear: d3_ease_default, + poly: d3_ease_poly, + quad: function() { + return d3_ease_quad; }, - logNormal: function() { - var random = d3.random.normal.apply(d3, arguments); - return function() { - return Math.exp(random()); - }; + cubic: function() { + return d3_ease_cubic; }, - bates: function(m) { - var random = d3.random.irwinHall(m); - return function() { - return random() / m; - }; + sin: function() { + return d3_ease_sin; }, - irwinHall: function(m) { - return function() { - for (var s = 0, j = 0; j < m; j++) s += Math.random(); - return s; - }; + exp: function() { + return d3_ease_exp; + }, + circle: function() { + return d3_ease_circle; + }, + elastic: d3_ease_elastic, + back: d3_ease_back, + bounce: function() { + return d3_ease_bounce; } + }); + var d3_ease_mode = d3.map({ + "in": d3_identity, + out: d3_ease_reverse, + "in-out": d3_ease_reflect, + "out-in": function(f) { + return d3_ease_reflect(d3_ease_reverse(f)); + } + }); + d3.ease = function(name) { + var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in"; + t = d3_ease.get(t) || d3_ease_default; + m = d3_ease_mode.get(m) || d3_identity; + return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); }; - d3.scale = {}; - function d3_scaleExtent(domain) { - var start = domain[0], stop = domain[domain.length - 1]; - return start < stop ? [ start, stop ] : [ stop, start ]; + function d3_ease_clamp(f) { + return function(t) { + return t <= 0 ? 0 : t >= 1 ? 1 : f(t); + }; } - function d3_scaleRange(scale) { - return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + function d3_ease_reverse(f) { + return function(t) { + return 1 - f(1 - t); + }; } - function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { - var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); - return function(x) { - return i(u(x)); + function d3_ease_reflect(f) { + return function(t) { + return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); }; } - function d3_scale_nice(domain, nice) { - var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; - if (x1 < x0) { - dx = i0, i0 = i1, i1 = dx; - dx = x0, x0 = x1, x1 = dx; - } - domain[i0] = nice.floor(x0); - domain[i1] = nice.ceil(x1); - return domain; + function d3_ease_quad(t) { + return t * t; } - function d3_scale_niceStep(step) { - return step ? { - floor: function(x) { - return Math.floor(x / step) * step; - }, - ceil: function(x) { - return Math.ceil(x / step) * step; - } - } : d3_scale_niceIdentity; + function d3_ease_cubic(t) { + return t * t * t; } - var d3_scale_niceIdentity = { - floor: d3_identity, - ceil: d3_identity + function d3_ease_cubicInOut(t) { + if (t <= 0) return 0; + if (t >= 1) return 1; + var t2 = t * t, t3 = t2 * t; + return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + } + function d3_ease_poly(e) { + return function(t) { + return Math.pow(t, e); + }; + } + function d3_ease_sin(t) { + return 1 - Math.cos(t * halfπ); + } + function d3_ease_exp(t) { + return Math.pow(2, 10 * (t - 1)); + } + function d3_ease_circle(t) { + return 1 - Math.sqrt(1 - t * t); + } + function d3_ease_elastic(a, p) { + var s; + if (arguments.length < 2) p = .45; + if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4; + return function(t) { + return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p); + }; + } + function d3_ease_back(s) { + if (!s) s = 1.70158; + return function(t) { + return t * t * ((s + 1) * t - s); + }; + } + function d3_ease_bounce(t) { + return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; + } + d3.interpolateHcl = d3_interpolateHcl; + function d3_interpolateHcl(a, b) { + a = d3.hcl(a); + b = d3.hcl(b); + var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; + if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + }; + } + d3.interpolateHsl = d3_interpolateHsl; + function d3_interpolateHsl(a, b) { + a = d3.hsl(a); + b = d3.hsl(b); + var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; + if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + }; + } + d3.interpolateLab = d3_interpolateLab; + function d3_interpolateLab(a, b) { + a = d3.lab(a); + b = d3.lab(b); + var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; + return function(t) { + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + }; + } + d3.interpolateRound = d3_interpolateRound; + function d3_interpolateRound(a, b) { + b -= a; + return function(t) { + return Math.round(a + b * t); + }; + } + d3.transform = function(string) { + var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); + return (d3.transform = function(string) { + if (string != null) { + g.setAttribute("transform", string); + var t = g.transform.baseVal.consolidate(); + } + return new d3_transform(t ? t.matrix : d3_transformIdentity); + })(string); }; - function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { - var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; - if (domain[k] < domain[0]) { - domain = domain.slice().reverse(); - range = range.slice().reverse(); + function d3_transform(m) { + var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; + if (r0[0] * r1[1] < r1[0] * r0[1]) { + r0[0] *= -1; + r0[1] *= -1; + kx *= -1; + kz *= -1; } - while (++j <= k) { - u.push(uninterpolate(domain[j - 1], domain[j])); - i.push(interpolate(range[j - 1], range[j])); + this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; + this.translate = [ m.e, m.f ]; + this.scale = [ kx, ky ]; + this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + } + d3_transform.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + }; + function d3_transformDot(a, b) { + return a[0] * b[0] + a[1] * b[1]; + } + function d3_transformNormalize(a) { + var k = Math.sqrt(d3_transformDot(a, a)); + if (k) { + a[0] /= k; + a[1] /= k; } - return function(x) { - var j = d3.bisect(domain, x, 1, k) - 1; - return i[j](u[j](x)); - }; + return k; } - d3.scale.linear = function() { - return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + function d3_transformCombine(a, b, k) { + a[0] += k * b[0]; + a[1] += k * b[1]; + return a; + } + var d3_transformIdentity = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 }; - function d3_scale_linear(domain, range, interpolate, clamp) { - var output, input; - function rescale() { - var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; - output = linear(domain, range, uninterpolate, interpolate); - input = linear(range, domain, uninterpolate, d3_interpolate); - return scale; + d3.interpolateTransform = d3_interpolateTransform; + function d3_interpolateTransformPop(s) { + return s.length ? s.pop() + "," : ""; + } + function d3_interpolateTranslate(ta, tb, s, q) { + if (ta[0] !== tb[0] || ta[1] !== tb[1]) { + var i = s.push("translate(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ta[0], tb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ta[1], tb[1]) + }); + } else if (tb[0] || tb[1]) { + s.push("translate(" + tb + ")"); } - function scale(x) { - return output(x); + } + function d3_interpolateRotate(ra, rb, s, q) { + if (ra !== rb) { + if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2, + x: d3_interpolateNumber(ra, rb) + }); + } else if (rb) { + s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")"); } - scale.invert = function(y) { - return input(y); + } + function d3_interpolateSkew(wa, wb, s, q) { + if (wa !== wb) { + q.push({ + i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2, + x: d3_interpolateNumber(wa, wb) + }); + } else if (wb) { + s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")"); + } + } + function d3_interpolateScale(ka, kb, s, q) { + if (ka[0] !== kb[0] || ka[1] !== kb[1]) { + var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")"); + q.push({ + i: i - 4, + x: d3_interpolateNumber(ka[0], kb[0]) + }, { + i: i - 2, + x: d3_interpolateNumber(ka[1], kb[1]) + }); + } else if (kb[0] !== 1 || kb[1] !== 1) { + s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")"); + } + } + function d3_interpolateTransform(a, b) { + var s = [], q = []; + a = d3.transform(a), b = d3.transform(b); + d3_interpolateTranslate(a.translate, b.translate, s, q); + d3_interpolateRotate(a.rotate, b.rotate, s, q); + d3_interpolateSkew(a.skew, b.skew, s, q); + d3_interpolateScale(a.scale, b.scale, s, q); + a = b = null; + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); }; - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(Number); - return rescale(); + } + function d3_uninterpolateNumber(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return (x - a) / b; }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); + } + function d3_uninterpolateClamp(a, b) { + b = (b -= a = +a) || 1 / b; + return function(x) { + return Math.max(0, Math.min(1, (x - a) / b)); }; - scale.rangeRound = function(x) { - return scale.range(x).interpolate(d3_interpolateRound); + } + d3.layout = {}; + d3.layout.bundle = function() { + return function(links) { + var paths = [], i = -1, n = links.length; + while (++i < n) paths.push(d3_layout_bundlePath(links[i])); + return paths; + }; + }; + function d3_layout_bundlePath(link) { + var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; + while (start !== lca) { + start = start.parent; + points.push(start); + } + var k = points.length; + while (end !== lca) { + points.splice(k, 0, end); + end = end.parent; + } + return points; + } + function d3_layout_bundleAncestors(node) { + var ancestors = [], parent = node.parent; + while (parent != null) { + ancestors.push(node); + node = parent; + parent = parent.parent; + } + ancestors.push(node); + return ancestors; + } + function d3_layout_bundleLeastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; + while (aNode === bNode) { + sharedNode = aNode; + aNode = aNodes.pop(); + bNode = bNodes.pop(); + } + return sharedNode; + } + d3.layout.chord = function() { + var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; + function relayout() { + var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; + chords = []; + groups = []; + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3.range(n)); + k += x; + } + if (sortGroups) { + groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + } + if (sortSubgroups) { + subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + } + k = (τ - padding * n) / k; + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; + subgroups[di + "-" + dj] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += padding; + } + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; + if (source.value || target.value) { + chords.push(source.value < target.value ? { + source: target, + target: source + } : { + source: source, + target: target + }); + } + } + } + if (sortChords) resort(); + } + function resort() { + chords.sort(function(a, b) { + return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); + }); + } + chord.matrix = function(x) { + if (!arguments.length) return matrix; + n = (matrix = x) && matrix.length; + chords = groups = null; + return chord; }; - scale.clamp = function(x) { - if (!arguments.length) return clamp; - clamp = x; - return rescale(); + chord.padding = function(x) { + if (!arguments.length) return padding; + padding = x; + chords = groups = null; + return chord; }; - scale.interpolate = function(x) { - if (!arguments.length) return interpolate; - interpolate = x; - return rescale(); + chord.sortGroups = function(x) { + if (!arguments.length) return sortGroups; + sortGroups = x; + chords = groups = null; + return chord; }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); + chord.sortSubgroups = function(x) { + if (!arguments.length) return sortSubgroups; + sortSubgroups = x; + chords = null; + return chord; }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); + chord.sortChords = function(x) { + if (!arguments.length) return sortChords; + sortChords = x; + if (chords) resort(); + return chord; }; - scale.nice = function(m) { - d3_scale_linearNice(domain, m); - return rescale(); + chord.chords = function() { + if (!chords) relayout(); + return chords; }; - scale.copy = function() { - return d3_scale_linear(domain, range, interpolate, clamp); + chord.groups = function() { + if (!groups) relayout(); + return groups; }; - return rescale(); - } - function d3_scale_linearRebind(scale, linear) { - return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); - } - function d3_scale_linearNice(domain, m) { - return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); - } - function d3_scale_linearTickRange(domain, m) { - if (m == null) m = 10; - var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; - if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; - extent[0] = Math.ceil(extent[0] / step) * step; - extent[1] = Math.floor(extent[1] / step) * step + step * .5; - extent[2] = step; - return extent; - } - function d3_scale_linearTicks(domain, m) { - return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); - } - function d3_scale_linearTickFormat(domain, m, format) { - var range = d3_scale_linearTickRange(domain, m); - if (format) { - var match = d3_format_re.exec(format); - match.shift(); - if (match[8] === "s") { - var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); - if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); - match[8] = "f"; - format = d3.format(match.join("")); - return function(d) { - return format(prefix.scale(d)) + prefix.symbol; - }; - } - if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); - format = match.join(""); - } else { - format = ",." + d3_scale_linearPrecision(range[2]) + "f"; - } - return d3.format(format); - } - var d3_scale_linearFormatSignificant = { - s: 1, - g: 1, - p: 1, - r: 1, - e: 1 - }; - function d3_scale_linearPrecision(value) { - return -Math.floor(Math.log(value) / Math.LN10 + .01); - } - function d3_scale_linearFormatPrecision(type, range) { - var p = d3_scale_linearPrecision(range[2]); - return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; - } - d3.scale.log = function() { - return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); + return chord; }; - function d3_scale_log(linear, base, positive, domain) { - function log(x) { - return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); - } - function pow(x) { - return positive ? Math.pow(base, x) : -Math.pow(base, -x); - } - function scale(x) { - return linear(log(x)); + d3.layout.force = function() { + var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; + function repulse(node) { + return function(quad, x1, _, x2) { + if (quad.point !== node) { + var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; + if (dw * dw / theta2 < dn) { + if (dn < chargeDistance2) { + var k = quad.charge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + return true; + } + if (quad.point && dn && dn < chargeDistance2) { + var k = quad.pointCharge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + } + return !quad.charge; + }; } - scale.invert = function(x) { - return pow(linear.invert(x)); - }; - scale.domain = function(x) { - if (!arguments.length) return domain; - positive = x[0] >= 0; - linear.domain((domain = x.map(Number)).map(log)); - return scale; - }; - scale.base = function(_) { - if (!arguments.length) return base; - base = +_; - linear.domain(domain.map(log)); - return scale; - }; - scale.nice = function() { - var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); - linear.domain(niced); - domain = niced.map(pow); - return scale; - }; - scale.ticks = function() { - var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; - if (isFinite(j - i)) { - if (positive) { - for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); - ticks.push(pow(i)); + force.tick = function() { + if ((alpha *= .99) < .005) { + timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + return true; + } + var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; + for (i = 0; i < m; ++i) { + o = links[i]; + s = o.source; + t = o.target; + x = t.x - s.x; + y = t.y - s.y; + if (l = x * x + y * y) { + l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; + x *= l; + y *= l; + t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; + } + } + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; + if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } + } + if (charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); + i = -1; + while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o)); + } + } + } + i = -1; + while (++i < n) { + o = nodes[i]; + if (o.fixed) { + o.x = o.px; + o.y = o.py; } else { - ticks.push(pow(i)); - for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); + o.x -= (o.px - (o.px = o.x)) * friction; + o.y -= (o.py - (o.py = o.y)) * friction; } - for (i = 0; ticks[i] < u; i++) {} - for (j = ticks.length; ticks[j - 1] > v; j--) {} - ticks = ticks.slice(i, j); } - return ticks; + event.tick({ + type: "tick", + alpha: alpha + }); }; - scale.tickFormat = function(n, format) { - if (!arguments.length) return d3_scale_logFormat; - if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); - var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, - Math.floor), e; - return function(d) { - return d / pow(f(log(d) + e)) <= k ? format(d) : ""; - }; + force.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return force; }; - scale.copy = function() { - return d3_scale_log(linear.copy(), base, positive, domain); + force.links = function(x) { + if (!arguments.length) return links; + links = x; + return force; }; - return d3_scale_linearRebind(scale, linear); - } - var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { - floor: function(x) { - return -Math.ceil(-x); - }, - ceil: function(x) { - return -Math.floor(-x); - } - }; - d3.scale.pow = function() { - return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); - }; - function d3_scale_pow(linear, exponent, domain) { - var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); - function scale(x) { - return linear(powp(x)); - } - scale.invert = function(x) { - return powb(linear.invert(x)); + force.size = function(x) { + if (!arguments.length) return size; + size = x; + return force; }; - scale.domain = function(x) { - if (!arguments.length) return domain; - linear.domain((domain = x.map(Number)).map(powp)); - return scale; + force.linkDistance = function(x) { + if (!arguments.length) return linkDistance; + linkDistance = typeof x === "function" ? x : +x; + return force; }; - scale.ticks = function(m) { - return d3_scale_linearTicks(domain, m); + force.distance = force.linkDistance; + force.linkStrength = function(x) { + if (!arguments.length) return linkStrength; + linkStrength = typeof x === "function" ? x : +x; + return force; }; - scale.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); + force.friction = function(x) { + if (!arguments.length) return friction; + friction = +x; + return force; }; - scale.nice = function(m) { - return scale.domain(d3_scale_linearNice(domain, m)); + force.charge = function(x) { + if (!arguments.length) return charge; + charge = typeof x === "function" ? x : +x; + return force; }; - scale.exponent = function(x) { - if (!arguments.length) return exponent; - powp = d3_scale_powPow(exponent = x); - powb = d3_scale_powPow(1 / exponent); - linear.domain(domain.map(powp)); - return scale; + force.chargeDistance = function(x) { + if (!arguments.length) return Math.sqrt(chargeDistance2); + chargeDistance2 = x * x; + return force; }; - scale.copy = function() { - return d3_scale_pow(linear.copy(), exponent, domain); + force.gravity = function(x) { + if (!arguments.length) return gravity; + gravity = +x; + return force; }; - return d3_scale_linearRebind(scale, linear); - } - function d3_scale_powPow(e) { - return function(x) { - return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + force.theta = function(x) { + if (!arguments.length) return Math.sqrt(theta2); + theta2 = x * x; + return force; }; - } - d3.scale.sqrt = function() { - return d3.scale.pow().exponent(.5); - }; - d3.scale.ordinal = function() { - return d3_scale_ordinal([], { - t: "range", - a: [ [] ] - }); - }; - function d3_scale_ordinal(domain, ranger) { - var index, range, rangeBand; - function scale(x) { - return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; - } - function steps(start, step) { - return d3.range(domain.length).map(function(i) { - return start + step * i; - }); - } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = []; - index = new d3_Map(); - var i = -1, n = x.length, xi; - while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); - return scale[ranger.t].apply(scale, ranger.a); + force.alpha = function(x) { + if (!arguments.length) return alpha; + x = +x; + if (alpha) { + if (x > 0) { + alpha = x; + } else { + timer.c = null, timer.t = NaN, timer = null; + event.end({ + type: "end", + alpha: alpha = 0 + }); + } + } else if (x > 0) { + event.start({ + type: "start", + alpha: alpha = x + }); + timer = d3_timer(force.tick); + } + return force; }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - rangeBand = 0; - ranger = { - t: "range", - a: arguments - }; - return scale; + force.start = function() { + var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; + for (i = 0; i < n; ++i) { + (o = nodes[i]).index = i; + o.weight = 0; + } + for (i = 0; i < m; ++i) { + o = links[i]; + if (typeof o.source == "number") o.source = nodes[o.source]; + if (typeof o.target == "number") o.target = nodes[o.target]; + ++o.source.weight; + ++o.target.weight; + } + for (i = 0; i < n; ++i) { + o = nodes[i]; + if (isNaN(o.x)) o.x = position("x", w); + if (isNaN(o.y)) o.y = position("y", h); + if (isNaN(o.px)) o.px = o.x; + if (isNaN(o.py)) o.py = o.y; + } + distances = []; + if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; + strengths = []; + if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; + charges = []; + if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; + function position(dimension, size) { + if (!neighbors) { + neighbors = new Array(n); + for (j = 0; j < n; ++j) { + neighbors[j] = []; + } + for (j = 0; j < m; ++j) { + var o = links[j]; + neighbors[o.source.index].push(o.target); + neighbors[o.target.index].push(o.source); + } + } + var candidates = neighbors[i], j = -1, l = candidates.length, x; + while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x; + return Math.random() * size; + } + return force.resume(); }; - scale.rangePoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, - 0) : (stop - start) / (domain.length - 1 + padding); - range = steps(start + step * padding / 2, step); - rangeBand = 0; - ranger = { - t: "rangePoints", - a: arguments - }; - return scale; + force.resume = function() { + return force.alpha(.1); }; - scale.rangeRoundPoints = function(x, padding) { - if (arguments.length < 2) padding = 0; - var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), - 0) : (stop - start) / (domain.length - 1 + padding) | 0; - range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); - rangeBand = 0; - ranger = { - t: "rangeRoundPoints", - a: arguments - }; - return scale; + force.stop = function() { + return force.alpha(0); }; - scale.rangeBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); - range = steps(start + step * outerPadding, step); - if (reverse) range.reverse(); - rangeBand = step * (1 - padding); - ranger = { - t: "rangeBands", - a: arguments - }; - return scale; + force.drag = function() { + if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); + if (!arguments.length) return drag; + this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); }; - scale.rangeRoundBands = function(x, padding, outerPadding) { - if (arguments.length < 2) padding = 0; - if (arguments.length < 3) outerPadding = padding; - var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); - range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); - if (reverse) range.reverse(); - rangeBand = Math.round(step * (1 - padding)); - ranger = { - t: "rangeRoundBands", - a: arguments - }; - return scale; + function dragmove(d) { + d.px = d3.event.x, d.py = d3.event.y; + force.resume(); + } + return d3.rebind(force, event, "on"); + }; + function d3_layout_forceDragstart(d) { + d.fixed |= 2; + } + function d3_layout_forceDragend(d) { + d.fixed &= ~6; + } + function d3_layout_forceMouseover(d) { + d.fixed |= 4; + d.px = d.x, d.py = d.y; + } + function d3_layout_forceMouseout(d) { + d.fixed &= ~4; + } + function d3_layout_forceAccumulate(quad, alpha, charges) { + var cx = 0, cy = 0; + quad.charge = 0; + if (!quad.leaf) { + var nodes = quad.nodes, n = nodes.length, i = -1, c; + while (++i < n) { + c = nodes[i]; + if (c == null) continue; + d3_layout_forceAccumulate(c, alpha, charges); + quad.charge += c.charge; + cx += c.charge * c.cx; + cy += c.charge * c.cy; + } + } + if (quad.point) { + if (!quad.leaf) { + quad.point.x += Math.random() - .5; + quad.point.y += Math.random() - .5; + } + var k = alpha * charges[quad.point.index]; + quad.charge += quad.pointCharge = k; + cx += k * quad.point.x; + cy += k * quad.point.y; + } + quad.cx = cx / quad.charge; + quad.cy = cy / quad.charge; + } + var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; + d3.layout.hierarchy = function() { + var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; + function hierarchy(root) { + var stack = [ root ], nodes = [], node; + root.depth = 0; + while ((node = stack.pop()) != null) { + nodes.push(node); + if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { + var n, childs, child; + while (--n >= 0) { + stack.push(child = childs[n]); + child.parent = node; + child.depth = node.depth + 1; + } + if (value) node.value = 0; + node.children = childs; + } else { + if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; + delete node.children; + } + } + d3_layout_hierarchyVisitAfter(root, function(node) { + var childs, parent; + if (sort && (childs = node.children)) childs.sort(sort); + if (value && (parent = node.parent)) parent.value += node.value; + }); + return nodes; + } + hierarchy.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return hierarchy; }; - scale.rangeBand = function() { - return rangeBand; + hierarchy.children = function(x) { + if (!arguments.length) return children; + children = x; + return hierarchy; }; - scale.rangeExtent = function() { - return d3_scaleExtent(ranger.a[0]); + hierarchy.value = function(x) { + if (!arguments.length) return value; + value = x; + return hierarchy; }; - scale.copy = function() { - return d3_scale_ordinal(domain, ranger); + hierarchy.revalue = function(root) { + if (value) { + d3_layout_hierarchyVisitBefore(root, function(node) { + if (node.children) node.value = 0; + }); + d3_layout_hierarchyVisitAfter(root, function(node) { + var parent; + if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; + if (parent = node.parent) parent.value += node.value; + }); + } + return root; }; - return scale.domain(domain); - } - d3.scale.category10 = function() { - return d3.scale.ordinal().range(d3_category10); - }; - d3.scale.category20 = function() { - return d3.scale.ordinal().range(d3_category20); - }; - d3.scale.category20b = function() { - return d3.scale.ordinal().range(d3_category20b); - }; - d3.scale.category20c = function() { - return d3.scale.ordinal().range(d3_category20c); - }; - var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); - var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); - var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); - var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); - d3.scale.quantile = function() { - return d3_scale_quantile([], []); + return hierarchy; }; - function d3_scale_quantile(domain, range) { - var thresholds; - function rescale() { - var k = 0, q = range.length; - thresholds = []; - while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); - return scale; + function d3_layout_hierarchyRebind(object, hierarchy) { + d3.rebind(object, hierarchy, "sort", "children", "value"); + object.nodes = object; + object.links = d3_layout_hierarchyLinks; + return object; + } + function d3_layout_hierarchyVisitBefore(node, callback) { + var nodes = [ node ]; + while ((node = nodes.pop()) != null) { + callback(node); + if ((children = node.children) && (n = children.length)) { + var n, children; + while (--n >= 0) nodes.push(children[n]); + } } - function scale(x) { - if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; + } + function d3_layout_hierarchyVisitAfter(node, callback) { + var nodes = [ node ], nodes2 = []; + while ((node = nodes.pop()) != null) { + nodes2.push(node); + if ((children = node.children) && (n = children.length)) { + var i = -1, n, children; + while (++i < n) nodes.push(children[i]); + } + } + while ((node = nodes2.pop()) != null) { + callback(node); } - scale.domain = function(x) { - if (!arguments.length) return domain; - domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.quantiles = function() { - return thresholds; - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; - }; - scale.copy = function() { - return d3_scale_quantile(domain, range); - }; - return rescale(); } - d3.scale.quantize = function() { - return d3_scale_quantize(0, 1, [ 0, 1 ]); - }; - function d3_scale_quantize(x0, x1, range) { - var kx, i; - function scale(x) { - return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; + function d3_layout_hierarchyChildren(d) { + return d.children; + } + function d3_layout_hierarchyValue(d) { + return d.value; + } + function d3_layout_hierarchySort(a, b) { + return b.value - a.value; + } + function d3_layout_hierarchyLinks(nodes) { + return d3.merge(nodes.map(function(parent) { + return (parent.children || []).map(function(child) { + return { + source: parent, + target: child + }; + }); + })); + } + d3.layout.partition = function() { + var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; + function position(node, x, dx, dy) { + var children = node.children; + node.x = x; + node.y = node.depth * dy; + node.dx = dx; + node.dy = dy; + if (children && (n = children.length)) { + var i = -1, n, c, d; + dx = node.value ? dx / node.value : 0; + while (++i < n) { + position(c = children[i], x, d = c.value * dx, dy); + x += d; + } + } } - function rescale() { - kx = range.length / (x1 - x0); - i = range.length - 1; - return scale; + function depth(node) { + var children = node.children, d = 0; + if (children && (n = children.length)) { + var i = -1, n; + while (++i < n) d = Math.max(d, depth(children[i])); + } + return 1 + d; } - scale.domain = function(x) { - if (!arguments.length) return [ x0, x1 ]; - x0 = +x[0]; - x1 = +x[x.length - 1]; - return rescale(); - }; - scale.range = function(x) { - if (!arguments.length) return range; - range = x; - return rescale(); - }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - y = y < 0 ? NaN : y / kx + x0; - return [ y, y + 1 / kx ]; - }; - scale.copy = function() { - return d3_scale_quantize(x0, x1, range); + function partition(d, i) { + var nodes = hierarchy.call(this, d, i); + position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); + return nodes; + } + partition.size = function(x) { + if (!arguments.length) return size; + size = x; + return partition; }; - return rescale(); - } - d3.scale.threshold = function() { - return d3_scale_threshold([ .5 ], [ 0, 1 ]); + return d3_layout_hierarchyRebind(partition, hierarchy); }; - function d3_scale_threshold(domain, range) { - function scale(x) { - if (x <= x) return range[d3.bisect(domain, x)]; + d3.layout.pie = function() { + var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0; + function pie(data) { + var n = data.length, values = data.map(function(d, i) { + return +value.call(pie, d, i); + }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v; + if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { + return values[j] - values[i]; + } : function(i, j) { + return sort(data[i], data[j]); + }); + index.forEach(function(i) { + arcs[i] = { + data: data[i], + value: v = values[i], + startAngle: a, + endAngle: a += v * k + pa, + padAngle: p + }; + }); + return arcs; } - scale.domain = function(_) { - if (!arguments.length) return domain; - domain = _; - return scale; + pie.value = function(_) { + if (!arguments.length) return value; + value = _; + return pie; }; - scale.range = function(_) { - if (!arguments.length) return range; - range = _; - return scale; + pie.sort = function(_) { + if (!arguments.length) return sort; + sort = _; + return pie; }; - scale.invertExtent = function(y) { - y = range.indexOf(y); - return [ domain[y - 1], domain[y] ]; + pie.startAngle = function(_) { + if (!arguments.length) return startAngle; + startAngle = _; + return pie; }; - scale.copy = function() { - return d3_scale_threshold(domain, range); + pie.endAngle = function(_) { + if (!arguments.length) return endAngle; + endAngle = _; + return pie; }; - return scale; - } - d3.scale.identity = function() { - return d3_scale_identity([ 0, 1 ]); + pie.padAngle = function(_) { + if (!arguments.length) return padAngle; + padAngle = _; + return pie; + }; + return pie; }; - function d3_scale_identity(domain) { - function identity(x) { - return +x; + var d3_layout_pieSortByValue = {}; + d3.layout.stack = function() { + var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; + function stack(data, index) { + if (!(n = data.length)) return data; + var series = data.map(function(d, i) { + return values.call(stack, d, i); + }); + var points = series.map(function(d) { + return d.map(function(v, i) { + return [ x.call(stack, v, i), y.call(stack, v, i) ]; + }); + }); + var orders = order.call(stack, points, index); + series = d3.permute(series, orders); + points = d3.permute(points, orders); + var offsets = offset.call(stack, points, index); + var m = series[0].length, n, i, j, o; + for (j = 0; j < m; ++j) { + out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); + for (i = 1; i < n; ++i) { + out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + } + } + return data; } - identity.invert = identity; - identity.domain = identity.range = function(x) { - if (!arguments.length) return domain; - domain = x.map(identity); - return identity; + stack.values = function(x) { + if (!arguments.length) return values; + values = x; + return stack; }; - identity.ticks = function(m) { - return d3_scale_linearTicks(domain, m); + stack.order = function(x) { + if (!arguments.length) return order; + order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; + return stack; }; - identity.tickFormat = function(m, format) { - return d3_scale_linearTickFormat(domain, m, format); + stack.offset = function(x) { + if (!arguments.length) return offset; + offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; + return stack; }; - identity.copy = function() { - return d3_scale_identity(domain); + stack.x = function(z) { + if (!arguments.length) return x; + x = z; + return stack; }; - return identity; + stack.y = function(z) { + if (!arguments.length) return y; + y = z; + return stack; + }; + stack.out = function(z) { + if (!arguments.length) return out; + out = z; + return stack; + }; + return stack; + }; + function d3_layout_stackX(d) { + return d.x; } - d3.svg = {}; - function d3_zero() { - return 0; + function d3_layout_stackY(d) { + return d.y; } - d3.svg.arc = function() { - var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; - function arc() { - var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; - if (r1 < r0) rc = r1, r1 = r0, r0 = rc; - if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; - var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; - if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { - rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); - if (!cw) p1 *= -1; - if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); - if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); - } - if (r1) { - x0 = r1 * Math.cos(a0 + p1); - y0 = r1 * Math.sin(a0 + p1); - x1 = r1 * Math.cos(a1 - p1); - y1 = r1 * Math.sin(a1 - p1); - var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; - if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { - var h1 = (a0 + a1) / 2; - x0 = r1 * Math.cos(h1); - y0 = r1 * Math.sin(h1); - x1 = y1 = null; + function d3_layout_stackOut(d, y0, y) { + d.y0 = y0; + d.y = y; + } + var d3_layout_stackOrders = d3.map({ + "inside-out": function(data) { + var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { + return max[a] - max[b]; + }), top = 0, bottom = 0, tops = [], bottoms = []; + for (i = 0; i < n; ++i) { + j = index[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); } - } else { - x0 = y0 = 0; } - if (r0) { - x2 = r0 * Math.cos(a1 - p0); - y2 = r0 * Math.sin(a1 - p0); - x3 = r0 * Math.cos(a0 + p0); - y3 = r0 * Math.sin(a0 + p0); - var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; - if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { - var h0 = (a0 + a1) / 2; - x2 = r0 * Math.cos(h0); - y2 = r0 * Math.sin(h0); - x3 = y3 = null; - } - } else { - x2 = y2 = 0; + return bottoms.reverse().concat(tops); + }, + reverse: function(data) { + return d3.range(data.length).reverse(); + }, + "default": d3_layout_stackOrderDefault + }); + var d3_layout_stackOffsets = d3.map({ + silhouette: function(data) { + var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o > max) max = o; + sums.push(o); } - if ((rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { - cr = r0 < r1 ^ cw ? 0 : 1; - var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); - if (x1 != null) { - var rc1 = Math.min(rc, (r1 - lc) / (kc + 1)), t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); - if (rc === rc1) { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); - } else { - path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); + for (j = 0; j < m; ++j) { + y0[j] = (max - sums[j]) / 2; + } + return y0; + }, + wiggle: function(data) { + var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; + y0[0] = o = o0 = 0; + for (j = 1; j < m; ++j) { + for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; + for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { + for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { + s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; } - } else { - path.push("M", x0, ",", y0); + s2 += s3 * data[i][j][1]; } - if (x3 != null) { - var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); - if (rc === rc0) { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); - } else { - path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + y0[j] = o -= s1 ? s2 / s1 * dx : 0; + if (o < o0) o0 = o; + } + for (j = 0; j < m; ++j) y0[j] -= o0; + return y0; + }, + expand: function(data) { + var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }, + zero: d3_layout_stackOffsetZero + }); + function d3_layout_stackOrderDefault(data) { + return d3.range(data.length); + } + function d3_layout_stackOffsetZero(data) { + var j = -1, m = data[0].length, y0 = []; + while (++j < m) y0[j] = 0; + return y0; + } + function d3_layout_stackMaxIndex(array) { + var i = 1, j = 0, v = array[0][1], k, n = array.length; + for (;i < n; ++i) { + if ((k = array[i][1]) > v) { + j = i; + v = k; + } + } + return j; + } + function d3_layout_stackReduceSum(d) { + return d.reduce(d3_layout_stackSum, 0); + } + function d3_layout_stackSum(p, d) { + return p + d[1]; + } + d3.layout.histogram = function() { + var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; + function histogram(data, i) { + var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; + while (++i < m) { + bin = bins[i] = []; + bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); + bin.y = 0; + } + if (m > 0) { + i = -1; + while (++i < n) { + x = values[i]; + if (x >= range[0] && x <= range[1]) { + bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; + bin.y += k; + bin.push(data[i]); } - } else { - path.push("L", x2, ",", y2); } - } else { - path.push("M", x0, ",", y0); - if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); - path.push("L", x2, ",", y2); - if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); } - path.push("Z"); - return path.join(""); - } - function circleSegment(r1, cw) { - return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; + return bins; } - arc.innerRadius = function(v) { - if (!arguments.length) return innerRadius; - innerRadius = d3_functor(v); - return arc; - }; - arc.outerRadius = function(v) { - if (!arguments.length) return outerRadius; - outerRadius = d3_functor(v); - return arc; - }; - arc.cornerRadius = function(v) { - if (!arguments.length) return cornerRadius; - cornerRadius = d3_functor(v); - return arc; - }; - arc.padRadius = function(v) { - if (!arguments.length) return padRadius; - padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); - return arc; - }; - arc.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return arc; + histogram.value = function(x) { + if (!arguments.length) return valuer; + valuer = x; + return histogram; }; - arc.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return arc; + histogram.range = function(x) { + if (!arguments.length) return ranger; + ranger = d3_functor(x); + return histogram; }; - arc.padAngle = function(v) { - if (!arguments.length) return padAngle; - padAngle = d3_functor(v); - return arc; + histogram.bins = function(x) { + if (!arguments.length) return binner; + binner = typeof x === "number" ? function(range) { + return d3_layout_histogramBinFixed(range, x); + } : d3_functor(x); + return histogram; }; - arc.centroid = function() { - var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; - return [ Math.cos(a) * r, Math.sin(a) * r ]; + histogram.frequency = function(x) { + if (!arguments.length) return frequency; + frequency = !!x; + return histogram; }; - return arc; + return histogram; }; - var d3_svg_arcAuto = "auto"; - function d3_svg_arcInnerRadius(d) { - return d.innerRadius; - } - function d3_svg_arcOuterRadius(d) { - return d.outerRadius; - } - function d3_svg_arcStartAngle(d) { - return d.startAngle; - } - function d3_svg_arcEndAngle(d) { - return d.endAngle; - } - function d3_svg_arcPadAngle(d) { - return d && d.padAngle; + function d3_layout_histogramBinSturges(range, values) { + return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); } - function d3_svg_arcSweep(x0, y0, x1, y1) { - return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; + function d3_layout_histogramBinFixed(range, n) { + var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; + while (++x <= n) f[x] = m * x + b; + return f; } - function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { - var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(r * r * d2 - D * D), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; - if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; - return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; + function d3_layout_histogramRange(values) { + return [ d3.min(values), d3.max(values) ]; } - function d3_svg_line(projection) { - var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; - function line(data) { - var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); - function segment() { - segments.push("M", interpolate(projection(points), tension)); - } - while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); - } else if (points.length) { - segment(); - points = []; - } + d3.layout.pack = function() { + var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; + function pack(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { + return radius; + }; + root.x = root.y = 0; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r = +r(d.value); + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + if (padding) { + var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r += dr; + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r -= dr; + }); } - if (points.length) segment(); - return segments.length ? segments.join("") : null; + d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); + return nodes; } - line.x = function(_) { - if (!arguments.length) return x; - x = _; - return line; - }; - line.y = function(_) { - if (!arguments.length) return y; - y = _; - return line; - }; - line.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return line; + pack.size = function(_) { + if (!arguments.length) return size; + size = _; + return pack; }; - line.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - return line; + pack.radius = function(_) { + if (!arguments.length) return radius; + radius = _ == null || typeof _ === "function" ? _ : +_; + return pack; }; - line.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return line; + pack.padding = function(_) { + if (!arguments.length) return padding; + padding = +_; + return pack; }; - return line; - } - d3.svg.line = function() { - return d3_svg_line(d3_identity); + return d3_layout_hierarchyRebind(pack, hierarchy); }; - var d3_svg_lineInterpolators = d3.map({ - linear: d3_svg_lineLinear, - "linear-closed": d3_svg_lineLinearClosed, - step: d3_svg_lineStep, - "step-before": d3_svg_lineStepBefore, - "step-after": d3_svg_lineStepAfter, - basis: d3_svg_lineBasis, - "basis-open": d3_svg_lineBasisOpen, - "basis-closed": d3_svg_lineBasisClosed, - bundle: d3_svg_lineBundle, - cardinal: d3_svg_lineCardinal, - "cardinal-open": d3_svg_lineCardinalOpen, - "cardinal-closed": d3_svg_lineCardinalClosed, - monotone: d3_svg_lineMonotone - }); - d3_svg_lineInterpolators.forEach(function(key, value) { - value.key = key; - value.closed = /-closed$/.test(key); - }); - function d3_svg_lineLinear(points) { - return points.join("L"); - } - function d3_svg_lineLinearClosed(points) { - return d3_svg_lineLinear(points) + "Z"; - } - function d3_svg_lineStep(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); - if (n > 1) path.push("H", p[0]); - return path.join(""); - } - function d3_svg_lineStepBefore(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); - return path.join(""); - } - function d3_svg_lineStepAfter(points) { - var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; - while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); - return path.join(""); + function d3_layout_packSort(a, b) { + return a.value - b.value; } - function d3_svg_lineCardinalOpen(points, tension) { - return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); + function d3_layout_packInsert(a, b) { + var c = a._pack_next; + a._pack_next = b; + b._pack_prev = a; + b._pack_next = c; + c._pack_prev = b; } - function d3_svg_lineCardinalClosed(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), - points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + function d3_layout_packSplice(a, b) { + a._pack_next = b; + b._pack_prev = a; } - function d3_svg_lineCardinal(points, tension) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + function d3_layout_packIntersects(a, b) { + var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; + return .999 * dr * dr > dx * dx + dy * dy; } - function d3_svg_lineHermite(points, tangents) { - if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { - return d3_svg_lineLinear(points); - } - var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; - if (quad) { - path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; - p0 = points[1]; - pi = 2; + function d3_layout_packSiblings(node) { + if (!(nodes = node.children) || !(n = nodes.length)) return; + var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; + function bound(node) { + xMin = Math.min(node.x - node.r, xMin); + xMax = Math.max(node.x + node.r, xMax); + yMin = Math.min(node.y - node.r, yMin); + yMax = Math.max(node.y + node.r, yMax); } - if (tangents.length > 1) { - t = tangents[1]; - p = points[pi]; - pi++; - path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; - for (var i = 2; i < tangents.length; i++, pi++) { - p = points[pi]; - t = tangents[i]; - path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + nodes.forEach(d3_layout_packLink); + a = nodes[0]; + a.x = -a.r; + a.y = 0; + bound(a); + if (n > 1) { + b = nodes[1]; + b.x = b.r; + b.y = 0; + bound(b); + if (n > 2) { + c = nodes[2]; + d3_layout_packPlace(a, b, c); + bound(c); + d3_layout_packInsert(a, c); + a._pack_prev = c; + d3_layout_packInsert(c, b); + b = a._pack_next; + for (i = 3; i < n; i++) { + d3_layout_packPlace(a, b, c = nodes[i]); + var isect = 0, s1 = 1, s2 = 1; + for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { + if (d3_layout_packIntersects(j, c)) { + isect = 1; + break; + } + } + if (isect == 1) { + for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { + if (d3_layout_packIntersects(k, c)) { + break; + } + } + } + if (isect) { + if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); + i--; + } else { + d3_layout_packInsert(a, c); + b = c; + bound(c); + } + } } } - if (quad) { - var lp = points[pi]; - path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; + for (i = 0; i < n; i++) { + c = nodes[i]; + c.x -= cx; + c.y -= cy; + cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); } - return path; + node.r = cr; + nodes.forEach(d3_layout_packUnlink); } - function d3_svg_lineCardinalTangents(points, tension) { - var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; - while (++i < n) { - p0 = p1; - p1 = p2; - p2 = points[i]; - tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + function d3_layout_packLink(node) { + node._pack_next = node._pack_prev = node; + } + function d3_layout_packUnlink(node) { + delete node._pack_next; + delete node._pack_prev; + } + function d3_layout_packTransform(node, x, y, k) { + var children = node.children; + node.x = x += k * node.x; + node.y = y += k * node.y; + node.r *= k; + if (children) { + var i = -1, n = children.length; + while (++i < n) d3_layout_packTransform(children[i], x, y, k); } - return tangents; } - function d3_svg_lineBasis(points) { - if (points.length < 3) return d3_svg_lineLinear(points); - var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - points.push(points[n - 1]); - while (++i <= n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); + function d3_layout_packPlace(a, b, c) { + var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; + if (db && (dx || dy)) { + var da = b.r + c.r, dc = dx * dx + dy * dy; + da *= da; + db *= db; + var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = a.x + x * dx + y * dy; + c.y = a.y + x * dy - y * dx; + } else { + c.x = a.x + db; + c.y = a.y; } - points.pop(); - path.push("L", pi); - return path.join(""); } - function d3_svg_lineBasisOpen(points) { - if (points.length < 4) return d3_svg_lineLinear(points); - var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; - while (++i < 3) { - pi = points[i]; - px.push(pi[0]); - py.push(pi[1]); + d3.layout.tree = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; + function tree(d, i) { + var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); + d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; + d3_layout_hierarchyVisitBefore(root1, secondWalk); + if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { + var left = root0, right = root0, bottom = root0; + d3_layout_hierarchyVisitBefore(root0, function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); + d3_layout_hierarchyVisitBefore(root0, function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + return nodes; } - path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); - --i; - while (++i < n) { - pi = points[i]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); + function wrapTree(root0) { + var root1 = { + A: null, + children: [ root0 ] + }, queue = [ root1 ], node1; + while ((node1 = queue.pop()) != null) { + for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { + queue.push((children[i] = child = { + _: children[i], + parent: node1, + children: (child = children[i].children) && child.slice() || [], + A: null, + a: null, + z: 0, + m: 0, + c: 0, + s: 0, + t: null, + i: i + }).a = child); + } + } + return root1.children[0]; } - return path.join(""); - } - function d3_svg_lineBasisClosed(points) { - var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; - while (++i < 4) { - pi = points[i % n]; - px.push(pi[0]); - py.push(pi[1]); + function firstWalk(v) { + var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; + if (children.length) { + d3_layout_treeShift(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); } - path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; - --i; - while (++i < m) { - pi = points[i % n]; - px.shift(); - px.push(pi[0]); - py.shift(); - py.push(pi[1]); - d3_svg_lineBasisBezier(path, px, py); + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; } - return path.join(""); - } - function d3_svg_lineBundle(points, tension) { - var n = points.length - 1; - if (n) { - var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; - while (++i <= n) { - p = points[i]; - t = i / n; - p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); - p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); + function apportion(v, w, ancestor) { + if (w) { + var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; + while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { + vom = d3_layout_treeLeft(vom); + vop = d3_layout_treeRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !d3_layout_treeRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !d3_layout_treeLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } } + return ancestor; } - return d3_svg_lineBasis(points); + function sizeNode(node) { + node.x *= size[0]; + node.y = node.depth * size[1]; + } + tree.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return tree; + }; + tree.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null ? sizeNode : null; + return tree; + }; + tree.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) == null ? null : sizeNode; + return tree; + }; + return d3_layout_hierarchyRebind(tree, hierarchy); + }; + function d3_layout_treeSeparation(a, b) { + return a.parent == b.parent ? 1 : 2; } - function d3_svg_lineDot4(a, b) { - return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + function d3_layout_treeLeft(v) { + var children = v.children; + return children.length ? children[0] : v.t; } - var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; - function d3_svg_lineBasisBezier(path, x, y) { - path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); + function d3_layout_treeRight(v) { + var children = v.children, n; + return (n = children.length) ? children[n - 1] : v.t; } - function d3_svg_lineSlope(p0, p1) { - return (p1[1] - p0[1]) / (p1[0] - p0[0]); + function d3_layout_treeMove(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; } - function d3_svg_lineFiniteDifferences(points) { - var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); - while (++i < j) { - m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + function d3_layout_treeShift(v) { + var shift = 0, change = 0, children = v.children, i = children.length, w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); } - m[i] = d; - return m; } - function d3_svg_lineMonotoneTangents(points) { - var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; - while (++i < j) { - d = d3_svg_lineSlope(points[i], points[i + 1]); - if (abs(d) < ε) { - m[i] = m[i + 1] = 0; - } else { - a = m[i] / d; - b = m[i + 1] / d; - s = a * a + b * b; - if (s > 9) { - s = d * 3 / Math.sqrt(s); - m[i] = s * a; - m[i + 1] = s * b; + function d3_layout_treeAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + d3.layout.cluster = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; + function cluster(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; + d3_layout_hierarchyVisitAfter(root, function(node) { + var children = node.children; + if (children && children.length) { + node.x = d3_layout_clusterX(children); + node.y = d3_layout_clusterY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; } - } - } - i = -1; - while (++i <= j) { - s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); - tangents.push([ s || 0, m[i] * s || 0 ]); + }); + var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; + d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { + node.x = (node.x - root.x) * size[0]; + node.y = (root.y - node.y) * size[1]; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * size[0]; + node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + }); + return nodes; } - return tangents; + cluster.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return cluster; + }; + cluster.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null; + return cluster; + }; + cluster.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) != null; + return cluster; + }; + return d3_layout_hierarchyRebind(cluster, hierarchy); + }; + function d3_layout_clusterY(children) { + return 1 + d3.max(children, function(child) { + return child.y; + }); } - function d3_svg_lineMonotone(points) { - return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); + function d3_layout_clusterX(children) { + return children.reduce(function(x, child) { + return x + child.x; + }, 0) / children.length; } - d3.svg.line.radial = function() { - var line = d3_svg_line(d3_svg_lineRadial); - line.radius = line.x, delete line.x; - line.angle = line.y, delete line.y; - return line; - }; - function d3_svg_lineRadial(points) { - var point, i = -1, n = points.length, r, a; - while (++i < n) { - point = points[i]; - r = point[0]; - a = point[1] - halfπ; - point[0] = r * Math.cos(a); - point[1] = r * Math.sin(a); - } - return points; + function d3_layout_clusterLeft(node) { + var children = node.children; + return children && children.length ? d3_layout_clusterLeft(children[0]) : node; } - function d3_svg_area(projection) { - var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; - function area(data) { - var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { - return x; - } : d3_functor(x1), fy1 = y0 === y1 ? function() { - return y; - } : d3_functor(y1), x, y; - function segment() { - segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); + function d3_layout_clusterRight(node) { + var children = node.children, n; + return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + } + d3.layout.treemap = function() { + var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); + function scale(children, k) { + var i = -1, n = children.length, child, area; + while (++i < n) { + area = (child = children[i]).value * (k < 0 ? 0 : k); + child.area = isNaN(area) || area <= 0 ? 0 : area; + } + } + function squarify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while ((n = remaining.length) > 0) { + row.push(child = remaining[n - 1]); + row.area += child.area; + if (mode !== "squarify" || (score = worst(row, u)) <= best) { + remaining.pop(); + best = score; + } else { + row.area -= row.pop().area; + position(row, u, rect, false); + u = Math.min(rect.dx, rect.dy); + row.length = row.area = 0; + best = Infinity; + } + } + if (row.length) { + position(row, u, rect, true); + row.length = row.area = 0; + } + children.forEach(squarify); + } + } + function stickify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), remaining = children.slice(), child, row = []; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while (child = remaining.pop()) { + row.push(child); + row.area += child.area; + if (child.z != null) { + position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); + row.length = row.area = 0; + } + } + children.forEach(stickify); } + } + function worst(row, u) { + var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; while (++i < n) { - if (defined.call(this, d = data[i], i)) { - points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); - points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); - } else if (points0.length) { - segment(); - points0 = []; - points1 = []; + if (!(r = row[i].area)) continue; + if (r < rmin) rmin = r; + if (r > rmax) rmax = r; + } + s *= s; + u *= u; + return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; + } + function position(row, u, rect, flush) { + var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; + if (u == rect.dx) { + if (flush || v > rect.dy) v = rect.dy; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dy = v; + x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); + } + o.z = true; + o.dx += rect.x + rect.dx - x; + rect.y += v; + rect.dy -= v; + } else { + if (flush || v > rect.dx) v = rect.dx; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dx = v; + y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); } + o.z = false; + o.dy += rect.y + rect.dy - y; + rect.x += v; + rect.dx -= v; } - if (points0.length) segment(); - return segments.length ? segments.join("") : null; } - area.x = function(_) { - if (!arguments.length) return x1; - x0 = x1 = _; - return area; - }; - area.x0 = function(_) { - if (!arguments.length) return x0; - x0 = _; - return area; - }; - area.x1 = function(_) { - if (!arguments.length) return x1; - x1 = _; - return area; + function treemap(d) { + var nodes = stickies || hierarchy(d), root = nodes[0]; + root.x = root.y = 0; + if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0; + if (stickies) hierarchy.revalue(root); + scale([ root ], root.dx * root.dy / root.value); + (stickies ? stickify : squarify)(root); + if (sticky) stickies = nodes; + return nodes; + } + treemap.size = function(x) { + if (!arguments.length) return size; + size = x; + return treemap; }; - area.y = function(_) { - if (!arguments.length) return y1; - y0 = y1 = _; - return area; + treemap.padding = function(x) { + if (!arguments.length) return padding; + function padFunction(node) { + var p = x.call(treemap, node, node.depth); + return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); + } + function padConstant(node) { + return d3_layout_treemapPad(node, x); + } + var type; + pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], + padConstant) : padConstant; + return treemap; }; - area.y0 = function(_) { - if (!arguments.length) return y0; - y0 = _; - return area; + treemap.round = function(x) { + if (!arguments.length) return round != Number; + round = x ? Math.round : Number; + return treemap; }; - area.y1 = function(_) { - if (!arguments.length) return y1; - y1 = _; - return area; + treemap.sticky = function(x) { + if (!arguments.length) return sticky; + sticky = x; + stickies = null; + return treemap; }; - area.defined = function(_) { - if (!arguments.length) return defined; - defined = _; - return area; + treemap.ratio = function(x) { + if (!arguments.length) return ratio; + ratio = x; + return treemap; }; - area.interpolate = function(_) { - if (!arguments.length) return interpolateKey; - if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; - interpolateReverse = interpolate.reverse || interpolate; - L = interpolate.closed ? "M" : "L"; - return area; + treemap.mode = function(x) { + if (!arguments.length) return mode; + mode = x + ""; + return treemap; }; - area.tension = function(_) { - if (!arguments.length) return tension; - tension = _; - return area; + return d3_layout_hierarchyRebind(treemap, hierarchy); + }; + function d3_layout_treemapPadNull(node) { + return { + x: node.x, + y: node.y, + dx: node.dx, + dy: node.dy }; - return area; } - d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; - d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; - d3.svg.area = function() { - return d3_svg_area(d3_identity); - }; - d3.svg.area.radial = function() { - var area = d3_svg_area(d3_svg_lineRadial); - area.radius = area.x, delete area.x; - area.innerRadius = area.x0, delete area.x0; - area.outerRadius = area.x1, delete area.x1; - area.angle = area.y, delete area.y; - area.startAngle = area.y0, delete area.y0; - area.endAngle = area.y1, delete area.y1; - return area; - }; - d3.svg.chord = function() { - var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; - function chord(d, i) { - var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); - return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; + function d3_layout_treemapPad(node, padding) { + var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; + if (dx < 0) { + x += dx / 2; + dx = 0; } - function subgroup(self, f, d, i) { - var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ; - return { - r: r, - a0: a0, - a1: a1, - p0: [ r * Math.cos(a0), r * Math.sin(a0) ], - p1: [ r * Math.cos(a1), r * Math.sin(a1) ] + if (dy < 0) { + y += dy / 2; + dy = 0; + } + return { + x: x, + y: y, + dx: dx, + dy: dy + }; + } + d3.random = { + normal: function(µ, σ) { + var n = arguments.length; + if (n < 2) σ = 1; + if (n < 1) µ = 0; + return function() { + var x, y, r; + do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); + }; + }, + logNormal: function() { + var random = d3.random.normal.apply(d3, arguments); + return function() { + return Math.exp(random()); + }; + }, + bates: function(m) { + var random = d3.random.irwinHall(m); + return function() { + return random() / m; + }; + }, + irwinHall: function(m) { + return function() { + for (var s = 0, j = 0; j < m; j++) s += Math.random(); + return s; }; } - function equals(a, b) { - return a.a0 == b.a0 && a.a1 == b.a1; + }; + d3.scale = {}; + function d3_scaleExtent(domain) { + var start = domain[0], stop = domain[domain.length - 1]; + return start < stop ? [ start, stop ] : [ stop, start ]; + } + function d3_scaleRange(scale) { + return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + } + function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { + var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); + return function(x) { + return i(u(x)); + }; + } + function d3_scale_nice(domain, nice) { + var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; + if (x1 < x0) { + dx = i0, i0 = i1, i1 = dx; + dx = x0, x0 = x1, x1 = dx; } - function arc(r, p, a) { - return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p; + domain[i0] = nice.floor(x0); + domain[i1] = nice.ceil(x1); + return domain; + } + function d3_scale_niceStep(step) { + return step ? { + floor: function(x) { + return Math.floor(x / step) * step; + }, + ceil: function(x) { + return Math.ceil(x / step) * step; + } + } : d3_scale_niceIdentity; + } + var d3_scale_niceIdentity = { + floor: d3_identity, + ceil: d3_identity + }; + function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { + var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; + if (domain[k] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); } - function curve(r0, p0, r1, p1) { - return "Q 0,0 " + p1; + while (++j <= k) { + u.push(uninterpolate(domain[j - 1], domain[j])); + i.push(interpolate(range[j - 1], range[j])); } - chord.radius = function(v) { - if (!arguments.length) return radius; - radius = d3_functor(v); - return chord; - }; - chord.source = function(v) { - if (!arguments.length) return source; - source = d3_functor(v); - return chord; - }; - chord.target = function(v) { - if (!arguments.length) return target; - target = d3_functor(v); - return chord; - }; - chord.startAngle = function(v) { - if (!arguments.length) return startAngle; - startAngle = d3_functor(v); - return chord; - }; - chord.endAngle = function(v) { - if (!arguments.length) return endAngle; - endAngle = d3_functor(v); - return chord; + return function(x) { + var j = d3.bisect(domain, x, 1, k) - 1; + return i[j](u[j](x)); }; - return chord; - }; - function d3_svg_chordRadius(d) { - return d.radius; } - d3.svg.diagonal = function() { - var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; - function diagonal(d, i) { - var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { - x: p0.x, - y: m - }, { - x: p3.x, - y: m - }, p3 ]; - p = p.map(projection); - return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; + d3.scale.linear = function() { + return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + }; + function d3_scale_linear(domain, range, interpolate, clamp) { + var output, input; + function rescale() { + var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; + output = linear(domain, range, uninterpolate, interpolate); + input = linear(range, domain, uninterpolate, d3_interpolate); + return scale; } - diagonal.source = function(x) { - if (!arguments.length) return source; - source = d3_functor(x); - return diagonal; + function scale(x) { + return output(x); + } + scale.invert = function(y) { + return input(y); }; - diagonal.target = function(x) { - if (!arguments.length) return target; - target = d3_functor(x); - return diagonal; + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(Number); + return rescale(); }; - diagonal.projection = function(x) { - if (!arguments.length) return projection; - projection = x; - return diagonal; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); }; - return diagonal; - }; - function d3_svg_diagonalProjection(d) { - return [ d.x, d.y ]; - } - d3.svg.diagonal.radial = function() { - var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; - diagonal.projection = function(x) { - return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; + scale.rangeRound = function(x) { + return scale.range(x).interpolate(d3_interpolateRound); }; - return diagonal; - }; - function d3_svg_diagonalRadialProjection(projection) { - return function() { - var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ; - return [ r * Math.cos(a), r * Math.sin(a) ]; + scale.clamp = function(x) { + if (!arguments.length) return clamp; + clamp = x; + return rescale(); }; - } - d3.svg.symbol = function() { - var type = d3_svg_symbolType, size = d3_svg_symbolSize; - function symbol(d, i) { - return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); - } - symbol.type = function(x) { - if (!arguments.length) return type; - type = d3_functor(x); - return symbol; + scale.interpolate = function(x) { + if (!arguments.length) return interpolate; + interpolate = x; + return rescale(); }; - symbol.size = function(x) { - if (!arguments.length) return size; - size = d3_functor(x); - return symbol; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); }; - return symbol; - }; - function d3_svg_symbolSize() { - return 64; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + d3_scale_linearNice(domain, m); + return rescale(); + }; + scale.copy = function() { + return d3_scale_linear(domain, range, interpolate, clamp); + }; + return rescale(); } - function d3_svg_symbolType() { - return "circle"; + function d3_scale_linearRebind(scale, linear) { + return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); } - function d3_svg_symbolCircle(size) { - var r = Math.sqrt(size / π); - return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + function d3_scale_linearNice(domain, m) { + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + return domain; } - var d3_svg_symbols = d3.map({ - circle: d3_svg_symbolCircle, - cross: function(size) { - var r = Math.sqrt(size / 5) / 2; - return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; - }, - diamond: function(size) { - var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; - return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; - }, - square: function(size) { - var r = Math.sqrt(size) / 2; - return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; - }, - "triangle-down": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; - }, - "triangle-up": function(size) { - var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; - return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; - } - }); - d3.svg.symbolTypes = d3_svg_symbols.keys(); - var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); - d3_selectionPrototype.transition = function(name) { - var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { - time: Date.now(), - ease: d3_ease_cubicInOut, - delay: 0, - duration: 250 - }; - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); - subgroup.push(node); + function d3_scale_linearTickRange(domain, m) { + if (m == null) m = 10; + var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; + if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; + extent[0] = Math.ceil(extent[0] / step) * step; + extent[1] = Math.floor(extent[1] / step) * step + step * .5; + extent[2] = step; + return extent; + } + function d3_scale_linearTicks(domain, m) { + return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); + } + function d3_scale_linearTickFormat(domain, m, format) { + var range = d3_scale_linearTickRange(domain, m); + if (format) { + var match = d3_format_re.exec(format); + match.shift(); + if (match[8] === "s") { + var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); + if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); + match[8] = "f"; + format = d3.format(match.join("")); + return function(d) { + return format(prefix.scale(d)) + prefix.symbol; + }; } + if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); + format = match.join(""); + } else { + format = ",." + d3_scale_linearPrecision(range[2]) + "f"; } - return d3_transition(subgroups, ns, id); - }; - d3_selectionPrototype.interrupt = function(name) { - return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); + return d3.format(format); + } + var d3_scale_linearFormatSignificant = { + s: 1, + g: 1, + p: 1, + r: 1, + e: 1 }; - var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); - function d3_selection_interruptNS(ns) { - return function() { - var lock, active; - if ((lock = this[ns]) && (active = lock[lock.active])) { - if (--lock.count) delete lock[lock.active]; else delete this[ns]; - lock.active += .5; - active.event && active.event.interrupt.call(this, this.__data__, active.index); - } - }; + function d3_scale_linearPrecision(value) { + return -Math.floor(Math.log(value) / Math.LN10 + .01); } - function d3_transition(groups, ns, id) { - d3_subclass(groups, d3_transitionPrototype); - groups.namespace = ns; - groups.id = id; - return groups; + function d3_scale_linearFormatPrecision(type, range) { + var p = d3_scale_linearPrecision(range[2]); + return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; } - var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; - d3_transitionPrototype.call = d3_selectionPrototype.call; - d3_transitionPrototype.empty = d3_selectionPrototype.empty; - d3_transitionPrototype.node = d3_selectionPrototype.node; - d3_transitionPrototype.size = d3_selectionPrototype.size; - d3.transition = function(selection, name) { - return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection); + d3.scale.log = function() { + return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); }; - d3.transition.prototype = d3_transitionPrototype; - d3_transitionPrototype.select = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node; - selector = d3_selection_selector(selector); - for (var j = -1, m = this.length; ++j < m; ) { - subgroups.push(subgroup = []); - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { - if ("__data__" in node) subnode.__data__ = node.__data__; - d3_transitionNode(subnode, i, ns, id, node[ns][id]); - subgroup.push(subnode); + function d3_scale_log(linear, base, positive, domain) { + function log(x) { + return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); + } + function pow(x) { + return positive ? Math.pow(base, x) : -Math.pow(base, -x); + } + function scale(x) { + return linear(log(x)); + } + scale.invert = function(x) { + return pow(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + positive = x[0] >= 0; + linear.domain((domain = x.map(Number)).map(log)); + return scale; + }; + scale.base = function(_) { + if (!arguments.length) return base; + base = +_; + linear.domain(domain.map(log)); + return scale; + }; + scale.nice = function() { + var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); + linear.domain(niced); + domain = niced.map(pow); + return scale; + }; + scale.ticks = function() { + var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; + if (isFinite(j - i)) { + if (positive) { + for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); + ticks.push(pow(i)); } else { - subgroup.push(null); + ticks.push(pow(i)); + for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); } + for (i = 0; ticks[i] < u; i++) {} + for (j = ticks.length; ticks[j - 1] > v; j--) {} + ticks = ticks.slice(i, j); } + return ticks; + }; + scale.tickFormat = function(n, format) { + if (!arguments.length) return d3_scale_logFormat; + if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); + var k = Math.max(1, base * n / scale.ticks().length); + return function(d) { + var i = d / pow(Math.round(log(d))); + if (i * base < base - .5) i *= base; + return i <= k ? format(d) : ""; + }; + }; + scale.copy = function() { + return d3_scale_log(linear.copy(), base, positive, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { + floor: function(x) { + return -Math.ceil(-x); + }, + ceil: function(x) { + return -Math.floor(-x); } - return d3_transition(subgroups, ns, id); }; - d3_transitionPrototype.selectAll = function(selector) { - var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition; - selector = d3_selection_selectorAll(selector); - for (var j = -1, m = this.length; ++j < m; ) { - for (var group = this[j], i = -1, n = group.length; ++i < n; ) { - if (node = group[i]) { - transition = node[ns][id]; - subnodes = selector.call(node, node.__data__, i, j); - subgroups.push(subgroup = []); - for (var k = -1, o = subnodes.length; ++k < o; ) { - if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition); - subgroup.push(subnode); - } - } - } - } - return d3_transition(subgroups, ns, id); + d3.scale.pow = function() { + return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); }; - d3_transitionPrototype.filter = function(filter) { - var subgroups = [], subgroup, group, node; - if (typeof filter !== "function") filter = d3_selection_filter(filter); - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { - subgroup.push(node); - } - } + function d3_scale_pow(linear, exponent, domain) { + var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); + function scale(x) { + return linear(powp(x)); } - return d3_transition(subgroups, this.namespace, this.id); + scale.invert = function(x) { + return powb(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + linear.domain((domain = x.map(Number)).map(powp)); + return scale; + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + return scale.domain(d3_scale_linearNice(domain, m)); + }; + scale.exponent = function(x) { + if (!arguments.length) return exponent; + powp = d3_scale_powPow(exponent = x); + powb = d3_scale_powPow(1 / exponent); + linear.domain(domain.map(powp)); + return scale; + }; + scale.copy = function() { + return d3_scale_pow(linear.copy(), exponent, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_scale_powPow(e) { + return function(x) { + return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + }; + } + d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5); }; - d3_transitionPrototype.tween = function(name, tween) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) return this.node()[ns][id].tween.get(name); - return d3_selection_each(this, tween == null ? function(node) { - node[ns][id].tween.remove(name); - } : function(node) { - node[ns][id].tween.set(name, tween); + d3.scale.ordinal = function() { + return d3_scale_ordinal([], { + t: "range", + a: [ [] ] }); }; - function d3_transition_tween(groups, name, value, tween) { - var id = groups.id, ns = groups.namespace; - return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { - node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); - } : (value = tween(value), function(node) { - node[ns][id].tween.set(name, value); - })); - } - d3_transitionPrototype.attr = function(nameNS, value) { - if (arguments.length < 2) { - for (value in nameNS) this.attr(value, nameNS[value]); - return this; - } - var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); - function attrNull() { - this.removeAttribute(name); - } - function attrNullNS() { - this.removeAttributeNS(name.space, name.local); - } - function attrTween(b) { - return b == null ? attrNull : (b += "", function() { - var a = this.getAttribute(name), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttribute(name, i(t)); - }); - }); + function d3_scale_ordinal(domain, ranger) { + var index, range, rangeBand; + function scale(x) { + return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; } - function attrTweenNS(b) { - return b == null ? attrNullNS : (b += "", function() { - var a = this.getAttributeNS(name.space, name.local), i; - return a !== b && (i = interpolate(a, b), function(t) { - this.setAttributeNS(name.space, name.local, i(t)); - }); + function steps(start, step) { + return d3.range(domain.length).map(function(i) { + return start + step * i; }); } - return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.attrTween = function(nameNS, tween) { - var name = d3.ns.qualify(nameNS); - function attrTween(d, i) { - var f = tween.call(this, d, i, this.getAttribute(name)); - return f && function(t) { - this.setAttribute(name, f(t)); + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = []; + index = new d3_Map(); + var i = -1, n = x.length, xi; + while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); + return scale[ranger.t].apply(scale, ranger.a); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + rangeBand = 0; + ranger = { + t: "range", + a: arguments }; - } - function attrTweenNS(d, i) { - var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); - return f && function(t) { - this.setAttributeNS(name.space, name.local, f(t)); + return scale; + }; + scale.rangePoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, + 0) : (stop - start) / (domain.length - 1 + padding); + range = steps(start + step * padding / 2, step); + rangeBand = 0; + ranger = { + t: "rangePoints", + a: arguments }; - } - return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); - }; - d3_transitionPrototype.style = function(name, value, priority) { - var n = arguments.length; - if (n < 3) { - if (typeof name !== "string") { - if (n < 2) value = ""; - for (priority in name) this.style(priority, name[priority], value); - return this; - } - priority = ""; - } - function styleNull() { - this.style.removeProperty(name); - } - function styleString(b) { - return b == null ? styleNull : (b += "", function() { - var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i; - return a !== b && (i = d3_interpolate(a, b), function(t) { - this.style.setProperty(name, i(t), priority); - }); - }); - } - return d3_transition_tween(this, "style." + name, value, styleString); - }; - d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = ""; - function styleTween(d, i) { - var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name)); - return f && function(t) { - this.style.setProperty(name, f(t), priority); + return scale; + }; + scale.rangeRoundPoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), + 0) : (stop - start) / (domain.length - 1 + padding) | 0; + range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step); + rangeBand = 0; + ranger = { + t: "rangeRoundPoints", + a: arguments }; - } - return this.tween("style." + name, styleTween); - }; - d3_transitionPrototype.text = function(value) { - return d3_transition_tween(this, "text", value, d3_transition_text); - }; - function d3_transition_text(b) { - if (b == null) b = ""; - return function() { - this.textContent = b; + return scale; + }; + scale.rangeBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); + range = steps(start + step * outerPadding, step); + if (reverse) range.reverse(); + rangeBand = step * (1 - padding); + ranger = { + t: "rangeBands", + a: arguments + }; + return scale; + }; + scale.rangeRoundBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)); + range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step); + if (reverse) range.reverse(); + rangeBand = Math.round(step * (1 - padding)); + ranger = { + t: "rangeRoundBands", + a: arguments + }; + return scale; + }; + scale.rangeBand = function() { + return rangeBand; + }; + scale.rangeExtent = function() { + return d3_scaleExtent(ranger.a[0]); + }; + scale.copy = function() { + return d3_scale_ordinal(domain, ranger); }; + return scale.domain(domain); } - d3_transitionPrototype.remove = function() { - var ns = this.namespace; - return this.each("end.transition", function() { - var p; - if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this); - }); + d3.scale.category10 = function() { + return d3.scale.ordinal().range(d3_category10); }; - d3_transitionPrototype.ease = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].ease; - if (typeof value !== "function") value = d3.ease.apply(d3, arguments); - return d3_selection_each(this, function(node) { - node[ns][id].ease = value; - }); + d3.scale.category20 = function() { + return d3.scale.ordinal().range(d3_category20); }; - d3_transitionPrototype.delay = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].delay; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].delay = +value.call(node, node.__data__, i, j); - } : (value = +value, function(node) { - node[ns][id].delay = value; - })); + d3.scale.category20b = function() { + return d3.scale.ordinal().range(d3_category20b); }; - d3_transitionPrototype.duration = function(value) { - var id = this.id, ns = this.namespace; - if (arguments.length < 1) return this.node()[ns][id].duration; - return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { - node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); - } : (value = Math.max(1, value), function(node) { - node[ns][id].duration = value; - })); + d3.scale.category20c = function() { + return d3.scale.ordinal().range(d3_category20c); }; - d3_transitionPrototype.each = function(type, listener) { - var id = this.id, ns = this.namespace; - if (arguments.length < 2) { - var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; - try { - d3_transitionInheritId = id; - d3_selection_each(this, function(node, i, j) { - d3_transitionInherit = node[ns][id]; - type.call(node, node.__data__, i, j); - }); - } finally { - d3_transitionInherit = inherit; - d3_transitionInheritId = inheritId; - } - } else { - d3_selection_each(this, function(node) { - var transition = node[ns][id]; - (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener); - }); - } - return this; + var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); + var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); + var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); + var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); + d3.scale.quantile = function() { + return d3_scale_quantile([], []); }; - d3_transitionPrototype.transition = function() { - var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition; - for (var j = 0, m = this.length; j < m; j++) { - subgroups.push(subgroup = []); - for (var group = this[j], i = 0, n = group.length; i < n; i++) { - if (node = group[i]) { - transition = node[ns][id0]; - d3_transitionNode(node, i, ns, id1, { - time: transition.time, - ease: transition.ease, - delay: transition.delay + transition.duration, - duration: transition.duration - }); - } - subgroup.push(node); - } + function d3_scale_quantile(domain, range) { + var thresholds; + function rescale() { + var k = 0, q = range.length; + thresholds = []; + while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); + return scale; } - return d3_transition(subgroups, ns, id1); - }; - function d3_transitionNamespace(name) { - return name == null ? "__transition__" : "__transition_" + name + "__"; - } - function d3_transitionNode(node, i, ns, id, inherit) { - var lock = node[ns] || (node[ns] = { - active: 0, - count: 0 - }), transition = lock[id]; - if (!transition) { - var time = inherit.time; - transition = lock[id] = { - tween: new d3_Map(), - time: time, - delay: inherit.delay, - duration: inherit.duration, - ease: inherit.ease, - index: i - }; - inherit = null; - ++lock.count; - d3.timer(function(elapsed) { - var delay = transition.delay, duration, ease, timer = d3_timer_active, tweened = []; - timer.t = delay + time; - if (delay <= elapsed) return start(elapsed - delay); - timer.c = start; - function start(elapsed) { - if (lock.active > id) return stop(); - var active = lock[lock.active]; - if (active) { - --lock.count; - delete lock[lock.active]; - active.event && active.event.interrupt.call(node, node.__data__, active.index); - } - lock.active = id; - transition.event && transition.event.start.call(node, node.__data__, i); - transition.tween.forEach(function(key, value) { - if (value = value.call(node, node.__data__, i)) { - tweened.push(value); - } - }); - ease = transition.ease; - duration = transition.duration; - d3.timer(function() { - timer.c = tick(elapsed || 1) ? d3_true : tick; - return 1; - }, 0, time); - } - function tick(elapsed) { - if (lock.active !== id) return 1; - var t = elapsed / duration, e = ease(t), n = tweened.length; - while (n > 0) { - tweened[--n].call(node, e); - } - if (t >= 1) { - transition.event && transition.event.end.call(node, node.__data__, i); - return stop(); - } - } - function stop() { - if (--lock.count) delete lock[id]; else delete node[ns]; - return 1; - } - }, 0, time); + function scale(x) { + if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.quantiles = function() { + return thresholds; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; + }; + scale.copy = function() { + return d3_scale_quantile(domain, range); + }; + return rescale(); } - d3.svg.axis = function() { - var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; - function axis(g) { - g.each(function() { - var g = d3.select(this); - var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); - var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; - var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), - d3.transition(path)); - tickEnter.append("line"); - tickEnter.append("text"); - var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; - if (orient === "bottom" || orient === "top") { - tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; - text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); - pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); - } else { - tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; - text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); - pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); - } - lineEnter.attr(y2, sign * innerTickSize); - textEnter.attr(y1, sign * tickSpacing); - lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); - textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); - if (scale1.rangeBand) { - var x = scale1, dx = x.rangeBand() / 2; - scale0 = scale1 = function(d) { - return x(d) + dx; - }; - } else if (scale0.rangeBand) { - scale0 = scale1; - } else { - tickExit.call(tickTransform, scale1, scale0); - } - tickEnter.call(tickTransform, scale0, scale1); - tickUpdate.call(tickTransform, scale1, scale1); - }); + d3.scale.quantize = function() { + return d3_scale_quantize(0, 1, [ 0, 1 ]); + }; + function d3_scale_quantize(x0, x1, range) { + var kx, i; + function scale(x) { + return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; } - axis.scale = function(x) { - if (!arguments.length) return scale; - scale = x; - return axis; + function rescale() { + kx = range.length / (x1 - x0); + i = range.length - 1; + return scale; + } + scale.domain = function(x) { + if (!arguments.length) return [ x0, x1 ]; + x0 = +x[0]; + x1 = +x[x.length - 1]; + return rescale(); }; - axis.orient = function(x) { - if (!arguments.length) return orient; - orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; - return axis; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); }; - axis.ticks = function() { - if (!arguments.length) return tickArguments_; - tickArguments_ = arguments; - return axis; + scale.invertExtent = function(y) { + y = range.indexOf(y); + y = y < 0 ? NaN : y / kx + x0; + return [ y, y + 1 / kx ]; }; - axis.tickValues = function(x) { - if (!arguments.length) return tickValues; - tickValues = x; - return axis; + scale.copy = function() { + return d3_scale_quantize(x0, x1, range); }; - axis.tickFormat = function(x) { - if (!arguments.length) return tickFormat_; - tickFormat_ = x; - return axis; + return rescale(); + } + d3.scale.threshold = function() { + return d3_scale_threshold([ .5 ], [ 0, 1 ]); + }; + function d3_scale_threshold(domain, range) { + function scale(x) { + if (x <= x) return range[d3.bisect(domain, x)]; + } + scale.domain = function(_) { + if (!arguments.length) return domain; + domain = _; + return scale; }; - axis.tickSize = function(x) { - var n = arguments.length; - if (!n) return innerTickSize; - innerTickSize = +x; - outerTickSize = +arguments[n - 1]; - return axis; + scale.range = function(_) { + if (!arguments.length) return range; + range = _; + return scale; }; - axis.innerTickSize = function(x) { - if (!arguments.length) return innerTickSize; - innerTickSize = +x; - return axis; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return [ domain[y - 1], domain[y] ]; }; - axis.outerTickSize = function(x) { - if (!arguments.length) return outerTickSize; - outerTickSize = +x; - return axis; + scale.copy = function() { + return d3_scale_threshold(domain, range); }; - axis.tickPadding = function(x) { - if (!arguments.length) return tickPadding; - tickPadding = +x; - return axis; + return scale; + } + d3.scale.identity = function() { + return d3_scale_identity([ 0, 1 ]); + }; + function d3_scale_identity(domain) { + function identity(x) { + return +x; + } + identity.invert = identity; + identity.domain = identity.range = function(x) { + if (!arguments.length) return domain; + domain = x.map(identity); + return identity; }; - axis.tickSubdivide = function() { - return arguments.length && axis; + identity.ticks = function(m) { + return d3_scale_linearTicks(domain, m); }; - return axis; - }; - var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { - top: 1, - right: 1, - bottom: 1, - left: 1 - }; - function d3_svg_axisX(selection, x0, x1) { - selection.attr("transform", function(d) { - var v0 = x0(d); - return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; - }); + identity.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + identity.copy = function() { + return d3_scale_identity(domain); + }; + return identity; } - function d3_svg_axisY(selection, y0, y1) { - selection.attr("transform", function(d) { - var v0 = y0(d); - return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; - }); + d3.svg = {}; + function d3_zero() { + return 0; } - d3.svg.brush = function() { - var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; - function brush(g) { - g.each(function() { - var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); - var background = g.selectAll(".background").data([ 0 ]); - background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); - g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); - var resize = g.selectAll(".resize").data(resizes, d3_identity); - resize.exit().remove(); - resize.enter().append("g").attr("class", function(d) { - return "resize " + d; - }).style("cursor", function(d) { - return d3_svg_brushCursor[d]; - }).append("rect").attr("x", function(d) { - return /[ew]$/.test(d) ? -3 : null; - }).attr("y", function(d) { - return /^[ns]/.test(d) ? -3 : null; - }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); - resize.style("display", brush.empty() ? "none" : null); - var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; - if (x) { - range = d3_scaleRange(x); - backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); - redrawX(gUpdate); - } - if (y) { - range = d3_scaleRange(y); - backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); - redrawY(gUpdate); - } - redraw(gUpdate); - }); - } - brush.event = function(g) { - g.each(function() { - var event_ = event.of(this, arguments), extent1 = { - x: xExtent, - y: yExtent, - i: xExtentDomain, - j: yExtentDomain - }, extent0 = this.__chart__ || extent1; - this.__chart__ = extent1; - if (d3_transitionInheritId) { - d3.select(this).transition().each("start.brush", function() { - xExtentDomain = extent0.i; - yExtentDomain = extent0.j; - xExtent = extent0.x; - yExtent = extent0.y; - event_({ - type: "brushstart" - }); - }).tween("brush:brush", function() { - var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); - xExtentDomain = yExtentDomain = null; - return function(t) { - xExtent = extent1.x = xi(t); - yExtent = extent1.y = yi(t); - event_({ - type: "brush", - mode: "resize" - }); - }; - }).each("end.brush", function() { - xExtentDomain = extent1.i; - yExtentDomain = extent1.j; - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - }); - } else { - event_({ - type: "brushstart" - }); - event_({ - type: "brush", - mode: "resize" - }); - event_({ - type: "brushend" - }); - } - }); - }; - function redraw(g) { - g.selectAll(".resize").attr("transform", function(d) { - return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; - }); - } - function redrawX(g) { - g.select(".extent").attr("x", xExtent[0]); - g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); - } - function redrawY(g) { - g.select(".extent").attr("y", yExtent[0]); - g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); - } - function brushstart() { - var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; - var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); - if (d3.event.changedTouches) { - w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); - } else { - w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); - } - g.interrupt().selectAll("*").interrupt(); - if (dragging) { - origin[0] = xExtent[0] - origin[0]; - origin[1] = yExtent[0] - origin[1]; - } else if (resizing) { - var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); - offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; - origin[0] = xExtent[ex]; - origin[1] = yExtent[ey]; - } else if (d3.event.altKey) center = origin.slice(); - g.style("pointer-events", "none").selectAll(".resize").style("display", null); - d3.select("body").style("cursor", eventTarget.style("cursor")); - event_({ - type: "brushstart" - }); - brushmove(); - function keydown() { - if (d3.event.keyCode == 32) { - if (!dragging) { - center = null; - origin[0] -= xExtent[1]; - origin[1] -= yExtent[1]; - dragging = 2; - } - d3_eventPreventDefault(); - } - } - function keyup() { - if (d3.event.keyCode == 32 && dragging == 2) { - origin[0] += xExtent[1]; - origin[1] += yExtent[1]; - dragging = 0; - d3_eventPreventDefault(); - } + d3.svg.arc = function() { + var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle; + function arc() { + var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1; + if (r1 < r0) rc = r1, r1 = r0, r0 = rc; + if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z"; + var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = []; + if (ap = (+padAngle.apply(this, arguments) || 0) / 2) { + rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments); + if (!cw) p1 *= -1; + if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap)); + if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap)); } - function brushmove() { - var point = d3.mouse(target), moved = false; - if (offset) { - point[0] += offset[0]; - point[1] += offset[1]; - } - if (!dragging) { - if (d3.event.altKey) { - if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; - origin[0] = xExtent[+(point[0] < center[0])]; - origin[1] = yExtent[+(point[1] < center[1])]; - } else center = null; - } - if (resizingX && move1(point, x, 0)) { - redrawX(g); - moved = true; - } - if (resizingY && move1(point, y, 1)) { - redrawY(g); - moved = true; + if (r1) { + x0 = r1 * Math.cos(a0 + p1); + y0 = r1 * Math.sin(a0 + p1); + x1 = r1 * Math.cos(a1 - p1); + y1 = r1 * Math.sin(a1 - p1); + var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1; + if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) { + var h1 = (a0 + a1) / 2; + x0 = r1 * Math.cos(h1); + y0 = r1 * Math.sin(h1); + x1 = y1 = null; } - if (moved) { - redraw(g); - event_({ - type: "brush", - mode: dragging ? "move" : "resize" - }); + } else { + x0 = y0 = 0; + } + if (r0) { + x2 = r0 * Math.cos(a1 - p0); + y2 = r0 * Math.sin(a1 - p0); + x3 = r0 * Math.cos(a0 + p0); + y3 = r0 * Math.sin(a0 + p0); + var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1; + if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) { + var h0 = (a0 + a1) / 2; + x2 = r0 * Math.cos(h0); + y2 = r0 * Math.sin(h0); + x3 = y3 = null; } + } else { + x2 = y2 = 0; } - function move1(point, scale, i) { - var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; - if (dragging) { - r0 -= position; - r1 -= size + position; + if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) { + cr = r0 < r1 ^ cw ? 0 : 1; + var rc1 = rc, rc0 = rc; + if (da < π) { + var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = Math.min(rc, (r0 - lc) / (kc - 1)); + rc1 = Math.min(rc, (r1 - lc) / (kc + 1)); } - min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; - if (dragging) { - max = (min += position) + size; - } else { - if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); - if (position < min) { - max = min; - min = position; + if (x1 != null) { + var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw); + if (rc === rc1) { + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]); } else { - max = position; + path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]); } + } else { + path.push("M", x0, ",", y0); } - if (extent[0] != min || extent[1] != max) { - if (i) yExtentDomain = null; else xExtentDomain = null; - extent[0] = min; - extent[1] = max; - return true; + if (x3 != null) { + var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw); + if (rc === rc0) { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } else { + path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]); + } + } else { + path.push("L", x2, ",", y2); } + } else { + path.push("M", x0, ",", y0); + if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1); + path.push("L", x2, ",", y2); + if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3); } - function brushend() { - brushmove(); - g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); - d3.select("body").style("cursor", null); - w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); - dragRestore(); - event_({ - type: "brushend" - }); - } + path.push("Z"); + return path.join(""); } - brush.x = function(z) { - if (!arguments.length) return x; - x = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; + function circleSegment(r1, cw) { + return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1; + } + arc.innerRadius = function(v) { + if (!arguments.length) return innerRadius; + innerRadius = d3_functor(v); + return arc; }; - brush.y = function(z) { - if (!arguments.length) return y; - y = z; - resizes = d3_svg_brushResizes[!x << 1 | !y]; - return brush; + arc.outerRadius = function(v) { + if (!arguments.length) return outerRadius; + outerRadius = d3_functor(v); + return arc; }; - brush.clamp = function(z) { - if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; - if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; - return brush; + arc.cornerRadius = function(v) { + if (!arguments.length) return cornerRadius; + cornerRadius = d3_functor(v); + return arc; }; - brush.extent = function(z) { - var x0, x1, y0, y1, t; - if (!arguments.length) { - if (x) { - if (xExtentDomain) { - x0 = xExtentDomain[0], x1 = xExtentDomain[1]; - } else { - x0 = xExtent[0], x1 = xExtent[1]; - if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - } - } - if (y) { - if (yExtentDomain) { - y0 = yExtentDomain[0], y1 = yExtentDomain[1]; - } else { - y0 = yExtent[0], y1 = yExtent[1]; - if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - } - } - return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; - } - if (x) { - x0 = z[0], x1 = z[1]; - if (y) x0 = x0[0], x1 = x1[0]; - xExtentDomain = [ x0, x1 ]; - if (x.invert) x0 = x(x0), x1 = x(x1); - if (x1 < x0) t = x0, x0 = x1, x1 = t; - if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; - } - if (y) { - y0 = z[0], y1 = z[1]; - if (x) y0 = y0[1], y1 = y1[1]; - yExtentDomain = [ y0, y1 ]; - if (y.invert) y0 = y(y0), y1 = y(y1); - if (y1 < y0) t = y0, y0 = y1, y1 = t; - if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; - } - return brush; + arc.padRadius = function(v) { + if (!arguments.length) return padRadius; + padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v); + return arc; }; - brush.clear = function() { - if (!brush.empty()) { - xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; - xExtentDomain = yExtentDomain = null; - } - return brush; + arc.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return arc; }; - brush.empty = function() { - return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + arc.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return arc; }; - return d3.rebind(brush, event, "on"); - }; - var d3_svg_brushCursor = { - n: "ns-resize", - e: "ew-resize", - s: "ns-resize", - w: "ew-resize", - nw: "nwse-resize", - ne: "nesw-resize", - se: "nwse-resize", - sw: "nesw-resize" - }; - var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; - var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; - var d3_time_formatUtc = d3_time_format.utc; - var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); - d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; - function d3_time_formatIsoNative(date) { - return date.toISOString(); - } - d3_time_formatIsoNative.parse = function(string) { - var date = new Date(string); - return isNaN(date) ? null : date; - }; - d3_time_formatIsoNative.toString = d3_time_formatIso.toString; - d3_time.second = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 1e3) * 1e3); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 1e3); - }, function(date) { - return date.getSeconds(); - }); - d3_time.seconds = d3_time.second.range; - d3_time.seconds.utc = d3_time.second.utc.range; - d3_time.minute = d3_time_interval(function(date) { - return new d3_date(Math.floor(date / 6e4) * 6e4); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 6e4); - }, function(date) { - return date.getMinutes(); - }); - d3_time.minutes = d3_time.minute.range; - d3_time.minutes.utc = d3_time.minute.utc.range; - d3_time.hour = d3_time_interval(function(date) { - var timezone = date.getTimezoneOffset() / 60; - return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); - }, function(date, offset) { - date.setTime(date.getTime() + Math.floor(offset) * 36e5); - }, function(date) { - return date.getHours(); - }); - d3_time.hours = d3_time.hour.range; - d3_time.hours.utc = d3_time.hour.utc.range; - d3_time.month = d3_time_interval(function(date) { - date = d3_time.day(date); - date.setDate(1); - return date; - }, function(date, offset) { - date.setMonth(date.getMonth() + offset); - }, function(date) { - return date.getMonth(); - }); - d3_time.months = d3_time.month.range; - d3_time.months.utc = d3_time.month.utc.range; - function d3_time_scale(linear, methods, format) { - function scale(x) { - return linear(x); - } - scale.invert = function(x) { - return d3_time_scaleDate(linear.invert(x)); + arc.padAngle = function(v) { + if (!arguments.length) return padAngle; + padAngle = d3_functor(v); + return arc; }; - scale.domain = function(x) { - if (!arguments.length) return linear.domain().map(d3_time_scaleDate); - linear.domain(x); - return scale; + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ; + return [ Math.cos(a) * r, Math.sin(a) * r ]; }; - function tickMethod(extent, count) { - var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); - return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { - return d / 31536e6; - }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; - } - scale.nice = function(interval, skip) { - var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); - if (method) interval = method[0], skip = method[1]; - function skipped(date) { - return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; + return arc; + }; + var d3_svg_arcAuto = "auto"; + function d3_svg_arcInnerRadius(d) { + return d.innerRadius; + } + function d3_svg_arcOuterRadius(d) { + return d.outerRadius; + } + function d3_svg_arcStartAngle(d) { + return d.startAngle; + } + function d3_svg_arcEndAngle(d) { + return d.endAngle; + } + function d3_svg_arcPadAngle(d) { + return d && d.padAngle; + } + function d3_svg_arcSweep(x0, y0, x1, y1) { + return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1; + } + function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) { + var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ]; + } + function d3_svg_line(projection) { + var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; + function line(data) { + var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); + function segment() { + segments.push("M", interpolate(projection(points), tension)); } - return scale.domain(d3_scale_nice(domain, skip > 1 ? { - floor: function(date) { - while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); - return date; - }, - ceil: function(date) { - while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); - return date; + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); + } else if (points.length) { + segment(); + points = []; } - } : interval)); + } + if (points.length) segment(); + return segments.length ? segments.join("") : null; + } + line.x = function(_) { + if (!arguments.length) return x; + x = _; + return line; }; - scale.ticks = function(interval, skip) { - var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { - range: interval - }, skip ]; - if (method) interval = method[0], skip = method[1]; - return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + line.y = function(_) { + if (!arguments.length) return y; + y = _; + return line; }; - scale.tickFormat = function() { - return format; + line.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return line; }; - scale.copy = function() { - return d3_time_scale(linear.copy(), methods, format); + line.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + return line; }; - return d3_scale_linearRebind(scale, linear); - } - function d3_time_scaleDate(t) { - return new Date(t); + line.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return line; + }; + return line; } - var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; - var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; - var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { - return d.getMilliseconds(); - } ], [ ":%S", function(d) { - return d.getSeconds(); - } ], [ "%I:%M", function(d) { - return d.getMinutes(); - } ], [ "%I %p", function(d) { - return d.getHours(); - } ], [ "%a %d", function(d) { - return d.getDay() && d.getDate() != 1; - } ], [ "%b %d", function(d) { - return d.getDate() != 1; - } ], [ "%B", function(d) { - return d.getMonth(); - } ], [ "%Y", d3_true ] ]); - var d3_time_scaleMilliseconds = { - range: function(start, stop, step) { - return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); - }, - floor: d3_identity, - ceil: d3_identity - }; - d3_time_scaleLocalMethods.year = d3_time.year; - d3_time.scale = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + d3.svg.line = function() { + return d3_svg_line(d3_identity); }; - var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { - return [ m[0].utc, m[1] ]; + var d3_svg_lineInterpolators = d3.map({ + linear: d3_svg_lineLinear, + "linear-closed": d3_svg_lineLinearClosed, + step: d3_svg_lineStep, + "step-before": d3_svg_lineStepBefore, + "step-after": d3_svg_lineStepAfter, + basis: d3_svg_lineBasis, + "basis-open": d3_svg_lineBasisOpen, + "basis-closed": d3_svg_lineBasisClosed, + bundle: d3_svg_lineBundle, + cardinal: d3_svg_lineCardinal, + "cardinal-open": d3_svg_lineCardinalOpen, + "cardinal-closed": d3_svg_lineCardinalClosed, + monotone: d3_svg_lineMonotone }); - var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { - return d.getUTCMilliseconds(); - } ], [ ":%S", function(d) { - return d.getUTCSeconds(); - } ], [ "%I:%M", function(d) { - return d.getUTCMinutes(); - } ], [ "%I %p", function(d) { - return d.getUTCHours(); - } ], [ "%a %d", function(d) { - return d.getUTCDay() && d.getUTCDate() != 1; - } ], [ "%b %d", function(d) { - return d.getUTCDate() != 1; - } ], [ "%B", function(d) { - return d.getUTCMonth(); - } ], [ "%Y", d3_true ] ]); - d3_time_scaleUtcMethods.year = d3_time.year.utc; - d3_time.scale.utc = function() { - return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); - }; - d3.text = d3_xhrType(function(request) { - return request.responseText; + d3_svg_lineInterpolators.forEach(function(key, value) { + value.key = key; + value.closed = /-closed$/.test(key); }); - d3.json = function(url, callback) { - return d3_xhr(url, "application/json", d3_json, callback); - }; - function d3_json(request) { - return JSON.parse(request.responseText); + function d3_svg_lineLinear(points) { + return points.length > 1 ? points.join("L") : points + "Z"; } - d3.html = function(url, callback) { - return d3_xhr(url, "text/html", d3_html, callback); - }; - function d3_html(request) { - var range = d3_document.createRange(); - range.selectNode(d3_document.body); - return range.createContextualFragment(request.responseText); + function d3_svg_lineLinearClosed(points) { + return points.join("L") + "Z"; + } + function d3_svg_lineStep(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); + if (n > 1) path.push("H", p[0]); + return path.join(""); + } + function d3_svg_lineStepBefore(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); + return path.join(""); + } + function d3_svg_lineStepAfter(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); + return path.join(""); + } + function d3_svg_lineCardinalOpen(points, tension) { + return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineCardinalClosed(points, tension) { + return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), + points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + } + function d3_svg_lineCardinal(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineHermite(points, tangents) { + if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { + return d3_svg_lineLinear(points); + } + var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; + if (quad) { + path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; + p0 = points[1]; + pi = 2; + } + if (tangents.length > 1) { + t = tangents[1]; + p = points[pi]; + pi++; + path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + for (var i = 2; i < tangents.length; i++, pi++) { + p = points[pi]; + t = tangents[i]; + path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + } + } + if (quad) { + var lp = points[pi]; + path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + } + return path; + } + function d3_svg_lineCardinalTangents(points, tension) { + var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; + while (++i < n) { + p0 = p1; + p1 = p2; + p2 = points[i]; + tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + } + return tangents; + } + function d3_svg_lineBasis(points) { + if (points.length < 3) return d3_svg_lineLinear(points); + var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + points.push(points[n - 1]); + while (++i <= n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + points.pop(); + path.push("L", pi); + return path.join(""); + } + function d3_svg_lineBasisOpen(points) { + if (points.length < 4) return d3_svg_lineLinear(points); + var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; + while (++i < 3) { + pi = points[i]; + px.push(pi[0]); + py.push(pi[1]); + } + path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); + --i; + while (++i < n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); } - d3.xml = d3_xhrType(function(request) { - return request.responseXML; - }); - if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; - this.d3 = d3; -}(); -},{}],65:[function(require,module,exports){ -arguments[4][59][0].apply(exports,arguments) -},{"dup":59,"robust-orientation":996,"simplicial-complex":68}],66:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],67:[function(require,module,exports){ -arguments[4][61][0].apply(exports,arguments) -},{"dup":61}],68:[function(require,module,exports){ -arguments[4][62][0].apply(exports,arguments) -},{"bit-twiddle":66,"dup":62,"union-find":67}],69:[function(require,module,exports){ -"use strict" - -function unique_pred(list, compare) { - var ptr = 1 - , len = list.length - , a=list[0], b=list[0] - for(var i=1; i 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); + tangents.push([ s || 0, m[i] * s || 0 ]); + } + return tangents; } - var lifted = points.map(function(p, i) { - return [ p[0], i ] - }) - lifted.sort(function(a,b) { - return a[0] - b[0] - }) - var cells = new Array(n - 1) - for(var i=1; i π) + ",1 " + p; + } + function curve(r0, p0, r1, p1) { + return "Q 0,0 " + p1; + } + chord.radius = function(v) { + if (!arguments.length) return radius; + radius = d3_functor(v); + return chord; + }; + chord.source = function(v) { + if (!arguments.length) return source; + source = d3_functor(v); + return chord; + }; + chord.target = function(v) { + if (!arguments.length) return target; + target = d3_functor(v); + return chord; + }; + chord.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return chord; + }; + chord.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return chord; + }; + return chord; + }; + function d3_svg_chordRadius(d) { + return d.radius; } - - //Lift points, sort - var lifted = new Array(n) - var upper = 1.0 - for(var i=0; i= 2) { - return false - } - } - cell[j] = v + function d3_svg_symbolCircle(size) { + var r = Math.sqrt(size / π); + return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + } + var d3_svg_symbols = d3.map({ + circle: d3_svg_symbolCircle, + cross: function(size) { + var r = Math.sqrt(size / 5) / 2; + return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; + }, + diamond: function(size) { + var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; + return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; + }, + square: function(size) { + var r = Math.sqrt(size) / 2; + return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; + }, + "triangle-down": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; + }, + "triangle-up": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; + } + }); + d3.svg.symbolTypes = d3_svg_symbols.keys(); + var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); + d3_selectionPrototype.transition = function(name) { + var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || { + time: Date.now(), + ease: d3_ease_cubicInOut, + delay: 0, + duration: 250 + }; + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) d3_transitionNode(node, i, ns, id, transition); + subgroup.push(node); } - return true - }) - } else { - hull = hull.filter(function(cell) { - for(var i=0; i<=d; ++i) { - var v = dindex[cell[i]] - if(v < 0) { - return false - } - cell[i] = v + } + return d3_transition(subgroups, ns, id); + }; + d3_selectionPrototype.interrupt = function(name) { + return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name))); + }; + var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace()); + function d3_selection_interruptNS(ns) { + return function() { + var lock, activeId, active; + if ((lock = this[ns]) && (active = lock[activeId = lock.active])) { + active.timer.c = null; + active.timer.t = NaN; + if (--lock.count) delete lock[activeId]; else delete this[ns]; + lock.active += .5; + active.event && active.event.interrupt.call(this, this.__data__, active.index); } - return true - }) + }; } - - if(d & 1) { - for(var i=0; i 0) { + tweens[--n].call(node, e); } - - if (promise._state !== lib$es6$promise$$internal$$PENDING) { - // noop - } else if (hasCallback && succeeded) { - lib$es6$promise$$internal$$resolve(promise, value); - } else if (failed) { - lib$es6$promise$$internal$$reject(promise, error); - } else if (settled === lib$es6$promise$$internal$$FULFILLED) { - lib$es6$promise$$internal$$fulfill(promise, value); - } else if (settled === lib$es6$promise$$internal$$REJECTED) { - lib$es6$promise$$internal$$reject(promise, value); + if (t >= 1) { + transition.event && transition.event.end.call(node, node.__data__, i); + if (--lock.count) delete lock[id]; else delete node[ns]; + return 1; } } - - function lib$es6$promise$$internal$$initializePromise(promise, resolver) { - try { - resolver(function resolvePromise(value){ - lib$es6$promise$$internal$$resolve(promise, value); - }, function rejectPromise(reason) { - lib$es6$promise$$internal$$reject(promise, reason); - }); - } catch(e) { - lib$es6$promise$$internal$$reject(promise, e); - } + if (!transition) { + time = inherit.time; + timer = d3_timer(schedule, 0, time); + transition = lock[id] = { + tween: new d3_Map(), + time: time, + timer: timer, + delay: inherit.delay, + duration: inherit.duration, + ease: inherit.ease, + index: i + }; + inherit = null; + ++lock.count; } - - function lib$es6$promise$enumerator$$Enumerator(Constructor, input) { - var enumerator = this; - - enumerator._instanceConstructor = Constructor; - enumerator.promise = new Constructor(lib$es6$promise$$internal$$noop); - - if (enumerator._validateInput(input)) { - enumerator._input = input; - enumerator.length = input.length; - enumerator._remaining = input.length; - - enumerator._init(); - - if (enumerator.length === 0) { - lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); + } + d3.svg.axis = function() { + var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; + function axis(g) { + g.each(function() { + var g = d3.select(this); + var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); + var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform; + var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), + d3.transition(path)); + tickEnter.append("line"); + tickEnter.append("text"); + var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2; + if (orient === "bottom" || orient === "top") { + tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2"; + text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize); } else { - enumerator.length = enumerator.length || 0; - enumerator._enumerate(); - if (enumerator._remaining === 0) { - lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); - } + tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2"; + text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start"); + pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize); } - } else { - lib$es6$promise$$internal$$reject(enumerator.promise, enumerator._validationError()); - } + lineEnter.attr(y2, sign * innerTickSize); + textEnter.attr(y1, sign * tickSpacing); + lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize); + textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing); + if (scale1.rangeBand) { + var x = scale1, dx = x.rangeBand() / 2; + scale0 = scale1 = function(d) { + return x(d) + dx; + }; + } else if (scale0.rangeBand) { + scale0 = scale1; + } else { + tickExit.call(tickTransform, scale1, scale0); + } + tickEnter.call(tickTransform, scale0, scale1); + tickUpdate.call(tickTransform, scale1, scale1); + }); } - - lib$es6$promise$enumerator$$Enumerator.prototype._validateInput = function(input) { - return lib$es6$promise$utils$$isArray(input); + axis.scale = function(x) { + if (!arguments.length) return scale; + scale = x; + return axis; }; - - lib$es6$promise$enumerator$$Enumerator.prototype._validationError = function() { - return new Error('Array Methods must be provided an Array'); + axis.orient = function(x) { + if (!arguments.length) return orient; + orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; + return axis; }; - - lib$es6$promise$enumerator$$Enumerator.prototype._init = function() { - this._result = new Array(this.length); + axis.ticks = function() { + if (!arguments.length) return tickArguments_; + tickArguments_ = d3_array(arguments); + return axis; }; - - var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator; - - lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() { - var enumerator = this; - - var length = enumerator.length; - var promise = enumerator.promise; - var input = enumerator._input; - - for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) { - enumerator._eachEntry(input[i], i); - } + axis.tickValues = function(x) { + if (!arguments.length) return tickValues; + tickValues = x; + return axis; }; - - lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { - var enumerator = this; - var c = enumerator._instanceConstructor; - - if (lib$es6$promise$utils$$isMaybeThenable(entry)) { - if (entry.constructor === c && entry._state !== lib$es6$promise$$internal$$PENDING) { - entry._onerror = null; - enumerator._settledAt(entry._state, i, entry._result); - } else { - enumerator._willSettleAt(c.resolve(entry), i); - } - } else { - enumerator._remaining--; - enumerator._result[i] = entry; - } + axis.tickFormat = function(x) { + if (!arguments.length) return tickFormat_; + tickFormat_ = x; + return axis; }; - - lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { - var enumerator = this; - var promise = enumerator.promise; - - if (promise._state === lib$es6$promise$$internal$$PENDING) { - enumerator._remaining--; - - if (state === lib$es6$promise$$internal$$REJECTED) { - lib$es6$promise$$internal$$reject(promise, value); + axis.tickSize = function(x) { + var n = arguments.length; + if (!n) return innerTickSize; + innerTickSize = +x; + outerTickSize = +arguments[n - 1]; + return axis; + }; + axis.innerTickSize = function(x) { + if (!arguments.length) return innerTickSize; + innerTickSize = +x; + return axis; + }; + axis.outerTickSize = function(x) { + if (!arguments.length) return outerTickSize; + outerTickSize = +x; + return axis; + }; + axis.tickPadding = function(x) { + if (!arguments.length) return tickPadding; + tickPadding = +x; + return axis; + }; + axis.tickSubdivide = function() { + return arguments.length && axis; + }; + return axis; + }; + var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { + top: 1, + right: 1, + bottom: 1, + left: 1 + }; + function d3_svg_axisX(selection, x0, x1) { + selection.attr("transform", function(d) { + var v0 = x0(d); + return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)"; + }); + } + function d3_svg_axisY(selection, y0, y1) { + selection.attr("transform", function(d) { + var v0 = y0(d); + return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")"; + }); + } + d3.svg.brush = function() { + var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; + function brush(g) { + g.each(function() { + var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); + var background = g.selectAll(".background").data([ 0 ]); + background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); + g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); + var resize = g.selectAll(".resize").data(resizes, d3_identity); + resize.exit().remove(); + resize.enter().append("g").attr("class", function(d) { + return "resize " + d; + }).style("cursor", function(d) { + return d3_svg_brushCursor[d]; + }).append("rect").attr("x", function(d) { + return /[ew]$/.test(d) ? -3 : null; + }).attr("y", function(d) { + return /^[ns]/.test(d) ? -3 : null; + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); + resize.style("display", brush.empty() ? "none" : null); + var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; + if (x) { + range = d3_scaleRange(x); + backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); + redrawX(gUpdate); + } + if (y) { + range = d3_scaleRange(y); + backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); + redrawY(gUpdate); + } + redraw(gUpdate); + }); + } + brush.event = function(g) { + g.each(function() { + var event_ = event.of(this, arguments), extent1 = { + x: xExtent, + y: yExtent, + i: xExtentDomain, + j: yExtentDomain + }, extent0 = this.__chart__ || extent1; + this.__chart__ = extent1; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.brush", function() { + xExtentDomain = extent0.i; + yExtentDomain = extent0.j; + xExtent = extent0.x; + yExtent = extent0.y; + event_({ + type: "brushstart" + }); + }).tween("brush:brush", function() { + var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); + xExtentDomain = yExtentDomain = null; + return function(t) { + xExtent = extent1.x = xi(t); + yExtent = extent1.y = yi(t); + event_({ + type: "brush", + mode: "resize" + }); + }; + }).each("end.brush", function() { + xExtentDomain = extent1.i; + yExtentDomain = extent1.j; + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + }); } else { - enumerator._result[i] = value; + event_({ + type: "brushstart" + }); + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); } - } - - if (enumerator._remaining === 0) { - lib$es6$promise$$internal$$fulfill(promise, enumerator._result); - } - }; - - lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { - var enumerator = this; - - lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) { - enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value); - }, function(reason) { - enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason); }); }; - function lib$es6$promise$promise$all$$all(entries) { - return new lib$es6$promise$enumerator$$default(this, entries).promise; + function redraw(g) { + g.selectAll(".resize").attr("transform", function(d) { + return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; + }); } - var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all; - function lib$es6$promise$promise$race$$race(entries) { - /*jshint validthis:true */ - var Constructor = this; - - var promise = new Constructor(lib$es6$promise$$internal$$noop); - - if (!lib$es6$promise$utils$$isArray(entries)) { - lib$es6$promise$$internal$$reject(promise, new TypeError('You must pass an array to race.')); - return promise; + function redrawX(g) { + g.select(".extent").attr("x", xExtent[0]); + g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); + } + function redrawY(g) { + g.select(".extent").attr("y", yExtent[0]); + g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); + } + function brushstart() { + var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset; + var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup); + if (d3.event.changedTouches) { + w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); + } else { + w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); } - - var length = entries.length; - - function onFulfillment(value) { - lib$es6$promise$$internal$$resolve(promise, value); + g.interrupt().selectAll("*").interrupt(); + if (dragging) { + origin[0] = xExtent[0] - origin[0]; + origin[1] = yExtent[0] - origin[1]; + } else if (resizing) { + var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); + offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; + origin[0] = xExtent[ex]; + origin[1] = yExtent[ey]; + } else if (d3.event.altKey) center = origin.slice(); + g.style("pointer-events", "none").selectAll(".resize").style("display", null); + d3.select("body").style("cursor", eventTarget.style("cursor")); + event_({ + type: "brushstart" + }); + brushmove(); + function keydown() { + if (d3.event.keyCode == 32) { + if (!dragging) { + center = null; + origin[0] -= xExtent[1]; + origin[1] -= yExtent[1]; + dragging = 2; + } + d3_eventPreventDefault(); + } } - - function onRejection(reason) { - lib$es6$promise$$internal$$reject(promise, reason); + function keyup() { + if (d3.event.keyCode == 32 && dragging == 2) { + origin[0] += xExtent[1]; + origin[1] += yExtent[1]; + dragging = 0; + d3_eventPreventDefault(); + } } - - for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) { - lib$es6$promise$$internal$$subscribe(Constructor.resolve(entries[i]), undefined, onFulfillment, onRejection); + function brushmove() { + var point = d3.mouse(target), moved = false; + if (offset) { + point[0] += offset[0]; + point[1] += offset[1]; + } + if (!dragging) { + if (d3.event.altKey) { + if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; + origin[0] = xExtent[+(point[0] < center[0])]; + origin[1] = yExtent[+(point[1] < center[1])]; + } else center = null; + } + if (resizingX && move1(point, x, 0)) { + redrawX(g); + moved = true; + } + if (resizingY && move1(point, y, 1)) { + redrawY(g); + moved = true; + } + if (moved) { + redraw(g); + event_({ + type: "brush", + mode: dragging ? "move" : "resize" + }); + } } - - return promise; - } - var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race; - function lib$es6$promise$promise$resolve$$resolve(object) { - /*jshint validthis:true */ - var Constructor = this; - - if (object && typeof object === 'object' && object.constructor === Constructor) { - return object; + function move1(point, scale, i) { + var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; + if (dragging) { + r0 -= position; + r1 -= size + position; + } + min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; + if (dragging) { + max = (min += position) + size; + } else { + if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); + if (position < min) { + max = min; + min = position; + } else { + max = position; + } + } + if (extent[0] != min || extent[1] != max) { + if (i) yExtentDomain = null; else xExtentDomain = null; + extent[0] = min; + extent[1] = max; + return true; + } } - - var promise = new Constructor(lib$es6$promise$$internal$$noop); - lib$es6$promise$$internal$$resolve(promise, object); - return promise; - } - var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve; - function lib$es6$promise$promise$reject$$reject(reason) { - /*jshint validthis:true */ - var Constructor = this; - var promise = new Constructor(lib$es6$promise$$internal$$noop); - lib$es6$promise$$internal$$reject(promise, reason); - return promise; - } - var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject; - - var lib$es6$promise$promise$$counter = 0; - - function lib$es6$promise$promise$$needsResolver() { - throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); - } - - function lib$es6$promise$promise$$needsNew() { - throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); - } - - var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise; - /** - Promise objects represent the eventual result of an asynchronous operation. The - primary way of interacting with a promise is through its `then` method, which - registers callbacks to receive either a promise's eventual value or the reason - why the promise cannot be fulfilled. - - Terminology - ----------- - - - `promise` is an object or function with a `then` method whose behavior conforms to this specification. - - `thenable` is an object or function that defines a `then` method. - - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). - - `exception` is a value that is thrown using the throw statement. - - `reason` is a value that indicates why a promise was rejected. - - `settled` the final resting state of a promise, fulfilled or rejected. - - A promise can be in one of three states: pending, fulfilled, or rejected. - - Promises that are fulfilled have a fulfillment value and are in the fulfilled - state. Promises that are rejected have a rejection reason and are in the - rejected state. A fulfillment value is never a thenable. - - Promises can also be said to *resolve* a value. If this value is also a - promise, then the original promise's settled state will match the value's - settled state. So a promise that *resolves* a promise that rejects will - itself reject, and a promise that *resolves* a promise that fulfills will - itself fulfill. - - - Basic Usage: - ------------ - - ```js - var promise = new Promise(function(resolve, reject) { - // on success - resolve(value); - - // on failure - reject(reason); - }); - - promise.then(function(value) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Advanced Usage: - --------------- - - Promises shine when abstracting away asynchronous interactions such as - `XMLHttpRequest`s. - - ```js - function getJSON(url) { - return new Promise(function(resolve, reject){ - var xhr = new XMLHttpRequest(); - - xhr.open('GET', url); - xhr.onreadystatechange = handler; - xhr.responseType = 'json'; - xhr.setRequestHeader('Accept', 'application/json'); - xhr.send(); - - function handler() { - if (this.readyState === this.DONE) { - if (this.status === 200) { - resolve(this.response); - } else { - reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); - } - } - }; + function brushend() { + brushmove(); + g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); + d3.select("body").style("cursor", null); + w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); + dragRestore(); + event_({ + type: "brushend" }); } - - getJSON('/posts.json').then(function(json) { - // on fulfillment - }, function(reason) { - // on rejection - }); - ``` - - Unlike callbacks, promises are great composable primitives. - - ```js - Promise.all([ - getJSON('/posts'), - getJSON('/comments') - ]).then(function(values){ - values[0] // => postsJSON - values[1] // => commentsJSON - - return values; - }); - ``` - - @class Promise - @param {function} resolver - Useful for tooling. - @constructor - */ - function lib$es6$promise$promise$$Promise(resolver) { - this._id = lib$es6$promise$promise$$counter++; - this._state = undefined; - this._result = undefined; - this._subscribers = []; - - if (lib$es6$promise$$internal$$noop !== resolver) { - if (!lib$es6$promise$utils$$isFunction(resolver)) { - lib$es6$promise$promise$$needsResolver(); + } + brush.x = function(z) { + if (!arguments.length) return x; + x = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.y = function(z) { + if (!arguments.length) return y; + y = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.clamp = function(z) { + if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; + if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; + return brush; + }; + brush.extent = function(z) { + var x0, x1, y0, y1, t; + if (!arguments.length) { + if (x) { + if (xExtentDomain) { + x0 = xExtentDomain[0], x1 = xExtentDomain[1]; + } else { + x0 = xExtent[0], x1 = xExtent[1]; + if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + } } - - if (!(this instanceof lib$es6$promise$promise$$Promise)) { - lib$es6$promise$promise$$needsNew(); + if (y) { + if (yExtentDomain) { + y0 = yExtentDomain[0], y1 = yExtentDomain[1]; + } else { + y0 = yExtent[0], y1 = yExtent[1]; + if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + } } - - lib$es6$promise$$internal$$initializePromise(this, resolver); + return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; + } + if (x) { + x0 = z[0], x1 = z[1]; + if (y) x0 = x0[0], x1 = x1[0]; + xExtentDomain = [ x0, x1 ]; + if (x.invert) x0 = x(x0), x1 = x(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; + } + if (y) { + y0 = z[0], y1 = z[1]; + if (x) y0 = y0[1], y1 = y1[1]; + yExtentDomain = [ y0, y1 ]; + if (y.invert) y0 = y(y0), y1 = y(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; + } + return brush; + }; + brush.clear = function() { + if (!brush.empty()) { + xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; + xExtentDomain = yExtentDomain = null; } + return brush; + }; + brush.empty = function() { + return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + }; + return d3.rebind(brush, event, "on"); + }; + var d3_svg_brushCursor = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; + var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; + var d3_time_formatUtc = d3_time_format.utc; + var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; + function d3_time_formatIsoNative(date) { + return date.toISOString(); + } + d3_time_formatIsoNative.parse = function(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + }; + d3_time_formatIsoNative.toString = d3_time_formatIso.toString; + d3_time.second = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 1e3) * 1e3); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 1e3); + }, function(date) { + return date.getSeconds(); + }); + d3_time.seconds = d3_time.second.range; + d3_time.seconds.utc = d3_time.second.utc.range; + d3_time.minute = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 6e4) * 6e4); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 6e4); + }, function(date) { + return date.getMinutes(); + }); + d3_time.minutes = d3_time.minute.range; + d3_time.minutes.utc = d3_time.minute.utc.range; + d3_time.hour = d3_time_interval(function(date) { + var timezone = date.getTimezoneOffset() / 60; + return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 36e5); + }, function(date) { + return date.getHours(); + }); + d3_time.hours = d3_time.hour.range; + d3_time.hours.utc = d3_time.hour.utc.range; + d3_time.month = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setDate(1); + return date; + }, function(date, offset) { + date.setMonth(date.getMonth() + offset); + }, function(date) { + return date.getMonth(); + }); + d3_time.months = d3_time.month.range; + d3_time.months.utc = d3_time.month.utc.range; + function d3_time_scale(linear, methods, format) { + function scale(x) { + return linear(x); } - - lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default; - lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default; - lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default; - lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default; - lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler; - lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap; - lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap; - - lib$es6$promise$promise$$Promise.prototype = { - constructor: lib$es6$promise$promise$$Promise, - - /** - The primary way of interacting with a promise is through its `then` method, - which registers callbacks to receive either a promise's eventual value or the - reason why the promise cannot be fulfilled. - - ```js - findUser().then(function(user){ - // user is available - }, function(reason){ - // user is unavailable, and you are given the reason why - }); - ``` - - Chaining - -------- - - The return value of `then` is itself a promise. This second, 'downstream' - promise is resolved with the return value of the first promise's fulfillment - or rejection handler, or rejected if the handler throws an exception. - - ```js - findUser().then(function (user) { - return user.name; - }, function (reason) { - return 'default name'; - }).then(function (userName) { - // If `findUser` fulfilled, `userName` will be the user's name, otherwise it - // will be `'default name'` - }); - - findUser().then(function (user) { - throw new Error('Found user, but still unhappy'); - }, function (reason) { - throw new Error('`findUser` rejected and we're unhappy'); - }).then(function (value) { - // never reached - }, function (reason) { - // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. - // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. - }); - ``` - If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. - - ```js - findUser().then(function (user) { - throw new PedagogicalException('Upstream error'); - }).then(function (value) { - // never reached - }).then(function (value) { - // never reached - }, function (reason) { - // The `PedgagocialException` is propagated all the way down to here - }); - ``` - - Assimilation - ------------ - - Sometimes the value you want to propagate to a downstream promise can only be - retrieved asynchronously. This can be achieved by returning a promise in the - fulfillment or rejection handler. The downstream promise will then be pending - until the returned promise is settled. This is called *assimilation*. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // The user's comments are now available - }); - ``` - - If the assimliated promise rejects, then the downstream promise will also reject. - - ```js - findUser().then(function (user) { - return findCommentsByAuthor(user); - }).then(function (comments) { - // If `findCommentsByAuthor` fulfills, we'll have the value here - }, function (reason) { - // If `findCommentsByAuthor` rejects, we'll have the reason here - }); - ``` - - Simple Example - -------------- - - Synchronous Example - - ```javascript - var result; - - try { - result = findResult(); - // success - } catch(reason) { - // failure + scale.invert = function(x) { + return d3_time_scaleDate(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return linear.domain().map(d3_time_scaleDate); + linear.domain(x); + return scale; + }; + function tickMethod(extent, count) { + var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); + return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { + return d / 31536e6; + }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; + } + scale.nice = function(interval, skip) { + var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); + if (method) interval = method[0], skip = method[1]; + function skipped(date) { + return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; } - ``` - - Errback Example - - ```js - findResult(function(result, err){ - if (err) { - // failure - } else { - // success + return scale.domain(d3_scale_nice(domain, skip > 1 ? { + floor: function(date) { + while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); + return date; + }, + ceil: function(date) { + while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); + return date; } - }); - ``` + } : interval)); + }; + scale.ticks = function(interval, skip) { + var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { + range: interval + }, skip ]; + if (method) interval = method[0], skip = method[1]; + return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + }; + scale.tickFormat = function() { + return format; + }; + scale.copy = function() { + return d3_time_scale(linear.copy(), methods, format); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_time_scaleDate(t) { + return new Date(t); + } + var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; + var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; + var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { + return d.getMilliseconds(); + } ], [ ":%S", function(d) { + return d.getSeconds(); + } ], [ "%I:%M", function(d) { + return d.getMinutes(); + } ], [ "%I %p", function(d) { + return d.getHours(); + } ], [ "%a %d", function(d) { + return d.getDay() && d.getDate() != 1; + } ], [ "%b %d", function(d) { + return d.getDate() != 1; + } ], [ "%B", function(d) { + return d.getMonth(); + } ], [ "%Y", d3_true ] ]); + var d3_time_scaleMilliseconds = { + range: function(start, stop, step) { + return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); + }, + floor: d3_identity, + ceil: d3_identity + }; + d3_time_scaleLocalMethods.year = d3_time.year; + d3_time.scale = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + }; + var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { + return [ m[0].utc, m[1] ]; + }); + var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { + return d.getUTCMilliseconds(); + } ], [ ":%S", function(d) { + return d.getUTCSeconds(); + } ], [ "%I:%M", function(d) { + return d.getUTCMinutes(); + } ], [ "%I %p", function(d) { + return d.getUTCHours(); + } ], [ "%a %d", function(d) { + return d.getUTCDay() && d.getUTCDate() != 1; + } ], [ "%b %d", function(d) { + return d.getUTCDate() != 1; + } ], [ "%B", function(d) { + return d.getUTCMonth(); + } ], [ "%Y", d3_true ] ]); + d3_time_scaleUtcMethods.year = d3_time.year.utc; + d3_time.scale.utc = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); + }; + d3.text = d3_xhrType(function(request) { + return request.responseText; + }); + d3.json = function(url, callback) { + return d3_xhr(url, "application/json", d3_json, callback); + }; + function d3_json(request) { + return JSON.parse(request.responseText); + } + d3.html = function(url, callback) { + return d3_xhr(url, "text/html", d3_html, callback); + }; + function d3_html(request) { + var range = d3_document.createRange(); + range.selectNode(d3_document.body); + return range.createContextualFragment(request.responseText); + } + d3.xml = d3_xhrType(function(request) { + return request.responseXML; + }); + if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3; +}(); +},{}],71:[function(require,module,exports){ +"use strict" - Promise Example; +var ch = require("incremental-convex-hull") +var uniq = require("uniq") - ```javascript - findResult().then(function(result){ - // success - }, function(reason){ - // failure - }); - ``` +module.exports = triangulate - Advanced Example - -------------- +function LiftedPoint(p, i) { + this.point = p + this.index = i +} - Synchronous Example +function compareLifted(a, b) { + var ap = a.point + var bp = b.point + var d = ap.length + for(var i=0; i= 2) { + return false } - // success - } - }); - ``` - - Promise Example; - - ```javascript - findAuthor(). - then(findBooksByAuthor). - then(function(books){ - // found books - }).catch(function(reason){ - // something went wrong - }); - ``` - - @method then - @param {Function} onFulfilled - @param {Function} onRejected - Useful for tooling. - @return {Promise} - */ - then: function(onFulfillment, onRejection) { - var parent = this; - var state = parent._state; - - if (state === lib$es6$promise$$internal$$FULFILLED && !onFulfillment || state === lib$es6$promise$$internal$$REJECTED && !onRejection) { - return this; - } - - var child = new this.constructor(lib$es6$promise$$internal$$noop); - var result = parent._result; - - if (state) { - var callback = arguments[state - 1]; - lib$es6$promise$asap$$asap(function(){ - lib$es6$promise$$internal$$invokeCallback(state, child, callback, result); - }); - } else { - lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection); } - - return child; - }, - - /** - `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same - as the catch block of a try/catch statement. - - ```js - function findAuthor(){ - throw new Error('couldn't find that author'); - } - - // synchronous - try { - findAuthor(); - } catch(reason) { - // something went wrong - } - - // async with promises - findAuthor().catch(function(reason){ - // something went wrong - }); - ``` - - @method catch - @param {Function} onRejection - Useful for tooling. - @return {Promise} - */ - 'catch': function(onRejection) { - return this.then(null, onRejection); - } - }; - function lib$es6$promise$polyfill$$polyfill() { - var local; - - if (typeof global !== 'undefined') { - local = global; - } else if (typeof self !== 'undefined') { - local = self; - } else { - try { - local = Function('return this')(); - } catch (e) { - throw new Error('polyfill failed because global object is unavailable in this environment'); - } + cell[j] = v } - - var P = local.Promise; - - if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) { - return; + return true + }) + } else { + hull = hull.filter(function(cell) { + for(var i=0; i<=d; ++i) { + var v = dindex[cell[i]] + if(v < 0) { + return false + } + cell[i] = v } + return true + }) + } - local.Promise = lib$es6$promise$promise$$default; + if(d & 1) { + for(var i=0; i - * but significantly simplified and sped up by ignoring number and string constructors - * ie these return false: - * new Number(1) - * new String('1') - */ - -'use strict'; - -/** - * Is this string all whitespace? - * This solution kind of makes my brain hurt, but it's significantly faster - * than !str.trim() or any other solution I could find. - * - * whitespace codes from: http://en.wikipedia.org/wiki/Whitespace_character - * and verified with: - * - * for(var i = 0; i < 65536; i++) { - * var s = String.fromCharCode(i); - * if(+s===0 && !s.trim()) console.log(i, s); - * } - * - * which counts a couple of these as *not* whitespace, but finds nothing else - * that *is* whitespace. Note that charCodeAt stops at 16 bits, but it appears - * that there are no whitespace characters above this, and code points above - * this do not map onto white space characters. - */ -function allBlankCharCodes(str){ - var l = str.length, - a; - for(var i = 0; i < l; i++) { - a = str.charCodeAt(i); - if((a < 9 || a > 13) && (a !== 32) && (a !== 133) && (a !== 160) && - (a !== 5760) && (a !== 6158) && (a < 8192 || a > 8205) && - (a !== 8232) && (a !== 8233) && (a !== 8239) && (a !== 8287) && - (a !== 8288) && (a !== 12288) && (a !== 65279)) { - return false; - } + } else { + for(j=0; j 0) { + return dupe_number(count|0, value) + } + break + case "object": + if(typeof (count.length) === "number") { + return dupe_array(count, value, 0) + } + break + } + return [] +} +module.exports = dupe },{}],73:[function(require,module,exports){ -'use strict' - -var createShader = require('gl-shader') -var createBuffer = require('gl-buffer') -var pool = require('typedarray-pool') -var shaders = require('./lib/shaders') - -module.exports = createError2D - -var WEIGHTS = [ - //x-error bar - [ 1, 0, 0, 1, 0, 0], - [ 1, 0, 0,-1, 0, 0], - [-1, 0, 0,-1, 0, 0], - - [-1, 0, 0,-1, 0, 0], - [-1, 0, 0, 1, 0, 0], - [ 1, 0, 0, 1, 0, 0], - - //x-error right cap - [ 1, 0, -1, 0, 0, 1], - [ 1, 0, -1, 0, 0,-1], - [ 1, 0, 1, 0, 0,-1], - - [ 1, 0, 1, 0, 0,-1], - [ 1, 0, 1, 0, 0, 1], - [ 1, 0, -1, 0, 0, 1], - - //x-error left cap - [-1, 0, -1, 0, 0, 1], - [-1, 0, -1, 0, 0,-1], - [-1, 0, 1, 0, 0,-1], - - [-1, 0, 1, 0, 0,-1], - [-1, 0, 1, 0, 0, 1], - [-1, 0, -1, 0, 0, 1], - - //y-error bar - [0, 1, 1, 0, 0, 0], - [0, 1,-1, 0, 0, 0], - [0,-1,-1, 0, 0, 0], - - [0,-1,-1, 0, 0, 0], - [0, 1, 1, 0, 0, 0], - [0,-1, 1, 0, 0, 0], - - //y-error top cap - [ 0, 1, 0,-1, 1, 0], - [ 0, 1, 0,-1,-1, 0], - [ 0, 1, 0, 1,-1, 0], +(function (process,global){ +/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE + * @version 3.0.2 + */ - [ 0, 1, 0, 1, 1, 0], - [ 0, 1, 0,-1, 1, 0], - [ 0, 1, 0, 1,-1, 0], +(function() { + "use strict"; + function lib$es6$promise$utils$$objectOrFunction(x) { + return typeof x === 'function' || (typeof x === 'object' && x !== null); + } - //y-error bottom cap - [ 0,-1, 0,-1, 1, 0], - [ 0,-1, 0,-1,-1, 0], - [ 0,-1, 0, 1,-1, 0], + function lib$es6$promise$utils$$isFunction(x) { + return typeof x === 'function'; + } - [ 0,-1, 0, 1, 1, 0], - [ 0,-1, 0,-1, 1, 0], - [ 0,-1, 0, 1,-1, 0] -] + function lib$es6$promise$utils$$isMaybeThenable(x) { + return typeof x === 'object' && x !== null; + } -function GLError2D(plot, shader, buffer) { - this.plot = plot + var lib$es6$promise$utils$$_isArray; + if (!Array.isArray) { + lib$es6$promise$utils$$_isArray = function (x) { + return Object.prototype.toString.call(x) === '[object Array]'; + }; + } else { + lib$es6$promise$utils$$_isArray = Array.isArray; + } - this.shader = shader - this.buffer = buffer + var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray; + var lib$es6$promise$asap$$len = 0; + var lib$es6$promise$asap$$toString = {}.toString; + var lib$es6$promise$asap$$vertxNext; + var lib$es6$promise$asap$$customSchedulerFn; - this.bounds = [Infinity, Infinity, -Infinity, -Infinity] + var lib$es6$promise$asap$$asap = function asap(callback, arg) { + lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback; + lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg; + lib$es6$promise$asap$$len += 2; + if (lib$es6$promise$asap$$len === 2) { + // If len is 2, that means that we need to schedule an async flush. + // If additional callbacks are queued before the queue is flushed, they + // will be processed by this flush that we are scheduling. + if (lib$es6$promise$asap$$customSchedulerFn) { + lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush); + } else { + lib$es6$promise$asap$$scheduleFlush(); + } + } + } - this.numPoints = 0 + function lib$es6$promise$asap$$setScheduler(scheduleFn) { + lib$es6$promise$asap$$customSchedulerFn = scheduleFn; + } - this.color = [0,0,0,1] -} + function lib$es6$promise$asap$$setAsap(asapFn) { + lib$es6$promise$asap$$asap = asapFn; + } -var proto = GLError2D.prototype + var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined; + var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {}; + var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver; + var lib$es6$promise$asap$$isNode = typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; -proto.draw = (function() { + // test for web worker but not in IE10 + var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' && + typeof importScripts !== 'undefined' && + typeof MessageChannel !== 'undefined'; - var MATRIX = [ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ] + // node + function lib$es6$promise$asap$$useNextTick() { + // node version 0.10.x displays a deprecation warning when nextTick is used recursively + // see https://github.com/cujojs/when/issues/410 for details + return function() { + process.nextTick(lib$es6$promise$asap$$flush); + }; + } - var PIXEL_SCALE = [1,1] + // vertx + function lib$es6$promise$asap$$useVertxTimer() { + return function() { + lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush); + }; + } - return function() { - var plot = this.plot - var shader = this.shader - var buffer = this.buffer - var bounds = this.bounds - var numPoints = this.numPoints - var color = this.color + function lib$es6$promise$asap$$useMutationObserver() { + var iterations = 0; + var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush); + var node = document.createTextNode(''); + observer.observe(node, { characterData: true }); - var gl = plot.gl - var dataBox = plot.dataBox - var viewBox = plot.viewBox - var pixelRatio = plot.pixelRatio + return function() { + node.data = (iterations = ++iterations % 2); + }; + } - var boundX = bounds[2] - bounds[0] - var boundY = bounds[3] - bounds[1] - var dataX = dataBox[2] - dataBox[0] - var dataY = dataBox[3] - dataBox[1] + // web worker + function lib$es6$promise$asap$$useMessageChannel() { + var channel = new MessageChannel(); + channel.port1.onmessage = lib$es6$promise$asap$$flush; + return function () { + channel.port2.postMessage(0); + }; + } - MATRIX[0] = 2.0 * boundX / dataX - MATRIX[4] = 2.0 * boundY / dataY - MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 - MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 + function lib$es6$promise$asap$$useSetTimeout() { + return function() { + setTimeout(lib$es6$promise$asap$$flush, 1); + }; + } - var screenX = viewBox[2] - viewBox[0] - var screenY = viewBox[3] - viewBox[1] + var lib$es6$promise$asap$$queue = new Array(1000); + function lib$es6$promise$asap$$flush() { + for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) { + var callback = lib$es6$promise$asap$$queue[i]; + var arg = lib$es6$promise$asap$$queue[i+1]; - PIXEL_SCALE[0] = 2.0 * pixelRatio / screenX - PIXEL_SCALE[1] = 2.0 * pixelRatio / screenY + callback(arg); - buffer.bind() - shader.bind() + lib$es6$promise$asap$$queue[i] = undefined; + lib$es6$promise$asap$$queue[i+1] = undefined; + } - shader.uniforms.viewTransform = MATRIX - shader.uniforms.pixelScale = PIXEL_SCALE - shader.uniforms.color = this.color + lib$es6$promise$asap$$len = 0; + } - shader.attributes.position.pointer( - gl.FLOAT, - false, - 16, - 0) + function lib$es6$promise$asap$$attemptVertx() { + try { + var r = require; + var vertx = r('vertx'); + lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext; + return lib$es6$promise$asap$$useVertxTimer(); + } catch(e) { + return lib$es6$promise$asap$$useSetTimeout(); + } + } - shader.attributes.pixelOffset.pointer( - gl.FLOAT, - false, - 16, - 8) + var lib$es6$promise$asap$$scheduleFlush; + // Decide what async method to use to triggering processing of queued callbacks: + if (lib$es6$promise$asap$$isNode) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick(); + } else if (lib$es6$promise$asap$$BrowserMutationObserver) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver(); + } else if (lib$es6$promise$asap$$isWorker) { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel(); + } else if (lib$es6$promise$asap$$browserWindow === undefined && typeof require === 'function') { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertx(); + } else { + lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout(); + } - gl.drawArrays(gl.TRIANGLES, 0, numPoints * WEIGHTS.length) - } -})() + function lib$es6$promise$$internal$$noop() {} -proto.drawPick = function(offset) { return offset } -proto.pick = function(x, y) { - return null -} + var lib$es6$promise$$internal$$PENDING = void 0; + var lib$es6$promise$$internal$$FULFILLED = 1; + var lib$es6$promise$$internal$$REJECTED = 2; -proto.update = function(options) { - options = options || {} + var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject(); - var positions = options.positions || [] - var errors = options.errors || [] + function lib$es6$promise$$internal$$selfFulfillment() { + return new TypeError("You cannot resolve a promise with itself"); + } - var lineWidth = 1 - if('lineWidth' in options) { - lineWidth = +options.lineWidth - } + function lib$es6$promise$$internal$$cannotReturnOwn() { + return new TypeError('A promises callback cannot return that same promise.'); + } - var capSize = 5 - if('capSize' in options) { - capSize = +options.capSize - } + function lib$es6$promise$$internal$$getThen(promise) { + try { + return promise.then; + } catch(error) { + lib$es6$promise$$internal$$GET_THEN_ERROR.error = error; + return lib$es6$promise$$internal$$GET_THEN_ERROR; + } + } - this.color = (options.color || [0,0,0,1]).slice() + function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) { + try { + then.call(value, fulfillmentHandler, rejectionHandler); + } catch(e) { + return e; + } + } - var bounds = this.bounds = [Infinity, Infinity, -Infinity, -Infinity] + function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) { + lib$es6$promise$asap$$asap(function(promise) { + var sealed = false; + var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) { + if (sealed) { return; } + sealed = true; + if (thenable !== value) { + lib$es6$promise$$internal$$resolve(promise, value); + } else { + lib$es6$promise$$internal$$fulfill(promise, value); + } + }, function(reason) { + if (sealed) { return; } + sealed = true; - var numPoints = this.numPoints = positions.length>>1 - for(var i=0; i 0) { - dx *= ex1 + function lib$es6$promise$$internal$$resolve(promise, value) { + if (promise === value) { + lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFulfillment()); + } else if (lib$es6$promise$utils$$objectOrFunction(value)) { + lib$es6$promise$$internal$$handleMaybeThenable(promise, value); + } else { + lib$es6$promise$$internal$$fulfill(promise, value); } + } - if(dy < 0) { - dy *= ey0 - } else if(dy > 0) { - dy *= ey1 + function lib$es6$promise$$internal$$publishRejection(promise) { + if (promise._onerror) { + promise._onerror(promise._result); } - bufferData[ptr++] = sx * ((x - tx) + dx) - bufferData[ptr++] = sy * ((y - ty) + dy) - bufferData[ptr++] = lineWidth * w[2] + (capSize + lineWidth) * w[4] - bufferData[ptr++] = lineWidth * w[3] + (capSize + lineWidth) * w[5] + lib$es6$promise$$internal$$publish(promise); } - } - this.buffer.update(bufferData) - pool.free(bufferData) -} -proto.dispose = function() { - this.plot.removeObject(this) - this.shader.dispose() - this.buffer.dispose() -} + function lib$es6$promise$$internal$$fulfill(promise, value) { + if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; } -function createError2D(plot, options) { - var shader = createShader(plot.gl, shaders.vertex, shaders.fragment) - var buffer = createBuffer(plot.gl) + promise._result = value; + promise._state = lib$es6$promise$$internal$$FULFILLED; - var errorbars = new GLError2D(plot, shader, buffer) + if (promise._subscribers.length !== 0) { + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise); + } + } - errorbars.update(options) + function lib$es6$promise$$internal$$reject(promise, reason) { + if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; } + promise._state = lib$es6$promise$$internal$$REJECTED; + promise._result = reason; - plot.addObject(errorbars) + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise); + } - return errorbars -} + function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) { + var subscribers = parent._subscribers; + var length = subscribers.length; -},{"./lib/shaders":74,"gl-buffer":75,"gl-shader":76,"typedarray-pool":102}],74:[function(require,module,exports){ + parent._onerror = null; + subscribers[length] = child; + subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment; + subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection; -module.exports = { - vertex: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 position;\nattribute vec2 pixelOffset;\n\nuniform mat3 viewTransform;\nuniform vec2 pixelScale;\n\nvoid main() {\n vec3 scrPosition = viewTransform * vec3(position, 1);\n gl_Position = vec4(\n scrPosition.xy + scrPosition.z * pixelScale * pixelOffset,\n 0,\n scrPosition.z);\n}\n", - fragment: "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n gl_FragColor = vec4(color.rgb * color.a, color.a);\n}\n" -} + if (length === 0 && parent._state) { + lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent); + } + } -},{}],75:[function(require,module,exports){ -"use strict" + function lib$es6$promise$$internal$$publish(promise) { + var subscribers = promise._subscribers; + var settled = promise._state; -var pool = require("typedarray-pool") -var ops = require("ndarray-ops") -var ndarray = require("ndarray") + if (subscribers.length === 0) { return; } -var SUPPORTED_TYPES = [ - "uint8", - "uint8_clamped", - "uint16", - "uint32", - "int8", - "int16", - "int32", - "float32" ] + var child, callback, detail = promise._result; -function GLBuffer(gl, type, handle, length, usage) { - this.gl = gl - this.type = type - this.handle = handle - this.length = length - this.usage = usage -} + for (var i = 0; i < subscribers.length; i += 3) { + child = subscribers[i]; + callback = subscribers[i + settled]; -var proto = GLBuffer.prototype + if (child) { + lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail); + } else { + callback(detail); + } + } -proto.bind = function() { - this.gl.bindBuffer(this.type, this.handle) -} + promise._subscribers.length = 0; + } -proto.unbind = function() { - this.gl.bindBuffer(this.type, null) -} + function lib$es6$promise$$internal$$ErrorObject() { + this.error = null; + } -proto.dispose = function() { - this.gl.deleteBuffer(this.handle) -} + var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject(); -function updateTypeArray(gl, type, len, usage, data, offset) { - var dataLen = data.length * data.BYTES_PER_ELEMENT - if(offset < 0) { - gl.bufferData(type, data, usage) - return dataLen - } - if(dataLen + offset > len) { - throw new Error("gl-buffer: If resizing buffer, must not specify offset") - } - gl.bufferSubData(type, offset, data) - return len -} + function lib$es6$promise$$internal$$tryCatch(callback, detail) { + try { + return callback(detail); + } catch(e) { + lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e; + return lib$es6$promise$$internal$$TRY_CATCH_ERROR; + } + } -function makeScratchTypeArray(array, dtype) { - var res = pool.malloc(array.length, dtype) - var n = array.length - for(var i=0; i=0; --i) { - if(stride[i] !== n) { - return false - } - n *= shape[i] - } - return true -} + if (hasCallback) { + value = lib$es6$promise$$internal$$tryCatch(callback, detail); + + if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) { + failed = true; + error = value.error; + value = null; + } else { + succeeded = true; + } + + if (promise === value) { + lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn()); + return; + } -proto.update = function(array, offset) { - if(typeof offset !== "number") { - offset = -1 - } - this.bind() - if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray - var dtype = array.dtype - if(SUPPORTED_TYPES.indexOf(dtype) < 0) { - dtype = "float32" - } - if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { - var ext = gl.getExtension('OES_element_index_uint') - if(ext && dtype !== "uint16") { - dtype = "uint32" } else { - dtype = "uint16" + value = detail; + succeeded = true; + } + + if (promise._state !== lib$es6$promise$$internal$$PENDING) { + // noop + } else if (hasCallback && succeeded) { + lib$es6$promise$$internal$$resolve(promise, value); + } else if (failed) { + lib$es6$promise$$internal$$reject(promise, error); + } else if (settled === lib$es6$promise$$internal$$FULFILLED) { + lib$es6$promise$$internal$$fulfill(promise, value); + } else if (settled === lib$es6$promise$$internal$$REJECTED) { + lib$es6$promise$$internal$$reject(promise, value); } } - if(dtype === array.dtype && isPacked(array.shape, array.stride)) { - if(array.offset === 0 && array.data.length === array.shape[0]) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset) - } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset) + + function lib$es6$promise$$internal$$initializePromise(promise, resolver) { + try { + resolver(function resolvePromise(value){ + lib$es6$promise$$internal$$resolve(promise, value); + }, function rejectPromise(reason) { + lib$es6$promise$$internal$$reject(promise, reason); + }); + } catch(e) { + lib$es6$promise$$internal$$reject(promise, e); } - } else { - var tmp = pool.malloc(array.size, dtype) - var ndt = ndarray(tmp, array.shape) - ops.assign(ndt, array) - if(offset < 0) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset) + } + + function lib$es6$promise$enumerator$$Enumerator(Constructor, input) { + var enumerator = this; + + enumerator._instanceConstructor = Constructor; + enumerator.promise = new Constructor(lib$es6$promise$$internal$$noop); + + if (enumerator._validateInput(input)) { + enumerator._input = input; + enumerator.length = input.length; + enumerator._remaining = input.length; + + enumerator._init(); + + if (enumerator.length === 0) { + lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); + } else { + enumerator.length = enumerator.length || 0; + enumerator._enumerate(); + if (enumerator._remaining === 0) { + lib$es6$promise$$internal$$fulfill(enumerator.promise, enumerator._result); + } + } } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset) + lib$es6$promise$$internal$$reject(enumerator.promise, enumerator._validationError()); } - pool.free(tmp) - } - } else if(Array.isArray(array)) { //Vanilla array - var t - if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { - t = makeScratchTypeArray(array, "uint16") - } else { - t = makeScratchTypeArray(array, "float32") - } - if(offset < 0) { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset) - } else { - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset) - } - pool.free(t) - } else if(typeof array === "object" && typeof array.length === "number") { //Typed array - this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset) - } else if(typeof array === "number" || array === undefined) { //Number/default - if(offset >= 0) { - throw new Error("gl-buffer: Cannot specify offset when resizing buffer") - } - array = array | 0 - if(array <= 0) { - array = 1 } - this.gl.bufferData(this.type, array|0, this.usage) - this.length = array - } else { //Error, case should not happen - throw new Error("gl-buffer: Invalid data type") - } -} - -function createBuffer(gl, data, type, usage) { - type = type || gl.ARRAY_BUFFER - usage = usage || gl.DYNAMIC_DRAW - if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) { - throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER") - } - if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) { - throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW") - } - var handle = gl.createBuffer() - var result = new GLBuffer(gl, type, handle, 0, usage) - result.update(data) - return result -} -module.exports = createBuffer + lib$es6$promise$enumerator$$Enumerator.prototype._validateInput = function(input) { + return lib$es6$promise$utils$$isArray(input); + }; -},{"ndarray":987,"ndarray-ops":982,"typedarray-pool":102}],76:[function(require,module,exports){ -'use strict' + lib$es6$promise$enumerator$$Enumerator.prototype._validationError = function() { + return new Error('Array Methods must be provided an Array'); + }; -var createUniformWrapper = require('./lib/create-uniforms') -var createAttributeWrapper = require('./lib/create-attributes') -var makeReflect = require('./lib/reflect') -var shaderCache = require('./lib/shader-cache') -var runtime = require('./lib/runtime-reflect') -var GLError = require("./lib/GLError") + lib$es6$promise$enumerator$$Enumerator.prototype._init = function() { + this._result = new Array(this.length); + }; -//Shader object -function Shader(gl) { - this.gl = gl + var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator; - //Default initialize these to null - this._vref = - this._fref = - this._relink = - this.vertShader = - this.fragShader = - this.program = - this.attributes = - this.uniforms = - this.types = null -} + lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() { + var enumerator = this; -var proto = Shader.prototype + var length = enumerator.length; + var promise = enumerator.promise; + var input = enumerator._input; -proto.bind = function() { - if(!this.program) { - this._relink() - } - this.gl.useProgram(this.program) -} + for (var i = 0; promise._state === lib$es6$promise$$internal$$PENDING && i < length; i++) { + enumerator._eachEntry(input[i], i); + } + }; -proto.dispose = function() { - if(this._fref) { - this._fref.dispose() - } - if(this._vref) { - this._vref.dispose() - } - this.attributes = - this.types = - this.vertShader = - this.fragShader = - this.program = - this._relink = - this._fref = - this._vref = null -} + lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) { + var enumerator = this; + var c = enumerator._instanceConstructor; -function compareAttributes(a, b) { - if(a.name < b.name) { - return -1 - } - return 1 -} + if (lib$es6$promise$utils$$isMaybeThenable(entry)) { + if (entry.constructor === c && entry._state !== lib$es6$promise$$internal$$PENDING) { + entry._onerror = null; + enumerator._settledAt(entry._state, i, entry._result); + } else { + enumerator._willSettleAt(c.resolve(entry), i); + } + } else { + enumerator._remaining--; + enumerator._result[i] = entry; + } + }; -//Update export hook for glslify-live -proto.update = function( - vertSource - , fragSource - , uniforms - , attributes) { + lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) { + var enumerator = this; + var promise = enumerator.promise; - //If only one object passed, assume glslify style output - if(!fragSource || arguments.length === 1) { - var obj = vertSource - vertSource = obj.vertex - fragSource = obj.fragment - uniforms = obj.uniforms - attributes = obj.attributes - } + if (promise._state === lib$es6$promise$$internal$$PENDING) { + enumerator._remaining--; - var wrapper = this - var gl = wrapper.gl + if (state === lib$es6$promise$$internal$$REJECTED) { + lib$es6$promise$$internal$$reject(promise, value); + } else { + enumerator._result[i] = value; + } + } - //Compile vertex and fragment shaders - var pvref = wrapper._vref - wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource) - if(pvref) { - pvref.dispose() - } - wrapper.vertShader = wrapper._vref.shader - var pfref = this._fref - wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource) - if(pfref) { - pfref.dispose() - } - wrapper.fragShader = wrapper._fref.shader + if (enumerator._remaining === 0) { + lib$es6$promise$$internal$$fulfill(promise, enumerator._result); + } + }; - //If uniforms/attributes is not specified, use RT reflection - if(!uniforms || !attributes) { + lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) { + var enumerator = this; - //Create initial test program - var testProgram = gl.createProgram() - gl.attachShader(testProgram, wrapper.fragShader) - gl.attachShader(testProgram, wrapper.vertShader) - gl.linkProgram(testProgram) - if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) { - var errLog = gl.getProgramInfoLog(testProgram) - throw new GLError(errLog, 'Error linking program:' + errLog) + lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) { + enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value); + }, function(reason) { + enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason); + }); + }; + function lib$es6$promise$promise$all$$all(entries) { + return new lib$es6$promise$enumerator$$default(this, entries).promise; } + var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all; + function lib$es6$promise$promise$race$$race(entries) { + /*jshint validthis:true */ + var Constructor = this; - //Load data from runtime - uniforms = uniforms || runtime.uniforms(gl, testProgram) - attributes = attributes || runtime.attributes(gl, testProgram) + var promise = new Constructor(lib$es6$promise$$internal$$noop); - //Release test program - gl.deleteProgram(testProgram) - } + if (!lib$es6$promise$utils$$isArray(entries)) { + lib$es6$promise$$internal$$reject(promise, new TypeError('You must pass an array to race.')); + return promise; + } - //Sort attributes lexicographically - // overrides undefined WebGL behavior for attribute locations - attributes = attributes.slice() - attributes.sort(compareAttributes) + var length = entries.length; - //Convert attribute types, read out locations - var attributeUnpacked = [] - var attributeNames = [] - var attributeLocations = [] - for(var i=0; i= 0) { - var size = attr.type.charAt(attr.type.length-1)|0 - var locVector = new Array(size) - for(var j=0; j= 0) { - curLocation += 1 + if (object && typeof object === 'object' && object.constructor === Constructor) { + return object; } - attributeLocations[i] = curLocation + + var promise = new Constructor(lib$es6$promise$$internal$$noop); + lib$es6$promise$$internal$$resolve(promise, object); + return promise; } - } + var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve; + function lib$es6$promise$promise$reject$$reject(reason) { + /*jshint validthis:true */ + var Constructor = this; + var promise = new Constructor(lib$es6$promise$$internal$$noop); + lib$es6$promise$$internal$$reject(promise, reason); + return promise; + } + var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject; - //Rebuild program and recompute all uniform locations - var uniformLocations = new Array(uniforms.length) - function relink() { - wrapper.program = shaderCache.program( - gl - , wrapper._vref - , wrapper._fref - , attributeNames - , attributeLocations) + var lib$es6$promise$promise$$counter = 0; - for(var i=0; i postsJSON + values[1] // => commentsJSON + + return values; + }); + ``` + + @class Promise + @param {function} resolver + Useful for tooling. + @constructor + */ + function lib$es6$promise$promise$$Promise(resolver) { + this._id = lib$es6$promise$promise$$counter++; + this._state = undefined; + this._result = undefined; + this._subscribers = []; + + if (lib$es6$promise$$internal$$noop !== resolver) { + if (!lib$es6$promise$utils$$isFunction(resolver)) { + lib$es6$promise$promise$$needsResolver(); + } + + if (!(this instanceof lib$es6$promise$promise$$Promise)) { + lib$es6$promise$promise$$needsNew(); + } + + lib$es6$promise$$internal$$initializePromise(this, resolver); + } + } + + lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default; + lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default; + lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default; + lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default; + lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler; + lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap; + lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap; + + lib$es6$promise$promise$$Promise.prototype = { + constructor: lib$es6$promise$promise$$Promise, + + /** + The primary way of interacting with a promise is through its `then` method, + which registers callbacks to receive either a promise's eventual value or the + reason why the promise cannot be fulfilled. + + ```js + findUser().then(function(user){ + // user is available + }, function(reason){ + // user is unavailable, and you are given the reason why + }); + ``` -var proto = ShaderAttribute.prototype + Chaining + -------- -proto.pointer = function setAttribPointer( - type - , normalized - , stride - , offset) { + The return value of `then` is itself a promise. This second, 'downstream' + promise is resolved with the return value of the first promise's fulfillment + or rejection handler, or rejected if the handler throws an exception. - var self = this - var gl = self._gl - var location = self._locations[self._index] + ```js + findUser().then(function (user) { + return user.name; + }, function (reason) { + return 'default name'; + }).then(function (userName) { + // If `findUser` fulfilled, `userName` will be the user's name, otherwise it + // will be `'default name'` + }); - gl.vertexAttribPointer( - location - , self._dimension - , type || gl.FLOAT - , !!normalized - , stride || 0 - , offset || 0) - gl.enableVertexAttribArray(location) -} + findUser().then(function (user) { + throw new Error('Found user, but still unhappy'); + }, function (reason) { + throw new Error('`findUser` rejected and we're unhappy'); + }).then(function (value) { + // never reached + }, function (reason) { + // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. + // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. + }); + ``` + If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. -proto.set = function(x0, x1, x2, x3) { - return this._constFunc(this._locations[this._index], x0, x1, x2, x3) -} + ```js + findUser().then(function (user) { + throw new PedagogicalException('Upstream error'); + }).then(function (value) { + // never reached + }).then(function (value) { + // never reached + }, function (reason) { + // The `PedgagocialException` is propagated all the way down to here + }); + ``` -Object.defineProperty(proto, 'location', { - get: function() { - return this._locations[this._index] - } - , set: function(v) { - if(v !== this._locations[this._index]) { - this._locations[this._index] = v|0 - this._wrapper.program = null - } - return v|0 - } -}) + Assimilation + ------------ -//Adds a vector attribute to obj -function addVectorAttribute( - gl - , wrapper - , index - , locations - , dimension - , obj - , name) { + Sometimes the value you want to propagate to a downstream promise can only be + retrieved asynchronously. This can be achieved by returning a promise in the + fulfillment or rejection handler. The downstream promise will then be pending + until the returned promise is settled. This is called *assimilation*. - //Construct constant function - var constFuncArgs = [ 'gl', 'v' ] - var varNames = [] - for(var i=0; i= 0) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) - } - addVectorAttribute( - gl - , wrapper - , locs[0] - , locations - , d - , obj - , name) - } else if(type.indexOf('mat') >= 0) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) - } - addMatrixAttribute( - gl - , wrapper - , locs - , locations - , d - , obj - , name) - } else { - throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type) - } - break - } - } - return obj -} + ```javascript + var author, books; -},{"./GLError":77}],79:[function(require,module,exports){ -'use strict' + try { + author = findAuthor(); + books = findBooksByAuthor(author); + // success + } catch(reason) { + // failure + } + ``` -var coallesceUniforms = require('./reflect') -var GLError = require("./GLError") + Errback Example -module.exports = createUniformWrapper + ```js -//Binds a function and returns a value -function identity(x) { - var c = new Function('y', 'return function(){return y}') - return c(x) -} + function foundBooks(books) { -function makeVector(length, fill) { - var result = new Array(length) - for(var i=0; i 4) { - throw new GLError('', 'Invalid data type') - } - switch(type.charAt(0)) { - case 'b': - case 'i': - return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')' - case 'v': - return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')' - default: - throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + type) - } - } else if(type.indexOf('mat') === 0 && type.length === 4) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) - } - return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')' + findAuthor(function(author, err){ + if (err) { + failure(err); + // failure } else { - throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + try { + findBoooksByAuthor(author, function(books, err) { + if (err) { + failure(err); + } else { + try { + foundBooks(books); + } catch(reason) { + failure(reason); + } + } + }); + } catch(error) { + failure(err); + } + // success } - break - } - } + }); + ``` - function enumerateIndices(prefix, type) { - if(typeof type !== 'object') { - return [ [prefix, type] ] - } - var indices = [] - for(var id in type) { - var prop = type[id] - var tprefix = prefix - if(parseInt(id) + '' === id) { - tprefix += '[' + id + ']' - } else { - tprefix += '.' + id - } - if(typeof prop === 'object') { - indices.push.apply(indices, enumerateIndices(tprefix, prop)) - } else { - indices.push([tprefix, prop]) - } - } - return indices - } + Promise Example; - function makeSetter(type) { - var code = [ 'return function updateProperty(obj){' ] - var indices = enumerateIndices('', type) - for(var i=0; i 4) { - throw new GLError('', 'Invalid data type') - } - if(type.charAt(0) === 'b') { - return makeVector(d, false) - } - return makeVector(d, 0) - } else if(type.indexOf('mat') === 0 && type.length === 4) { - var d = type.charCodeAt(type.length-1) - 48 - if(d < 2 || d > 4) { - throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) - } - return makeVector(d*d, 0) + @method then + @param {Function} onFulfilled + @param {Function} onRejected + Useful for tooling. + @return {Promise} + */ + then: function(onFulfillment, onRejection) { + var parent = this; + var state = parent._state; + + if (state === lib$es6$promise$$internal$$FULFILLED && !onFulfillment || state === lib$es6$promise$$internal$$REJECTED && !onRejection) { + return this; + } + + var child = new this.constructor(lib$es6$promise$$internal$$noop); + var result = parent._result; + + if (state) { + var callback = arguments[state - 1]; + lib$es6$promise$asap$$asap(function(){ + lib$es6$promise$$internal$$invokeCallback(state, child, callback, result); + }); } else { - throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection); } - break - } - } - function storeProperty(obj, prop, type) { - if(typeof type === 'object') { - var child = processObject(type) - Object.defineProperty(obj, prop, { - get: identity(child), - set: makeSetter(type), - enumerable: true, - configurable: false - }) - } else { - if(locations[type]) { - Object.defineProperty(obj, prop, { - get: makeGetter(type), - set: makeSetter(type), - enumerable: true, - configurable: false - }) - } else { - obj[prop] = defaultValue(uniforms[type].type) - } - } - } + return child; + }, - function processObject(obj) { - var result - if(Array.isArray(obj)) { - result = new Array(obj.length) - for(var i=0; i 1) { - if(!(x[0] in o)) { - o[x[0]] = [] - } - o = o[x[0]] - for(var k=1; k 1) { - for(var j=0; j + * but significantly simplified and sped up by ignoring number and string constructors + * ie these return false: + * new Number(1) + * new String('1') + */ + +'use strict'; + +/** + * Is this string all whitespace? + * This solution kind of makes my brain hurt, but it's significantly faster + * than !str.trim() or any other solution I could find. + * + * whitespace codes from: http://en.wikipedia.org/wiki/Whitespace_character + * and verified with: + * + * for(var i = 0; i < 65536; i++) { + * var s = String.fromCharCode(i); + * if(+s===0 && !s.trim()) console.log(i, s); + * } + * + * which counts a couple of these as *not* whitespace, but finds nothing else + * that *is* whitespace. Note that charCodeAt stops at 16 bits, but it appears + * that there are no whitespace characters above this, and code points above + * this do not map onto white space characters. + */ +function allBlankCharCodes(str){ + var l = str.length, + a; + for(var i = 0; i < l; i++) { + a = str.charCodeAt(i); + if((a < 9 || a > 13) && (a !== 32) && (a !== 133) && (a !== 160) && + (a !== 5760) && (a !== 6158) && (a < 8192 || a > 8205) && + (a !== 8232) && (a !== 8233) && (a !== 8239) && (a !== 8287) && + (a !== 8288) && (a !== 12288) && (a !== 65279)) { + return false; } - } else { - result.push({ - name: info.name, - type: type - }) - } } - } - return result + return true; } -function runtimeAttributes(gl, program) { - var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) - var result = [] - for(var i=0; i len) { + throw new Error("gl-buffer: If resizing buffer, must not specify offset") } - return program + gl.bufferSubData(type, offset, data) + return len } -proto.getProgram = function(vref, fref, attribs, locations) { - var token = [vref.id, fref.id, attribs.join(':'), locations.join(':')].join('@') - var prog = this.programs[token] - if(!prog || !this.gl.isProgram(prog)) { - this.programs[token] = prog = linkProgram( - this.gl, - vref.shader, - fref.shader, - attribs, - locations) - vref.programs.push(token) - fref.programs.push(token) +function makeScratchTypeArray(array, dtype) { + var res = pool.malloc(array.length, dtype) + var n = array.length + for(var i=0; i=0; --i) { + if(stride[i] !== n) { + return false + } + n *= shape[i] } - return ctxCache -} - -function getShaderReference(gl, type, src) { - return getCache(gl).getShaderReference(type, src) -} - -function createProgram(gl, vref, fref, attribs, locations) { - return getCache(gl).getProgram(vref, fref, attribs, locations) + return true } -},{"./GLError":77,"gl-format-compiler-error":83,"weakmap-shim":99}],83:[function(require,module,exports){ - -var sprintf = require('sprintf-js').sprintf; -var glConstants = require('gl-constants/lookup'); -var shaderName = require('glsl-shader-name'); -var addLineNumbers = require('add-line-numbers'); - -module.exports = formatCompilerError; - -function formatCompilerError(errLog, src, type) { - "use strict"; - - var name = shaderName(src) || 'of unknown name (see npm glsl-shader-name)'; - - var typeName = 'unknown type'; - if (type !== undefined) { - typeName = type === glConstants.FRAGMENT_SHADER ? 'fragment' : 'vertex' +proto.update = function(array, offset) { + if(typeof offset !== "number") { + offset = -1 + } + this.bind() + if(typeof array === "object" && typeof array.shape !== "undefined") { //ndarray + var dtype = array.dtype + if(SUPPORTED_TYPES.indexOf(dtype) < 0) { + dtype = "float32" + } + if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { + var ext = gl.getExtension('OES_element_index_uint') + if(ext && dtype !== "uint16") { + dtype = "uint32" + } else { + dtype = "uint16" + } + } + if(dtype === array.dtype && isPacked(array.shape, array.stride)) { + if(array.offset === 0 && array.data.length === array.shape[0]) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array.data.subarray(array.offset, array.shape[0]), offset) + } + } else { + var tmp = pool.malloc(array.size, dtype) + var ndt = ndarray(tmp, array.shape) + ops.assign(ndt, array) + if(offset < 0) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, tmp.subarray(0, array.size), offset) + } + pool.free(tmp) + } + } else if(Array.isArray(array)) { //Vanilla array + var t + if(this.type === this.gl.ELEMENT_ARRAY_BUFFER) { + t = makeScratchTypeArray(array, "uint16") + } else { + t = makeScratchTypeArray(array, "float32") + } + if(offset < 0) { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t, offset) + } else { + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, t.subarray(0, array.length), offset) + } + pool.free(t) + } else if(typeof array === "object" && typeof array.length === "number") { //Typed array + this.length = updateTypeArray(this.gl, this.type, this.length, this.usage, array, offset) + } else if(typeof array === "number" || array === undefined) { //Number/default + if(offset >= 0) { + throw new Error("gl-buffer: Cannot specify offset when resizing buffer") + } + array = array | 0 + if(array <= 0) { + array = 1 } + this.gl.bufferData(this.type, array|0, this.usage) + this.length = array + } else { //Error, case should not happen + throw new Error("gl-buffer: Invalid data type") + } +} - var longForm = sprintf('Error compiling %s shader %s:\n', typeName, name); - var shortForm = sprintf("%s%s", longForm, errLog); +function createBuffer(gl, data, type, usage) { + type = type || gl.ARRAY_BUFFER + usage = usage || gl.DYNAMIC_DRAW + if(type !== gl.ARRAY_BUFFER && type !== gl.ELEMENT_ARRAY_BUFFER) { + throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER") + } + if(usage !== gl.DYNAMIC_DRAW && usage !== gl.STATIC_DRAW && usage !== gl.STREAM_DRAW) { + throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW") + } + var handle = gl.createBuffer() + var result = new GLBuffer(gl, type, handle, 0, usage) + result.update(data) + return result +} - var errorStrings = errLog.split('\n'); - var errors = {}; +module.exports = createBuffer - for (var i = 0; i < errorStrings.length; i++) { - var errorString = errorStrings[i]; - if (errorString === '') continue; - var lineNo = parseInt(errorString.split(':')[2]); - if (isNaN(lineNo)) { - throw new Error(sprintf('Could not parse error: %s', errorString)); - } - errors[lineNo] = errorString; - } +},{"ndarray":208,"ndarray-ops":207,"typedarray-pool":233}],76:[function(require,module,exports){ +'use strict' - var lines = addLineNumbers(src).split('\n'); +var createShader = require('gl-shader') +var createBuffer = require('gl-buffer') +var pool = require('typedarray-pool') +var shaders = require('./lib/shaders') - for (var i = 0; i < lines.length; i++) { - if (!errors[i+3] && !errors[i+2] && !errors[i+1]) continue; - var line = lines[i]; - longForm += line + '\n'; - if (errors[i+1]) { - var e = errors[i+1]; - e = e.substr(e.split(':', 3).join(':').length + 1).trim(); - longForm += sprintf('^^^ %s\n\n', e); - } - } +module.exports = createError2D - return { - long: longForm.trim(), - short: shortForm.trim() - }; -} +var WEIGHTS = [ + //x-error bar + [ 1, 0, 0, 1, 0, 0], + [ 1, 0, 0,-1, 0, 0], + [-1, 0, 0,-1, 0, 0], + [-1, 0, 0,-1, 0, 0], + [-1, 0, 0, 1, 0, 0], + [ 1, 0, 0, 1, 0, 0], -},{"add-line-numbers":84,"gl-constants/lookup":88,"glsl-shader-name":89,"sprintf-js":96}],84:[function(require,module,exports){ -var padLeft = require('pad-left') + //x-error right cap + [ 1, 0, -1, 0, 0, 1], + [ 1, 0, -1, 0, 0,-1], + [ 1, 0, 1, 0, 0,-1], -module.exports = addLineNumbers -function addLineNumbers (string, start, delim) { - start = typeof start === 'number' ? start : 1 - delim = delim || ': ' + [ 1, 0, 1, 0, 0,-1], + [ 1, 0, 1, 0, 0, 1], + [ 1, 0, -1, 0, 0, 1], - var lines = string.split(/\r?\n/) - var totalDigits = String(lines.length + start - 1).length - return lines.map(function (line, i) { - var c = i + start - var digits = String(c).length - var prefix = padLeft(c, totalDigits - digits) - return prefix + delim + line - }).join('\n') -} + //x-error left cap + [-1, 0, -1, 0, 0, 1], + [-1, 0, -1, 0, 0,-1], + [-1, 0, 1, 0, 0,-1], -},{"pad-left":85}],85:[function(require,module,exports){ -/*! - * pad-left - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT license. - */ + [-1, 0, 1, 0, 0,-1], + [-1, 0, 1, 0, 0, 1], + [-1, 0, -1, 0, 0, 1], -'use strict'; + //y-error bar + [0, 1, 1, 0, 0, 0], + [0, 1,-1, 0, 0, 0], + [0,-1,-1, 0, 0, 0], -var repeat = require('repeat-string'); + [0,-1,-1, 0, 0, 0], + [0, 1, 1, 0, 0, 0], + [0,-1, 1, 0, 0, 0], -module.exports = function padLeft(str, num, ch) { - ch = typeof ch !== 'undefined' ? (ch + '') : ' '; - return repeat(ch, num) + str; -}; -},{"repeat-string":86}],86:[function(require,module,exports){ -/*! - * repeat-string - * - * Copyright (c) 2014-2015, Jon Schlinkert. - * Licensed under the MIT License. - */ + //y-error top cap + [ 0, 1, 0,-1, 1, 0], + [ 0, 1, 0,-1,-1, 0], + [ 0, 1, 0, 1,-1, 0], -'use strict'; + [ 0, 1, 0, 1, 1, 0], + [ 0, 1, 0,-1, 1, 0], + [ 0, 1, 0, 1,-1, 0], -/** - * Expose `repeat` - */ + //y-error bottom cap + [ 0,-1, 0,-1, 1, 0], + [ 0,-1, 0,-1,-1, 0], + [ 0,-1, 0, 1,-1, 0], -module.exports = repeat; + [ 0,-1, 0, 1, 1, 0], + [ 0,-1, 0,-1, 1, 0], + [ 0,-1, 0, 1,-1, 0] +] -/** - * Repeat the given `string` the specified `number` - * of times. - * - * **Example:** - * - * ```js - * var repeat = require('repeat-string'); - * repeat('A', 5); - * //=> AAAAA - * ``` - * - * @param {String} `string` The string to repeat - * @param {Number} `number` The number of times to repeat the string - * @return {String} Repeated string - * @api public - */ +function GLError2D(plot, shader, buffer) { + this.plot = plot -function repeat(str, num) { - if (typeof str !== 'string') { - throw new TypeError('repeat-string expects a string.'); - } + this.shader = shader + this.buffer = buffer - if (num === 1) return str; - if (num === 2) return str + str; + this.bounds = [Infinity, Infinity, -Infinity, -Infinity] - var max = str.length * num; - if (cache !== str || typeof cache === 'undefined') { - cache = str; - res = ''; - } + this.numPoints = 0 - while (max > res.length && num > 0) { - if (num & 1) { - res += str; - } + this.color = [0,0,0,1] +} - num >>= 1; - if (!num) break; - str += str; - } +var proto = GLError2D.prototype - return res.substr(0, max); -} +proto.draw = (function() { -/** - * Results cache - */ + var MATRIX = [ + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + ] -var res = ''; -var cache; + var PIXEL_SCALE = [1,1] -},{}],87:[function(require,module,exports){ -module.exports = { - 0: 'NONE', - 1: 'ONE', - 2: 'LINE_LOOP', - 3: 'LINE_STRIP', - 4: 'TRIANGLES', - 5: 'TRIANGLE_STRIP', - 6: 'TRIANGLE_FAN', - 256: 'DEPTH_BUFFER_BIT', - 512: 'NEVER', - 513: 'LESS', - 514: 'EQUAL', - 515: 'LEQUAL', - 516: 'GREATER', - 517: 'NOTEQUAL', - 518: 'GEQUAL', - 519: 'ALWAYS', - 768: 'SRC_COLOR', - 769: 'ONE_MINUS_SRC_COLOR', - 770: 'SRC_ALPHA', - 771: 'ONE_MINUS_SRC_ALPHA', - 772: 'DST_ALPHA', - 773: 'ONE_MINUS_DST_ALPHA', - 774: 'DST_COLOR', - 775: 'ONE_MINUS_DST_COLOR', - 776: 'SRC_ALPHA_SATURATE', - 1024: 'STENCIL_BUFFER_BIT', - 1028: 'FRONT', - 1029: 'BACK', - 1032: 'FRONT_AND_BACK', - 1280: 'INVALID_ENUM', - 1281: 'INVALID_VALUE', - 1282: 'INVALID_OPERATION', - 1285: 'OUT_OF_MEMORY', - 1286: 'INVALID_FRAMEBUFFER_OPERATION', - 2304: 'CW', - 2305: 'CCW', - 2849: 'LINE_WIDTH', - 2884: 'CULL_FACE', - 2885: 'CULL_FACE_MODE', - 2886: 'FRONT_FACE', - 2928: 'DEPTH_RANGE', - 2929: 'DEPTH_TEST', - 2930: 'DEPTH_WRITEMASK', - 2931: 'DEPTH_CLEAR_VALUE', - 2932: 'DEPTH_FUNC', - 2960: 'STENCIL_TEST', - 2961: 'STENCIL_CLEAR_VALUE', - 2962: 'STENCIL_FUNC', - 2963: 'STENCIL_VALUE_MASK', - 2964: 'STENCIL_FAIL', - 2965: 'STENCIL_PASS_DEPTH_FAIL', - 2966: 'STENCIL_PASS_DEPTH_PASS', - 2967: 'STENCIL_REF', - 2968: 'STENCIL_WRITEMASK', - 2978: 'VIEWPORT', - 3024: 'DITHER', - 3042: 'BLEND', - 3088: 'SCISSOR_BOX', - 3089: 'SCISSOR_TEST', - 3106: 'COLOR_CLEAR_VALUE', - 3107: 'COLOR_WRITEMASK', - 3317: 'UNPACK_ALIGNMENT', - 3333: 'PACK_ALIGNMENT', - 3379: 'MAX_TEXTURE_SIZE', - 3386: 'MAX_VIEWPORT_DIMS', - 3408: 'SUBPIXEL_BITS', - 3410: 'RED_BITS', - 3411: 'GREEN_BITS', - 3412: 'BLUE_BITS', - 3413: 'ALPHA_BITS', - 3414: 'DEPTH_BITS', - 3415: 'STENCIL_BITS', - 3553: 'TEXTURE_2D', - 4352: 'DONT_CARE', - 4353: 'FASTEST', - 4354: 'NICEST', - 5120: 'BYTE', - 5121: 'UNSIGNED_BYTE', - 5122: 'SHORT', - 5123: 'UNSIGNED_SHORT', - 5124: 'INT', - 5125: 'UNSIGNED_INT', - 5126: 'FLOAT', - 5386: 'INVERT', - 5890: 'TEXTURE', - 6401: 'STENCIL_INDEX', - 6402: 'DEPTH_COMPONENT', - 6406: 'ALPHA', - 6407: 'RGB', - 6408: 'RGBA', - 6409: 'LUMINANCE', - 6410: 'LUMINANCE_ALPHA', - 7680: 'KEEP', - 7681: 'REPLACE', - 7682: 'INCR', - 7683: 'DECR', - 7936: 'VENDOR', - 7937: 'RENDERER', - 7938: 'VERSION', - 9728: 'NEAREST', - 9729: 'LINEAR', - 9984: 'NEAREST_MIPMAP_NEAREST', - 9985: 'LINEAR_MIPMAP_NEAREST', - 9986: 'NEAREST_MIPMAP_LINEAR', - 9987: 'LINEAR_MIPMAP_LINEAR', - 10240: 'TEXTURE_MAG_FILTER', - 10241: 'TEXTURE_MIN_FILTER', - 10242: 'TEXTURE_WRAP_S', - 10243: 'TEXTURE_WRAP_T', - 10497: 'REPEAT', - 10752: 'POLYGON_OFFSET_UNITS', - 16384: 'COLOR_BUFFER_BIT', - 32769: 'CONSTANT_COLOR', - 32770: 'ONE_MINUS_CONSTANT_COLOR', - 32771: 'CONSTANT_ALPHA', - 32772: 'ONE_MINUS_CONSTANT_ALPHA', - 32773: 'BLEND_COLOR', - 32774: 'FUNC_ADD', - 32777: 'BLEND_EQUATION_RGB', - 32778: 'FUNC_SUBTRACT', - 32779: 'FUNC_REVERSE_SUBTRACT', - 32819: 'UNSIGNED_SHORT_4_4_4_4', - 32820: 'UNSIGNED_SHORT_5_5_5_1', - 32823: 'POLYGON_OFFSET_FILL', - 32824: 'POLYGON_OFFSET_FACTOR', - 32854: 'RGBA4', - 32855: 'RGB5_A1', - 32873: 'TEXTURE_BINDING_2D', - 32926: 'SAMPLE_ALPHA_TO_COVERAGE', - 32928: 'SAMPLE_COVERAGE', - 32936: 'SAMPLE_BUFFERS', - 32937: 'SAMPLES', - 32938: 'SAMPLE_COVERAGE_VALUE', - 32939: 'SAMPLE_COVERAGE_INVERT', - 32968: 'BLEND_DST_RGB', - 32969: 'BLEND_SRC_RGB', - 32970: 'BLEND_DST_ALPHA', - 32971: 'BLEND_SRC_ALPHA', - 33071: 'CLAMP_TO_EDGE', - 33170: 'GENERATE_MIPMAP_HINT', - 33189: 'DEPTH_COMPONENT16', - 33306: 'DEPTH_STENCIL_ATTACHMENT', - 33635: 'UNSIGNED_SHORT_5_6_5', - 33648: 'MIRRORED_REPEAT', - 33901: 'ALIASED_POINT_SIZE_RANGE', - 33902: 'ALIASED_LINE_WIDTH_RANGE', - 33984: 'TEXTURE0', - 33985: 'TEXTURE1', - 33986: 'TEXTURE2', - 33987: 'TEXTURE3', - 33988: 'TEXTURE4', - 33989: 'TEXTURE5', - 33990: 'TEXTURE6', - 33991: 'TEXTURE7', - 33992: 'TEXTURE8', - 33993: 'TEXTURE9', - 33994: 'TEXTURE10', - 33995: 'TEXTURE11', - 33996: 'TEXTURE12', - 33997: 'TEXTURE13', - 33998: 'TEXTURE14', - 33999: 'TEXTURE15', - 34000: 'TEXTURE16', - 34001: 'TEXTURE17', - 34002: 'TEXTURE18', - 34003: 'TEXTURE19', - 34004: 'TEXTURE20', - 34005: 'TEXTURE21', - 34006: 'TEXTURE22', - 34007: 'TEXTURE23', - 34008: 'TEXTURE24', - 34009: 'TEXTURE25', - 34010: 'TEXTURE26', - 34011: 'TEXTURE27', - 34012: 'TEXTURE28', - 34013: 'TEXTURE29', - 34014: 'TEXTURE30', - 34015: 'TEXTURE31', - 34016: 'ACTIVE_TEXTURE', - 34024: 'MAX_RENDERBUFFER_SIZE', - 34041: 'DEPTH_STENCIL', - 34055: 'INCR_WRAP', - 34056: 'DECR_WRAP', - 34067: 'TEXTURE_CUBE_MAP', - 34068: 'TEXTURE_BINDING_CUBE_MAP', - 34069: 'TEXTURE_CUBE_MAP_POSITIVE_X', - 34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X', - 34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y', - 34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y', - 34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z', - 34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z', - 34076: 'MAX_CUBE_MAP_TEXTURE_SIZE', - 34338: 'VERTEX_ATTRIB_ARRAY_ENABLED', - 34339: 'VERTEX_ATTRIB_ARRAY_SIZE', - 34340: 'VERTEX_ATTRIB_ARRAY_STRIDE', - 34341: 'VERTEX_ATTRIB_ARRAY_TYPE', - 34342: 'CURRENT_VERTEX_ATTRIB', - 34373: 'VERTEX_ATTRIB_ARRAY_POINTER', - 34466: 'NUM_COMPRESSED_TEXTURE_FORMATS', - 34467: 'COMPRESSED_TEXTURE_FORMATS', - 34660: 'BUFFER_SIZE', - 34661: 'BUFFER_USAGE', - 34816: 'STENCIL_BACK_FUNC', - 34817: 'STENCIL_BACK_FAIL', - 34818: 'STENCIL_BACK_PASS_DEPTH_FAIL', - 34819: 'STENCIL_BACK_PASS_DEPTH_PASS', - 34877: 'BLEND_EQUATION_ALPHA', - 34921: 'MAX_VERTEX_ATTRIBS', - 34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED', - 34930: 'MAX_TEXTURE_IMAGE_UNITS', - 34962: 'ARRAY_BUFFER', - 34963: 'ELEMENT_ARRAY_BUFFER', - 34964: 'ARRAY_BUFFER_BINDING', - 34965: 'ELEMENT_ARRAY_BUFFER_BINDING', - 34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING', - 35040: 'STREAM_DRAW', - 35044: 'STATIC_DRAW', - 35048: 'DYNAMIC_DRAW', - 35632: 'FRAGMENT_SHADER', - 35633: 'VERTEX_SHADER', - 35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS', - 35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', - 35663: 'SHADER_TYPE', - 35664: 'FLOAT_VEC2', - 35665: 'FLOAT_VEC3', - 35666: 'FLOAT_VEC4', - 35667: 'INT_VEC2', - 35668: 'INT_VEC3', - 35669: 'INT_VEC4', - 35670: 'BOOL', - 35671: 'BOOL_VEC2', - 35672: 'BOOL_VEC3', - 35673: 'BOOL_VEC4', - 35674: 'FLOAT_MAT2', - 35675: 'FLOAT_MAT3', - 35676: 'FLOAT_MAT4', - 35678: 'SAMPLER_2D', - 35680: 'SAMPLER_CUBE', - 35712: 'DELETE_STATUS', - 35713: 'COMPILE_STATUS', - 35714: 'LINK_STATUS', - 35715: 'VALIDATE_STATUS', - 35716: 'INFO_LOG_LENGTH', - 35717: 'ATTACHED_SHADERS', - 35718: 'ACTIVE_UNIFORMS', - 35719: 'ACTIVE_UNIFORM_MAX_LENGTH', - 35720: 'SHADER_SOURCE_LENGTH', - 35721: 'ACTIVE_ATTRIBUTES', - 35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH', - 35724: 'SHADING_LANGUAGE_VERSION', - 35725: 'CURRENT_PROGRAM', - 36003: 'STENCIL_BACK_REF', - 36004: 'STENCIL_BACK_VALUE_MASK', - 36005: 'STENCIL_BACK_WRITEMASK', - 36006: 'FRAMEBUFFER_BINDING', - 36007: 'RENDERBUFFER_BINDING', - 36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', - 36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', - 36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', - 36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE', - 36053: 'FRAMEBUFFER_COMPLETE', - 36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT', - 36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT', - 36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS', - 36061: 'FRAMEBUFFER_UNSUPPORTED', - 36064: 'COLOR_ATTACHMENT0', - 36096: 'DEPTH_ATTACHMENT', - 36128: 'STENCIL_ATTACHMENT', - 36160: 'FRAMEBUFFER', - 36161: 'RENDERBUFFER', - 36162: 'RENDERBUFFER_WIDTH', - 36163: 'RENDERBUFFER_HEIGHT', - 36164: 'RENDERBUFFER_INTERNAL_FORMAT', - 36168: 'STENCIL_INDEX8', - 36176: 'RENDERBUFFER_RED_SIZE', - 36177: 'RENDERBUFFER_GREEN_SIZE', - 36178: 'RENDERBUFFER_BLUE_SIZE', - 36179: 'RENDERBUFFER_ALPHA_SIZE', - 36180: 'RENDERBUFFER_DEPTH_SIZE', - 36181: 'RENDERBUFFER_STENCIL_SIZE', - 36194: 'RGB565', - 36336: 'LOW_FLOAT', - 36337: 'MEDIUM_FLOAT', - 36338: 'HIGH_FLOAT', - 36339: 'LOW_INT', - 36340: 'MEDIUM_INT', - 36341: 'HIGH_INT', - 36346: 'SHADER_COMPILER', - 36347: 'MAX_VERTEX_UNIFORM_VECTORS', - 36348: 'MAX_VARYING_VECTORS', - 36349: 'MAX_FRAGMENT_UNIFORM_VECTORS', - 37440: 'UNPACK_FLIP_Y_WEBGL', - 37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL', - 37442: 'CONTEXT_LOST_WEBGL', - 37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL', - 37444: 'BROWSER_DEFAULT_WEBGL' -} + return function() { + var plot = this.plot + var shader = this.shader + var buffer = this.buffer + var bounds = this.bounds + var numPoints = this.numPoints + var color = this.color + + var gl = plot.gl + var dataBox = plot.dataBox + var viewBox = plot.viewBox + var pixelRatio = plot.pixelRatio -},{}],88:[function(require,module,exports){ -var gl10 = require('./1.0/numbers') + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] -module.exports = function lookupConstant (number) { - return gl10[number] -} + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 -},{"./1.0/numbers":87}],89:[function(require,module,exports){ -var tokenize = require('glsl-tokenizer') -var atob = require('atob-lite') + var screenX = viewBox[2] - viewBox[0] + var screenY = viewBox[3] - viewBox[1] -module.exports = getName + PIXEL_SCALE[0] = 2.0 * pixelRatio / screenX + PIXEL_SCALE[1] = 2.0 * pixelRatio / screenY -function getName(src) { - var tokens = Array.isArray(src) - ? src - : tokenize(src) + buffer.bind() + shader.bind() - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i] - if (token.type !== 'preprocessor') continue - var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/) - if (!match) continue - if (!match[2]) continue + shader.uniforms.viewTransform = MATRIX + shader.uniforms.pixelScale = PIXEL_SCALE + shader.uniforms.color = this.color - var b64 = match[1] - var name = match[2] + shader.attributes.position.pointer( + gl.FLOAT, + false, + 16, + 0) - return (b64 ? atob(name) : name).trim() + shader.attributes.pixelOffset.pointer( + gl.FLOAT, + false, + 16, + 8) + + gl.drawArrays(gl.TRIANGLES, 0, numPoints * WEIGHTS.length) } -} +})() -},{"atob-lite":90,"glsl-tokenizer":95}],90:[function(require,module,exports){ -module.exports = function _atob(str) { - return atob(str) +proto.drawPick = function(offset) { return offset } +proto.pick = function(x, y) { + return null } -},{}],91:[function(require,module,exports){ -module.exports = tokenize +proto.update = function(options) { + options = options || {} -var literals = require('./lib/literals') - , operators = require('./lib/operators') - , builtins = require('./lib/builtins') + var positions = options.positions || [] + var errors = options.errors || [] -var NORMAL = 999 // <-- never emitted - , TOKEN = 9999 // <-- never emitted - , BLOCK_COMMENT = 0 - , LINE_COMMENT = 1 - , PREPROCESSOR = 2 - , OPERATOR = 3 - , INTEGER = 4 - , FLOAT = 5 - , IDENT = 6 - , BUILTIN = 7 - , KEYWORD = 8 - , WHITESPACE = 9 - , EOF = 10 - , HEX = 11 + var lineWidth = 1 + if('lineWidth' in options) { + lineWidth = +options.lineWidth + } -var map = [ - 'block-comment' - , 'line-comment' - , 'preprocessor' - , 'operator' - , 'integer' - , 'float' - , 'ident' - , 'builtin' - , 'keyword' - , 'whitespace' - , 'eof' - , 'integer' -] + var capSize = 5 + if('capSize' in options) { + capSize = +options.capSize + } -function tokenize() { - var i = 0 - , total = 0 - , mode = NORMAL - , c - , last - , content = [] - , tokens = [] - , token_idx = 0 - , token_offs = 0 - , line = 1 - , col = 0 - , start = 0 - , isnum = false - , isoperator = false - , input = '' - , len + this.color = (options.color || [0,0,0,1]).slice() - return function(data) { - tokens = [] - if (data !== null) return write(data) - return end() - } + var bounds = this.bounds = [Infinity, Infinity, -Infinity, -Infinity] - function token(data) { - if (data.length) { - tokens.push({ - type: map[mode] - , data: data - , position: start - , line: line - , column: col - }) - } + var numPoints = this.numPoints = positions.length>>1 + for(var i=0; i 0) { + dx *= ex1 } - if(last !== i) { - switch(input[last]) { - case '\n': col = 0; ++line; break - default: ++col; break - } + if(dy < 0) { + dy *= ey0 + } else if(dy > 0) { + dy *= ey1 } - } - total += i - input = input.slice(i) - return tokens + bufferData[ptr++] = sx * ((x - tx) + dx) + bufferData[ptr++] = sy * ((y - ty) + dy) + bufferData[ptr++] = lineWidth * w[2] + (capSize + lineWidth) * w[4] + bufferData[ptr++] = lineWidth * w[3] + (capSize + lineWidth) * w[5] + } } + this.buffer.update(bufferData) + pool.free(bufferData) +} - function end(chunk) { - if(content.length) { - token(content.join('')) - } +proto.dispose = function() { + this.plot.removeObject(this) + this.shader.dispose() + this.buffer.dispose() +} - mode = EOF - token('(eof)') - return tokens - } +function createError2D(plot, options) { + var shader = createShader(plot.gl, shaders.vertex, shaders.fragment) + var buffer = createBuffer(plot.gl) - function normal() { - content = content.length ? [] : content + var errorbars = new GLError2D(plot, shader, buffer) - if(last === '/' && c === '*') { - start = total + i - 1 - mode = BLOCK_COMMENT - last = c - return i + 1 - } + errorbars.update(options) - if(last === '/' && c === '/') { - start = total + i - 1 - mode = LINE_COMMENT - last = c - return i + 1 - } + plot.addObject(errorbars) - if(c === '#') { - mode = PREPROCESSOR - start = total + i - return i - } + return errorbars +} - if(/\s/.test(c)) { - mode = WHITESPACE - start = total + i - return i - } +},{"./lib/shaders":77,"gl-buffer":75,"gl-shader":154,"typedarray-pool":233}],77:[function(require,module,exports){ - isnum = /\d/.test(c) - isoperator = /[^\w_]/.test(c) - start = total + i - mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN - return i +module.exports = { + vertex: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 position;\nattribute vec2 pixelOffset;\n\nuniform mat3 viewTransform;\nuniform vec2 pixelScale;\n\nvoid main() {\n vec3 scrPosition = viewTransform * vec3(position, 1);\n gl_Position = vec4(\n scrPosition.xy + scrPosition.z * pixelScale * pixelOffset,\n 0,\n scrPosition.z);\n}\n", + fragment: "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n gl_FragColor = vec4(color.rgb * color.a, color.a);\n}\n" +} + +},{}],78:[function(require,module,exports){ +'use strict' + +module.exports = createErrorBars + +var createBuffer = require('gl-buffer') +var createVAO = require('gl-vao') +var createShader = require('./shaders/index') + +var IDENTITY = [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +function ErrorBars(gl, buffer, vao, shader) { + this.gl = gl + this.shader = shader + this.buffer = buffer + this.vao = vao + this.pixelRatio = 1 + this.bounds = [[ Infinity, Infinity, Infinity], [-Infinity,-Infinity,-Infinity]] + this.clipBounds = [[-Infinity,-Infinity,-Infinity], [ Infinity, Infinity, Infinity]] + this.lineWidth = [1,1,1] + this.capSize = [10,10,10] + this.lineCount = [0,0,0] + this.lineOffset = [0,0,0] + this.opacity = 1 +} + +var proto = ErrorBars.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 +} + +proto.isTransparent = function() { + return this.opacity < 1 +} + +proto.drawTransparent = proto.draw = function(cameraParams) { + var gl = this.gl + var uniforms = this.shader.uniforms + + this.shader.bind() + var view = uniforms.view = cameraParams.view || IDENTITY + var projection = uniforms.projection = cameraParams.projection || IDENTITY + uniforms.model = cameraParams.model || IDENTITY + uniforms.clipBounds = this.clipBounds + uniforms.opacity = this.opacity + + + var cx = view[12] + var cy = view[13] + var cz = view[14] + var cw = view[15] + var pixelScaleF = this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight + + + this.vao.bind() + for(var i=0; i<3; ++i) { + gl.lineWidth(this.lineWidth[i]) + uniforms.capSize = this.capSize[i] * pixelScaleF + gl.drawArrays(gl.LINES, this.lineOffset[i], this.lineCount[i]) } + this.vao.unbind() +} - function whitespace() { - if(/[^\s]/g.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } - content.push(c) - last = c - return i + 1 +function updateBounds(bounds, point) { + for(var i=0; i<3; ++i) { + bounds[0][i] = Math.min(bounds[0][i], point[i]) + bounds[1][i] = Math.max(bounds[1][i], point[i]) } +} - function preprocessor() { - if(c === '\n' && last !== '\\') { - token(content.join('')) - mode = NORMAL - return i +var FACE_TABLE = (function(){ + var table = new Array(3) + for(var d=0; d<3; ++d) { + var row = [] + for(var j=1; j<=2; ++j) { + for(var s=-1; s<=1; s+=2) { + var u = (j+d) % 3 + var y = [0,0,0] + y[u] = s + row.push(y) + } } - content.push(c) - last = c - return i + 1 + table[d] = row } + return table +})() - function line_comment() { - return preprocessor() + +function emitFace(verts, x, c, d) { + var offsets = FACE_TABLE[d] + for(var i=0; i 0) { + var x = p.slice() + x[j] += e[1][j] + verts.push(p[0], p[1], p[2], + c[0], c[1], c[2], c[3], + 0, 0, 0, + x[0], x[1], x[2], + c[0], c[1], c[2], c[3], + 0, 0, 0) + updateBounds(this.bounds, x) + vertexCount += 2 + emitFace(verts, x, c, j) + } + } + this.lineCount[j] = vertexCount - this.lineOffset[j] } + this.buffer.update(verts) + } +} - if(c === '.' && content.length) { - while(determine_operator(content)); +proto.dispose = function() { + this.shader.dispose() + this.buffer.dispose() + this.vao.dispose() +} + +function createErrorBars(options) { + var gl = options.gl + var buffer = createBuffer(gl) + var vao = createVAO(gl, [ + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 0, + stride: 40 + }, + { + buffer: buffer, + type: gl.FLOAT, + size: 4, + offset: 12, + stride: 40 + }, + { + buffer: buffer, + type: gl.FLOAT, + size: 3, + offset: 28, + stride: 40 + } + ]) - mode = FLOAT - return i - } + var shader = createShader(gl) + shader.attributes.position.location = 0 + shader.attributes.color.location = 1 + shader.attributes.offset.location = 2 - if(c === ';' || c === ')' || c === '(') { - if(content.length) while(determine_operator(content)); - token(c) - mode = NORMAL - return i + 1 - } + var result = new ErrorBars(gl, buffer, vao, shader) + result.update(options) + return result +} - var is_composite_operator = content.length === 2 && c !== '=' - if(/[\w_\d\s]/.test(c) || is_composite_operator) { - while(determine_operator(content)); - mode = NORMAL - return i - } +},{"./shaders/index":79,"gl-buffer":75,"gl-vao":189}],79:[function(require,module,exports){ +'use strict' - content.push(c) - last = c - return i + 1 - } - function determine_operator(buf) { - var j = 0 - , idx - , res +var createShader = require('gl-shader') - do { - idx = operators.indexOf(buf.slice(0, buf.length + j).join('')) - res = operators[idx] +var vertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}" +var fragSrc = "#define GLSLIFY 1\nprecision mediump float;\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if(any(lessThan(fragPosition, clipBounds[0])) || any(greaterThan(fragPosition, clipBounds[1]))) {\n discard;\n }\n gl_FragColor = opacity * fragColor;\n}" - if(idx === -1) { - if(j-- + buf.length > 0) continue - res = buf.slice(0, 1).join('') - } +module.exports = function(gl) { + return createShader(gl, vertSrc, fragSrc, null, [ + {name: 'position', type: 'vec3'}, + {name: 'offset', type: 'vec3'}, + {name: 'color', type: 'vec4'} + ]) +} - token(res) +},{"gl-shader":154}],80:[function(require,module,exports){ +'use strict' - start += res.length - content = content.slice(res.length) - return content.length - } while(1) - } +var createTexture = require('gl-texture2d') - function hex() { - if(/[^a-fA-F0-9]/.test(c)) { - token(content.join('')) - mode = NORMAL - return i - } +module.exports = createFBO - content.push(c) - last = c - return i + 1 - } +var colorAttachmentArrays = null +var FRAMEBUFFER_UNSUPPORTED +var FRAMEBUFFER_INCOMPLETE_ATTACHMENT +var FRAMEBUFFER_INCOMPLETE_DIMENSIONS +var FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT - function integer() { - if(c === '.') { - content.push(c) - mode = FLOAT - last = c - return i + 1 - } +function saveFBOState(gl) { + var fbo = gl.getParameter(gl.FRAMEBUFFER_BINDING) + var rbo = gl.getParameter(gl.RENDERBUFFER_BINDING) + var tex = gl.getParameter(gl.TEXTURE_BINDING_2D) + return [fbo, rbo, tex] +} - if(/[eE]/.test(c)) { - content.push(c) - mode = FLOAT - last = c - return i + 1 - } +function restoreFBOState(gl, data) { + gl.bindFramebuffer(gl.FRAMEBUFFER, data[0]) + gl.bindRenderbuffer(gl.RENDERBUFFER, data[1]) + gl.bindTexture(gl.TEXTURE_2D, data[2]) +} - if(c === 'x' && content.length === 1 && content[0] === '0') { - mode = HEX - content.push(c) - last = c - return i + 1 +function lazyInitColorAttachments(gl, ext) { + var maxColorAttachments = gl.getParameter(ext.MAX_COLOR_ATTACHMENTS_WEBGL) + colorAttachmentArrays = new Array(maxColorAttachments + 1) + for(var i=0; i<=maxColorAttachments; ++i) { + var x = new Array(maxColorAttachments) + for(var j=0; j -1) { - mode = KEYWORD - } else if(builtins.indexOf(contentstr) > -1) { - mode = BUILTIN - } else { - mode = IDENT - } - token(content.join('')) - mode = NORMAL - return i - } - content.push(c) - last = c - return i + 1 +//Initialize a texture object +function initTexture(gl, width, height, type, format, attachment) { + if(!type) { + return null } + var result = createTexture(gl, width, height, format, type) + result.magFilter = gl.NEAREST + result.minFilter = gl.NEAREST + result.mipSamples = 1 + result.bind() + gl.framebufferTexture2D(gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, result.handle, 0) + return result } -},{"./lib/builtins":92,"./lib/literals":93,"./lib/operators":94}],92:[function(require,module,exports){ -module.exports = [ - 'gl_Position' - , 'gl_PointSize' - , 'gl_ClipVertex' - , 'gl_FragCoord' - , 'gl_FrontFacing' - , 'gl_FragColor' - , 'gl_FragData' - , 'gl_FragDepth' - , 'gl_Color' - , 'gl_SecondaryColor' - , 'gl_Normal' - , 'gl_Vertex' - , 'gl_MultiTexCoord0' - , 'gl_MultiTexCoord1' - , 'gl_MultiTexCoord2' - , 'gl_MultiTexCoord3' - , 'gl_MultiTexCoord4' - , 'gl_MultiTexCoord5' - , 'gl_MultiTexCoord6' - , 'gl_MultiTexCoord7' - , 'gl_FogCoord' - , 'gl_MaxLights' - , 'gl_MaxClipPlanes' - , 'gl_MaxTextureUnits' - , 'gl_MaxTextureCoords' - , 'gl_MaxVertexAttribs' - , 'gl_MaxVertexUniformComponents' - , 'gl_MaxVaryingFloats' - , 'gl_MaxVertexTextureImageUnits' - , 'gl_MaxCombinedTextureImageUnits' - , 'gl_MaxTextureImageUnits' - , 'gl_MaxFragmentUniformComponents' - , 'gl_MaxDrawBuffers' - , 'gl_ModelViewMatrix' - , 'gl_ProjectionMatrix' - , 'gl_ModelViewProjectionMatrix' - , 'gl_TextureMatrix' - , 'gl_NormalMatrix' - , 'gl_ModelViewMatrixInverse' - , 'gl_ProjectionMatrixInverse' - , 'gl_ModelViewProjectionMatrixInverse' - , 'gl_TextureMatrixInverse' - , 'gl_ModelViewMatrixTranspose' - , 'gl_ProjectionMatrixTranspose' - , 'gl_ModelViewProjectionMatrixTranspose' - , 'gl_TextureMatrixTranspose' - , 'gl_ModelViewMatrixInverseTranspose' - , 'gl_ProjectionMatrixInverseTranspose' - , 'gl_ModelViewProjectionMatrixInverseTranspose' - , 'gl_TextureMatrixInverseTranspose' - , 'gl_NormalScale' - , 'gl_DepthRangeParameters' - , 'gl_DepthRange' - , 'gl_ClipPlane' - , 'gl_PointParameters' - , 'gl_Point' - , 'gl_MaterialParameters' - , 'gl_FrontMaterial' - , 'gl_BackMaterial' - , 'gl_LightSourceParameters' - , 'gl_LightSource' - , 'gl_LightModelParameters' - , 'gl_LightModel' - , 'gl_LightModelProducts' - , 'gl_FrontLightModelProduct' - , 'gl_BackLightModelProduct' - , 'gl_LightProducts' - , 'gl_FrontLightProduct' - , 'gl_BackLightProduct' - , 'gl_FogParameters' - , 'gl_Fog' - , 'gl_TextureEnvColor' - , 'gl_EyePlaneS' - , 'gl_EyePlaneT' - , 'gl_EyePlaneR' - , 'gl_EyePlaneQ' - , 'gl_ObjectPlaneS' - , 'gl_ObjectPlaneT' - , 'gl_ObjectPlaneR' - , 'gl_ObjectPlaneQ' - , 'gl_FrontColor' - , 'gl_BackColor' - , 'gl_FrontSecondaryColor' - , 'gl_BackSecondaryColor' - , 'gl_TexCoord' - , 'gl_FogFragCoord' - , 'gl_Color' - , 'gl_SecondaryColor' - , 'gl_TexCoord' - , 'gl_FogFragCoord' - , 'gl_PointCoord' - , 'radians' - , 'degrees' - , 'sin' - , 'cos' - , 'tan' - , 'asin' - , 'acos' - , 'atan' - , 'pow' - , 'exp' - , 'log' - , 'exp2' - , 'log2' - , 'sqrt' - , 'inversesqrt' - , 'abs' - , 'sign' - , 'floor' - , 'ceil' - , 'fract' - , 'mod' - , 'min' - , 'max' - , 'clamp' - , 'mix' - , 'step' - , 'smoothstep' - , 'length' - , 'distance' - , 'dot' - , 'cross' - , 'normalize' - , 'faceforward' - , 'reflect' - , 'refract' - , 'matrixCompMult' - , 'lessThan' - , 'lessThanEqual' - , 'greaterThan' - , 'greaterThanEqual' - , 'equal' - , 'notEqual' - , 'any' - , 'all' - , 'not' - , 'texture2D' - , 'texture2DProj' - , 'texture2DLod' - , 'texture2DProjLod' - , 'textureCube' - , 'textureCubeLod' - , 'dFdx' - , 'dFdy' -] +//Initialize a render buffer object +function initRenderBuffer(gl, width, height, component, attachment) { + var result = gl.createRenderbuffer() + gl.bindRenderbuffer(gl.RENDERBUFFER, result) + gl.renderbufferStorage(gl.RENDERBUFFER, component, width, height) + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, result) + return result +} -},{}],93:[function(require,module,exports){ -module.exports = [ - // current - 'precision' - , 'highp' - , 'mediump' - , 'lowp' - , 'attribute' - , 'const' - , 'uniform' - , 'varying' - , 'break' - , 'continue' - , 'do' - , 'for' - , 'while' - , 'if' - , 'else' - , 'in' - , 'out' - , 'inout' - , 'float' - , 'int' - , 'void' - , 'bool' - , 'true' - , 'false' - , 'discard' - , 'return' - , 'mat2' - , 'mat3' - , 'mat4' - , 'vec2' - , 'vec3' - , 'vec4' - , 'ivec2' - , 'ivec3' - , 'ivec4' - , 'bvec2' - , 'bvec3' - , 'bvec4' - , 'sampler1D' - , 'sampler2D' - , 'sampler3D' - , 'samplerCube' - , 'sampler1DShadow' - , 'sampler2DShadow' - , 'struct' +//Rebuild the frame buffer +function rebuildFBO(fbo) { - // future - , 'asm' - , 'class' - , 'union' - , 'enum' - , 'typedef' - , 'template' - , 'this' - , 'packed' - , 'goto' - , 'switch' - , 'default' - , 'inline' - , 'noinline' - , 'volatile' - , 'public' - , 'static' - , 'extern' - , 'external' - , 'interface' - , 'long' - , 'short' - , 'double' - , 'half' - , 'fixed' - , 'unsigned' - , 'input' - , 'output' - , 'hvec2' - , 'hvec3' - , 'hvec4' - , 'dvec2' - , 'dvec3' - , 'dvec4' - , 'fvec2' - , 'fvec3' - , 'fvec4' - , 'sampler2DRect' - , 'sampler3DRect' - , 'sampler2DRectShadow' - , 'sizeof' - , 'cast' - , 'namespace' - , 'using' -] + //Save FBO state + var state = saveFBOState(fbo.gl) -},{}],94:[function(require,module,exports){ -module.exports = [ - '<<=' - , '>>=' - , '++' - , '--' - , '<<' - , '>>' - , '<=' - , '>=' - , '==' - , '!=' - , '&&' - , '||' - , '+=' - , '-=' - , '*=' - , '/=' - , '%=' - , '&=' - , '^^' - , '^=' - , '|=' - , '(' - , ')' - , '[' - , ']' - , '.' - , '!' - , '~' - , '*' - , '/' - , '%' - , '+' - , '-' - , '<' - , '>' - , '&' - , '^' - , '|' - , '?' - , ':' - , '=' - , ',' - , ';' - , '{' - , '}' -] + var gl = fbo.gl + var handle = fbo.handle = gl.createFramebuffer() + var width = fbo._shape[0] + var height = fbo._shape[1] + var numColors = fbo.color.length + var ext = fbo._ext + var useStencil = fbo._useStencil + var useDepth = fbo._useDepth + var colorType = fbo._colorType + + //Bind the fbo + gl.bindFramebuffer(gl.FRAMEBUFFER, handle) + + //Allocate color buffers + for(var i=0; i 1) { + ext.drawBuffersWEBGL(colorAttachmentArrays[numColors]) + } -},{}],95:[function(require,module,exports){ -var tokenize = require('./index') + //Allocate depth/stencil buffers + var WEBGL_depth_texture = gl.getExtension('WEBGL_depth_texture') + if(WEBGL_depth_texture) { + if(useStencil) { + fbo.depth = initTexture(gl, width, height, + WEBGL_depth_texture.UNSIGNED_INT_24_8_WEBGL, + gl.DEPTH_STENCIL, + gl.DEPTH_STENCIL_ATTACHMENT) + } else if(useDepth) { + fbo.depth = initTexture(gl, width, height, + gl.UNSIGNED_SHORT, + gl.DEPTH_COMPONENT, + gl.DEPTH_ATTACHMENT) + } + } else { + if(useDepth && useStencil) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT) + } else if(useDepth) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) + } else if(useStencil) { + fbo._depth_rb = initRenderBuffer(gl, width, height, gl.STENCIL_INDEX, gl.STENCIL_ATTACHMENT) + } + } -module.exports = tokenizeString + //Check frame buffer state + var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER) + if(status !== gl.FRAMEBUFFER_COMPLETE) { -function tokenizeString(str) { - var generator = tokenize() - var tokens = [] + //Release all partially allocated resources + fbo._destroyed = true - tokens = tokens.concat(generator(str)) - tokens = tokens.concat(generator(null)) + //Release all resources + gl.bindFramebuffer(gl.FRAMEBUFFER, null) + gl.deleteFramebuffer(fbo.handle) + fbo.handle = null + if(fbo.depth) { + fbo.depth.dispose() + fbo.depth = null + } + if(fbo._depth_rb) { + gl.deleteRenderbuffer(fbo._depth_rb) + fbo._depth_rb = null + } + for(var i=0; i= 0 - } + //Don't resize if no change in shape + if( (fbo._shape[0] === w) && + (fbo._shape[1] === h) ) { + return + } - switch (match[8]) { - case "b": - arg = arg.toString(2) - break - case "c": - arg = String.fromCharCode(arg) - break - case "d": - case "i": - arg = parseInt(arg, 10) - break - case "j": - arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0) - break - case "e": - arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential() - break - case "f": - arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg) - break - case "g": - arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg) - break - case "o": - arg = arg.toString(8) - break - case "s": - arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg) - break - case "u": - arg = arg >>> 0 - break - case "x": - arg = arg.toString(16) - break - case "X": - arg = arg.toString(16).toUpperCase() - break - } - if (re.json.test(match[8])) { - output[output.length] = arg - } - else { - if (re.number.test(match[8]) && (!is_positive || match[3])) { - sign = is_positive ? "+" : "-" - arg = arg.toString().replace(re.sign, "") - } - else { - sign = "" - } - pad_character = match[4] ? match[4] === "0" ? "0" : match[4].charAt(1) : " " - pad_length = match[6] - (sign + arg).length - pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : "") : "" - output[output.length] = match[5] ? sign + arg + pad : (pad_character === "0" ? sign + pad + arg : pad + sign + arg) - } - } - } - return output.join("") - } + var gl = fbo.gl - sprintf.cache = {} + //Check parameter ranges + var maxFBOSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) + if( w < 0 || w > maxFBOSize || + h < 0 || h > maxFBOSize) { + throw new Error('gl-fbo: Can\'t resize FBO, invalid dimensions') + } - sprintf.parse = function(fmt) { - var _fmt = fmt, match = [], parse_tree = [], arg_names = 0 - while (_fmt) { - if ((match = re.text.exec(_fmt)) !== null) { - parse_tree[parse_tree.length] = match[0] - } - else if ((match = re.modulo.exec(_fmt)) !== null) { - parse_tree[parse_tree.length] = "%" - } - else if ((match = re.placeholder.exec(_fmt)) !== null) { - if (match[2]) { - arg_names |= 1 - var field_list = [], replacement_field = match[2], field_match = [] - if ((field_match = re.key.exec(replacement_field)) !== null) { - field_list[field_list.length] = field_match[1] - while ((replacement_field = replacement_field.substring(field_match[0].length)) !== "") { - if ((field_match = re.key_access.exec(replacement_field)) !== null) { - field_list[field_list.length] = field_match[1] - } - else if ((field_match = re.index_access.exec(replacement_field)) !== null) { - field_list[field_list.length] = field_match[1] - } - else { - throw new SyntaxError("[sprintf] failed to parse named argument key") - } - } - } - else { - throw new SyntaxError("[sprintf] failed to parse named argument key") - } - match[2] = field_list - } - else { - arg_names |= 2 - } - if (arg_names === 3) { - throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported") - } - parse_tree[parse_tree.length] = match - } - else { - throw new SyntaxError("[sprintf] unexpected placeholder") - } - _fmt = _fmt.substring(match[0].length) - } - return parse_tree - } + //Update shape + fbo._shape[0] = w + fbo._shape[1] = h - var vsprintf = function(fmt, argv, _argv) { - _argv = (argv || []).slice(0) - _argv.splice(0, 0, fmt) - return sprintf.apply(null, _argv) - } + //Save framebuffer state + var state = saveFBOState(gl) - /** - * helpers - */ - function get_type(variable) { - return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase() + //Resize framebuffer attachments + for(var i=0; i maxFBOSize || height < 0 || height > maxFBOSize) { + throw new Error('gl-fbo: Parameters are too large for FBO') + } + + //Handle each option type + options = options || {} + + //Figure out number of color buffers to use + var numColors = 1 + if('color' in options) { + numColors = Math.max(options.color|0, 0) + if(numColors < 0) { + throw new Error('gl-fbo: Must specify a nonnegative number of colors') } - else { - window.sprintf = sprintf - window.vsprintf = vsprintf + if(numColors > 1) { + //Check if multiple render targets supported + if(!WEBGL_draw_buffers) { + throw new Error('gl-fbo: Multiple draw buffer extension not supported') + } else if(numColors > gl.getParameter(WEBGL_draw_buffers.MAX_COLOR_ATTACHMENTS_WEBGL)) { + throw new Error('gl-fbo: Context does not support ' + numColors + ' draw buffers') + } + } + } - if (typeof define === "function" && define.amd) { - define(function() { - return { - sprintf: sprintf, - vsprintf: vsprintf - } - }) - } + //Determine whether to use floating point textures + var colorType = gl.UNSIGNED_BYTE + var OES_texture_float = gl.getExtension('OES_texture_float') + if(options.float && numColors > 0) { + if(!OES_texture_float) { + throw new Error('gl-fbo: Context does not support floating point textures') } -})(typeof window === "undefined" ? this : window); + colorType = gl.FLOAT + } else if(options.preferFloat && numColors > 0) { + if(OES_texture_float) { + colorType = gl.FLOAT + } + } -},{}],97:[function(require,module,exports){ -var hiddenStore = require('./hidden-store.js'); + //Check if we should use depth buffer + var useDepth = true + if('depth' in options) { + useDepth = !!options.depth + } -module.exports = createStore; + //Check if we should use a stencil buffer + var useStencil = false + if('stencil' in options) { + useStencil = !!options.stencil + } -function createStore() { - var key = {}; + return new Framebuffer( + gl, + width, + height, + colorType, + numColors, + useDepth, + useStencil, + WEBGL_draw_buffers) +} - return function (obj) { - if ((typeof obj !== 'object' || obj === null) && - typeof obj !== 'function' - ) { - throw new Error('Weakmap-shim: Key must be object') - } +},{"gl-texture2d":185}],81:[function(require,module,exports){ - var store = obj.valueOf(key); - return store && store.identity === key ? - store : hiddenStore(obj, key); - }; -} -},{"./hidden-store.js":98}],98:[function(require,module,exports){ -module.exports = hiddenStore; +exports.lineVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nfloat inverse_1_0(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse_1_0(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse_1_0(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse_1_0(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\n\n\nattribute vec2 a, d;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float width;\n\nvarying vec2 direction;\n\nvoid main() {\n vec2 dir = (matrix * vec3(d, 0)).xy;\n vec3 base = matrix * vec3(a, 1);\n vec2 n = 0.5 * width *\n normalize(screenShape.yx * vec2(dir.y, -dir.x)) / screenShape.xy;\n vec2 tangent = normalize(screenShape.xy * dir);\n if(dir.x < 0.0 || (dir.x == 0.0 && dir.y < 0.0)) {\n direction = -tangent;\n } else {\n direction = tangent;\n }\n gl_Position = vec4(base.xy/base.z + n, 0, 1);\n}\n" +exports.lineFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\nuniform vec2 screenShape;\nuniform sampler2D dashPattern;\nuniform float dashLength;\n\nvarying vec2 direction;\n\nvoid main() {\n float t = fract(dot(direction, gl_FragCoord.xy) / dashLength);\n vec4 pcolor = color * texture2D(dashPattern, vec2(t, 0.0)).r;\n gl_FragColor = vec4(pcolor.rgb * pcolor.a, pcolor.a);\n}\n" +exports.mitreVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 p;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float radius;\n\nvoid main() {\n vec3 pp = matrix * vec3(p, 1);\n gl_Position = vec4(pp.xy, 0, pp.z);\n gl_PointSize = radius;\n}\n" +exports.mitreFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n if(length(gl_PointCoord.xy - 0.5) > 0.25) {\n discard;\n }\n gl_FragColor = vec4(color.rgb, color.a);\n}\n" +exports.pickVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 a, d;\nattribute vec4 pick0, pick1;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float width;\n\nvarying vec4 pickA, pickB;\n\nfloat inverse_1_0(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse_1_0(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse_1_0(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse_1_0(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\n\n\nvoid main() {\n vec3 base = matrix * vec3(a, 1);\n vec2 n = width *\n normalize(screenShape.yx * vec2(d.y, -d.x)) / screenShape.xy;\n gl_Position = vec4(base.xy/base.z + n, 0, 1);\n pickA = pick0;\n pickB = pick1;\n}\n" +exports.pickFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 pickOffset;\n\nvarying vec4 pickA, pickB;\n\nvoid main() {\n vec4 fragId = vec4(pickA.xyz, 0.0);\n if(pickB.w > pickA.w) {\n fragId.xyz = pickB.xyz;\n }\n\n fragId += pickOffset;\n\n fragId.y += floor(fragId.x / 256.0);\n fragId.x -= floor(fragId.x / 256.0) * 256.0;\n\n fragId.z += floor(fragId.y / 256.0);\n fragId.y -= floor(fragId.y / 256.0) * 256.0;\n\n fragId.w += floor(fragId.z / 256.0);\n fragId.z -= floor(fragId.z / 256.0) * 256.0;\n\n gl_FragColor = fragId / 255.0;\n}\n" +exports.fillVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 a, d;\n\nuniform mat3 matrix;\nuniform vec2 projectAxis;\nuniform float projectValue;\nuniform float depth;\n\nvoid main() {\n vec3 base = matrix * vec3(a, 1);\n vec2 p = base.xy / base.z;\n if(d.y < 0.0 || (d.y == 0.0 && d.x < 0.0)) {\n if(dot(p, projectAxis) < projectValue) {\n p = p * (1.0 - abs(projectAxis)) + projectAxis * projectValue;\n }\n }\n gl_Position = vec4(p, depth, 1);\n}\n" +exports.fillFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n gl_FragColor = vec4(color.rgb * color.a, color.a);\n}\n" -function hiddenStore(obj, key) { - var store = { identity: key }; - var valueOf = obj.valueOf; +},{}],82:[function(require,module,exports){ +'use strict' - Object.defineProperty(obj, "valueOf", { - value: function (value) { - return value !== key ? - valueOf.apply(this, arguments) : store; - }, - writable: true - }); +module.exports = createLinePlot - return store; -} +var createShader = require('gl-shader') +var createBuffer = require('gl-buffer') +var createTexture = require('gl-texture2d') +var ndarray = require('ndarray') +var pool = require('typedarray-pool') -},{}],99:[function(require,module,exports){ -// Original - @Gozola. -// https://gist.github.com/Gozala/1269991 -// This is a reimplemented version (with a few bug fixes). +var SHADERS = require('./lib/shaders') -var createStore = require('./create-store.js'); +function GLLine2D( + plot, + dashPattern, + lineBuffer, + pickBuffer, + lineShader, + mitreShader, + fillShader, + pickShader) { -module.exports = weakMap; + this.plot = plot + this.dashPattern = dashPattern + this.lineBuffer = lineBuffer + this.pickBuffer = pickBuffer + this.lineShader = lineShader + this.mitreShader = mitreShader + this.fillShader = fillShader + this.pickShader = pickShader + this.usingDashes = false -function weakMap() { - var privates = createStore(); + this.bounds = [Infinity, Infinity, -Infinity, -Infinity] - return { - 'get': function (key, fallback) { - var store = privates(key) - return store.hasOwnProperty('value') ? - store.value : fallback - }, - 'set': function (key, value) { - privates(key).value = value; - }, - 'has': function(key) { - return 'value' in privates(key); - }, - 'delete': function (key) { - return delete privates(key).value; - } - } -} + this.width = 1 + this.color = [0,0,1,1] -},{"./create-store.js":97}],100:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],101:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],102:[function(require,module,exports){ -(function (global,Buffer){ -'use strict' + //Fill to axes + this.fill = [false, false, false, false] + this.fillColor = [[0,0,0,1], + [0,0,0,1], + [0,0,0,1], + [0,0,0,1]] -var bits = require('bit-twiddle') -var dup = require('dup') + this.data = null + this.numPoints = 0 + this.vertCount = 0 -//Legacy pool support -if(!global.__TYPEDARRAY_POOL) { - global.__TYPEDARRAY_POOL = { - UINT8 : dup([32, 0]) - , UINT16 : dup([32, 0]) - , UINT32 : dup([32, 0]) - , INT8 : dup([32, 0]) - , INT16 : dup([32, 0]) - , INT32 : dup([32, 0]) - , FLOAT : dup([32, 0]) - , DOUBLE : dup([32, 0]) - , DATA : dup([32, 0]) - , UINT8C : dup([32, 0]) - , BUFFER : dup([32, 0]) - } + this.pickOffset = 0 + + this.lodBuffer = [] } -var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined' -var POOL = global.__TYPEDARRAY_POOL +var proto = GLLine2D.prototype -//Upgrade pool -if(!POOL.UINT8C) { - POOL.UINT8C = dup([32, 0]) -} -if(!POOL.BUFFER) { - POOL.BUFFER = dup([32, 0]) -} +proto.draw = (function() { +var MATRIX = [1, 0, 0, + 0, 1, 0, + 0, 0, 1] +var SCREEN_SHAPE = [0,0] +var PX_AXIS = [1,0] +var NX_AXIS = [-1,0] +var PY_AXIS = [0,1] +var NY_AXIS = [0,-1] +return function() { + var plot = this.plot + var color = this.color + var width = this.width + var numPoints = this.numPoints + var bounds = this.bounds + var count = this.vertCount -//New technique: Only allocate from ArrayBufferView and Buffer -var DATA = POOL.DATA - , BUFFER = POOL.BUFFER + var gl = plot.gl + var viewBox = plot.viewBox + var dataBox = plot.dataBox + var pixelRatio = plot.pixelRatio -exports.free = function free(array) { - if(Buffer.isBuffer(array)) { - BUFFER[bits.log2(array.length)].push(array) - } else { - if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') { - array = array.buffer - } - if(!array) { - return - } - var n = array.length || array.byteLength - var log_n = bits.log2(n)|0 - DATA[log_n].push(array) - } -} + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + var screenX = viewBox[2] - viewBox[0] + var screenY = viewBox[3] - viewBox[1] -function freeArrayBuffer(buffer) { - if(!buffer) { - return - } - var n = buffer.length || buffer.byteLength - var log_n = bits.log2(n) - DATA[log_n].push(buffer) -} + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 -function freeTypedArray(array) { - freeArrayBuffer(array.buffer) -} + SCREEN_SHAPE[0] = screenX + SCREEN_SHAPE[1] = screenY -exports.freeUint8 = -exports.freeUint16 = -exports.freeUint32 = -exports.freeInt8 = -exports.freeInt16 = -exports.freeInt32 = -exports.freeFloat32 = -exports.freeFloat = -exports.freeFloat64 = -exports.freeDouble = -exports.freeUint8Clamped = -exports.freeDataView = freeTypedArray + var buffer = this.lineBuffer + buffer.bind() -exports.freeArrayBuffer = freeArrayBuffer + var fill = this.fill -exports.freeBuffer = function freeBuffer(array) { - BUFFER[bits.log2(array.length)].push(array) -} + if(fill[0] || fill[1] || fill[2] || fill[3]) { -exports.malloc = function malloc(n, dtype) { - if(dtype === undefined || dtype === 'arraybuffer') { - return mallocArrayBuffer(n) - } else { - switch(dtype) { - case 'uint8': - return mallocUint8(n) - case 'uint16': - return mallocUint16(n) - case 'uint32': - return mallocUint32(n) - case 'int8': - return mallocInt8(n) - case 'int16': - return mallocInt16(n) - case 'int32': - return mallocInt32(n) - case 'float': - case 'float32': - return mallocFloat(n) - case 'double': - case 'float64': - return mallocDouble(n) - case 'uint8_clamped': - return mallocUint8Clamped(n) - case 'buffer': - return mallocBuffer(n) - case 'data': - case 'dataview': - return mallocDataView(n) + var fillShader = this.fillShader + fillShader.bind() - default: - return null - } - } - return null -} + var fillUniforms = fillShader.uniforms + fillUniforms.matrix = MATRIX + fillUniforms.depth = plot.nextDepthValue() -function mallocArrayBuffer(n) { - var n = bits.nextPow2(n) - var log_n = bits.log2(n) - var d = DATA[log_n] - if(d.length > 0) { - return d.pop() - } - return new ArrayBuffer(n) -} -exports.mallocArrayBuffer = mallocArrayBuffer + var fillAttributes = fillShader.attributes + fillAttributes.a.pointer(gl.FLOAT, false, 16, 0) + fillAttributes.d.pointer(gl.FLOAT, false, 16, 8) -function mallocUint8(n) { - return new Uint8Array(mallocArrayBuffer(n), 0, n) -} -exports.mallocUint8 = mallocUint8 + gl.depthMask(true) + gl.enable(gl.DEPTH_TEST) -function mallocUint16(n) { - return new Uint16Array(mallocArrayBuffer(2*n), 0, n) -} -exports.mallocUint16 = mallocUint16 + var fillColor = this.fillColor + if(fill[0]) { + fillUniforms.color = fillColor[0] + fillUniforms.projectAxis = NX_AXIS + fillUniforms.projectValue = 1 + gl.drawArrays(gl.TRIANGLES, 0, count) + } -function mallocUint32(n) { - return new Uint32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocUint32 = mallocUint32 + if(fill[1]) { + fillUniforms.color = fillColor[1] + fillUniforms.projectAxis = NY_AXIS + fillUniforms.projectValue = 1 + gl.drawArrays(gl.TRIANGLES, 0, count) + } -function mallocInt8(n) { - return new Int8Array(mallocArrayBuffer(n), 0, n) -} -exports.mallocInt8 = mallocInt8 + if(fill[2]) { + fillUniforms.color = fillColor[2] + fillUniforms.projectAxis = PX_AXIS + fillUniforms.projectValue = 1 + gl.drawArrays(gl.TRIANGLES, 0, count) + } -function mallocInt16(n) { - return new Int16Array(mallocArrayBuffer(2*n), 0, n) -} -exports.mallocInt16 = mallocInt16 + if(fill[3]) { + fillUniforms.color = fillColor[3] + fillUniforms.projectAxis = PY_AXIS + fillUniforms.projectValue = 1 + gl.drawArrays(gl.TRIANGLES, 0, count) + } -function mallocInt32(n) { - return new Int32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocInt32 = mallocInt32 + gl.depthMask(false) + gl.disable(gl.DEPTH_TEST) + } -function mallocFloat(n) { - return new Float32Array(mallocArrayBuffer(4*n), 0, n) -} -exports.mallocFloat32 = exports.mallocFloat = mallocFloat + var shader = this.lineShader + shader.bind() -function mallocDouble(n) { - return new Float64Array(mallocArrayBuffer(8*n), 0, n) -} -exports.mallocFloat64 = exports.mallocDouble = mallocDouble + var uniforms = shader.uniforms + uniforms.matrix = MATRIX + uniforms.color = color + uniforms.width = width * pixelRatio + uniforms.screenShape = SCREEN_SHAPE + uniforms.dashPattern = this.dashPattern.bind() + uniforms.dashLength = this.dashLength * pixelRatio -function mallocUint8Clamped(n) { - if(hasUint8C) { - return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n) - } else { - return mallocUint8(n) - } -} -exports.mallocUint8Clamped = mallocUint8Clamped + var attributes = shader.attributes + attributes.a.pointer(gl.FLOAT, false, 16, 0) + attributes.d.pointer(gl.FLOAT, false, 16, 8) -function mallocDataView(n) { - return new DataView(mallocArrayBuffer(n), 0, n) -} -exports.mallocDataView = mallocDataView + gl.drawArrays(gl.TRIANGLES, 0, count) -function mallocBuffer(n) { - n = bits.nextPow2(n) - var log_n = bits.log2(n) - var cache = BUFFER[log_n] - if(cache.length > 0) { - return cache.pop() - } - return new Buffer(n) -} -exports.mallocBuffer = mallocBuffer + //Draw mitres + if(width > 2 && !this.usingDashes) { + var mshader = this.mitreShader + mshader.bind() -exports.clearCache = function clearCache() { - for(var i=0; i<32; ++i) { - POOL.UINT8[i].length = 0 - POOL.UINT16[i].length = 0 - POOL.UINT32[i].length = 0 - POOL.INT8[i].length = 0 - POOL.INT16[i].length = 0 - POOL.INT32[i].length = 0 - POOL.FLOAT[i].length = 0 - POOL.DOUBLE[i].length = 0 - POOL.UINT8C[i].length = 0 - DATA[i].length = 0 - BUFFER[i].length = 0 + var muniforms = mshader.uniforms + muniforms.matrix = MATRIX + muniforms.color = color + muniforms.screenShape = SCREEN_SHAPE + muniforms.radius = width * pixelRatio + + mshader.attributes.p.pointer(gl.FLOAT, false, 48, 0) + gl.drawArrays(gl.POINTS, 0, (count/3)|0) } } -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) -},{"bit-twiddle":100,"buffer":48,"dup":101}],103:[function(require,module,exports){ -'use strict' - -module.exports = createErrorBars +})() -var createBuffer = require('gl-buffer') -var createVAO = require('gl-vao') -var createShader = require('./shaders/index') +proto.drawPick = (function() { + var MATRIX = [1, 0, 0, + 0, 1, 0, + 0, 0, 1] + var SCREEN_SHAPE = [0,0] + var PICK_OFFSET = [0,0,0,0] + return function(pickOffset) { + var plot = this.plot + var shader = this.pickShader + var buffer = this.lineBuffer + var pickBuffer= this.pickBuffer + var width = this.width + var numPoints = this.numPoints + var bounds = this.bounds + var count = this.vertCount -var IDENTITY = [1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] + var gl = plot.gl + var viewBox = plot.viewBox + var dataBox = plot.dataBox + var pixelRatio = plot.pickPixelRatio -function ErrorBars(gl, buffer, vao, shader) { - this.gl = gl - this.shader = shader - this.buffer = buffer - this.vao = vao - this.pixelRatio = 1 - this.bounds = [[ Infinity, Infinity, Infinity], [-Infinity,-Infinity,-Infinity]] - this.clipBounds = [[-Infinity,-Infinity,-Infinity], [ Infinity, Infinity, Infinity]] - this.lineWidth = [1,1,1] - this.capSize = [10,10,10] - this.lineCount = [0,0,0] - this.lineOffset = [0,0,0] - this.opacity = 1 -} + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + var screenX = viewBox[2] - viewBox[0] + var screenY = viewBox[3] - viewBox[1] -var proto = ErrorBars.prototype + this.pickOffset = pickOffset -proto.isOpaque = function() { - return this.opacity >= 1 -} + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 -proto.isTransparent = function() { - return this.opacity < 1 -} + SCREEN_SHAPE[0] = screenX + SCREEN_SHAPE[1] = screenY -proto.drawTransparent = proto.draw = function(cameraParams) { - var gl = this.gl - var uniforms = this.shader.uniforms + PICK_OFFSET[0] = pickOffset & 0xff + PICK_OFFSET[1] = (pickOffset>>>8) & 0xff + PICK_OFFSET[2] = (pickOffset>>>16) & 0xff + PICK_OFFSET[3] = pickOffset>>>24 - this.shader.bind() - var view = uniforms.view = cameraParams.view || IDENTITY - var projection = uniforms.projection = cameraParams.projection || IDENTITY - uniforms.model = cameraParams.model || IDENTITY - uniforms.clipBounds = this.clipBounds - uniforms.opacity = this.opacity + shader.bind() + var uniforms = shader.uniforms + uniforms.matrix = MATRIX + uniforms.width = width * pixelRatio + uniforms.pickOffset = PICK_OFFSET + uniforms.screenShape = SCREEN_SHAPE - var cx = view[12] - var cy = view[13] - var cz = view[14] - var cw = view[15] - var pixelScaleF = this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight + var attributes = shader.attributes + buffer.bind() + attributes.a.pointer(gl.FLOAT, false, 16, 0) + attributes.d.pointer(gl.FLOAT, false, 16, 8) - this.vao.bind() - for(var i=0; i<3; ++i) { - gl.lineWidth(this.lineWidth[i]) - uniforms.capSize = this.capSize[i] * pixelScaleF - gl.drawArrays(gl.LINES, this.lineOffset[i], this.lineCount[i]) - } - this.vao.unbind() -} + pickBuffer.bind() + attributes.pick0.pointer(gl.UNSIGNED_BYTE, false, 8, 0) + attributes.pick1.pointer(gl.UNSIGNED_BYTE, false, 8, 4) -function updateBounds(bounds, point) { - for(var i=0; i<3; ++i) { - bounds[0][i] = Math.min(bounds[0][i], point[i]) - bounds[1][i] = Math.max(bounds[1][i], point[i]) - } -} + gl.drawArrays(gl.TRIANGLES, 0, count) -var FACE_TABLE = (function(){ - var table = new Array(3) - for(var d=0; d<3; ++d) { - var row = [] - for(var j=1; j<=2; ++j) { - for(var s=-1; s<=1; s+=2) { - var u = (j+d) % 3 - var y = [0,0,0] - y[u] = s - row.push(y) - } - } - table[d] = row + return pickOffset + numPoints } - return table })() - -function emitFace(verts, x, c, d) { - var offsets = FACE_TABLE[d] - for(var i=0; i= pickOffset + pointCount) { + return null } - return offsets.length + var pointId = value - pickOffset + var points = this.data + return { + object: this, + pointId: pointId, + dataCoord: [ points[2*pointId], points[2*pointId+1] ] + } +} + +function deepCopy(arr) { + return arr.map(function(x) { + return x.slice() + }) } proto.update = function(options) { options = options || {} - if('lineWidth' in options) { - this.lineWidth = options.lineWidth - if(!Array.isArray(this.lineWidth)) { - this.lineWidth = [this.lineWidth, this.lineWidth, this.lineWidth] - } + var gl = this.plot.gl + + this.color = (options.color || [0,0,1,1]).slice() + this.width = +(options.width || 1) + + this.fill = (options.fill || [false,false,false,false]).slice() + this.fillColor = deepCopy(options.fillColor || [[0,0,0,1], + [0,0,0,1], + [0,0,0,1], + [0,0,0,1]]) + + var dashes = options.dashes || [1] + var dashLength = 0 + for(var i=0; i 1 + + this.dashPattern = createTexture(gl, + ndarray(dashData, [dashLength, 1, 4], [1, 0, 0])) + this.dashPattern.minFilter = gl.NEAREST + this.dashPattern.magFilter = gl.NEAREST + this.dashLength = dashLength + pool.free(dashData) + + var data = options.positions + this.data = data + + var bounds = this.bounds + bounds[0] = bounds[1] = Infinity + bounds[2] = bounds[3] = -Infinity + + var numPoints = this.numPoints = data.length>>>1 + if(numPoints === 0) { + return } - var color = options.color || [[0,0,0],[0,0,0],[0,0,0]] - var position = options.position - var error = options.error - if(!Array.isArray(color[0])) { - color = [color,color,color] + for(var i=0; i 1) { + var id = --ptr + var ax = data[2*ptr] + var ay = data[2*ptr+1] - for(var k=0; k<3; ++k) { - if(isNaN(p[k]) || !isFinite(p[k])) { - continue i_loop - } - } + ax = (ax - bounds[0]) / (bounds[2] - bounds[0]) + ay = (ay - bounds[1]) / (bounds[3] - bounds[1]) - var e = error[i] - var c = color[j] - if(Array.isArray(c[0])) { - c = color[i] - } - if(c.length === 3) { - c = [c[0], c[1], c[2], 1] - } - if(isNaN(e[0][j]) || isNaN(e[1][j])) { - continue - } - if(e[0][j] < 0) { - var x = p.slice() - x[j] += e[0][j] - verts.push(p[0], p[1], p[2], - c[0], c[1], c[2], c[3], - 0, 0, 0, - x[0], x[1], x[2], - c[0], c[1], c[2], c[3], - 0, 0, 0) - updateBounds(this.bounds, x) - vertexCount += 2 + emitFace(verts, x, c, j) - } - if(e[1][j] > 0) { - var x = p.slice() - x[j] += e[1][j] - verts.push(p[0], p[1], p[2], - c[0], c[1], c[2], c[3], - 0, 0, 0, - x[0], x[1], x[2], - c[0], c[1], c[2], c[3], - 0, 0, 0) - updateBounds(this.bounds, x) - vertexCount += 2 + emitFace(verts, x, c, j) - } - } - this.lineCount[j] = vertexCount - this.lineOffset[j] - } - this.buffer.update(verts) - } -} + var next = id-1 + var bx = data[2*next] + var by = data[2*next+1] -proto.dispose = function() { - this.shader.dispose() - this.buffer.dispose() - this.vao.dispose() -} + bx = (bx - bounds[0]) / (bounds[2] - bounds[0]) + by = (by - bounds[1]) / (bounds[3] - bounds[1]) -function createErrorBars(options) { - var gl = options.gl - var buffer = createBuffer(gl) - var vao = createVAO(gl, [ - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 0, - stride: 40 - }, - { - buffer: buffer, - type: gl.FLOAT, - size: 4, - offset: 12, - stride: 40 - }, - { - buffer: buffer, - type: gl.FLOAT, - size: 3, - offset: 28, - stride: 40 - } - ]) + var dx = bx - ax + var dy = by - ay - var shader = createShader(gl) - shader.attributes.position.location = 0 - shader.attributes.color.location = 1 - shader.attributes.offset.location = 2 + var akey0 = id | (1<<24) + var akey1 = (id-1) + var bkey0 = id + var bkey1 = (id-1) | (1<<24) - var result = new ErrorBars(gl, buffer, vao, shader) - result.update(options) - return result -} + lineData[--lineDataPtr] = -dy + lineData[--lineDataPtr] = -dx + lineData[--lineDataPtr] = ay + lineData[--lineDataPtr] = ax + pickData[--pickDataPtr] = akey0 + pickData[--pickDataPtr] = akey1 -},{"./shaders/index":136,"gl-buffer":104,"gl-vao":135}],104:[function(require,module,exports){ -arguments[4][75][0].apply(exports,arguments) -},{"dup":75,"ndarray":987,"ndarray-ops":982,"typedarray-pool":107}],105:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],106:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],107:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":105,"buffer":48,"dup":102}],108:[function(require,module,exports){ -arguments[4][76][0].apply(exports,arguments) -},{"./lib/GLError":109,"./lib/create-attributes":110,"./lib/create-uniforms":111,"./lib/reflect":112,"./lib/runtime-reflect":113,"./lib/shader-cache":114,"dup":76}],109:[function(require,module,exports){ -arguments[4][77][0].apply(exports,arguments) -},{"dup":77}],110:[function(require,module,exports){ -arguments[4][78][0].apply(exports,arguments) -},{"./GLError":109,"dup":78}],111:[function(require,module,exports){ -arguments[4][79][0].apply(exports,arguments) -},{"./GLError":109,"./reflect":112,"dup":79}],112:[function(require,module,exports){ -arguments[4][80][0].apply(exports,arguments) -},{"dup":80}],113:[function(require,module,exports){ -arguments[4][81][0].apply(exports,arguments) -},{"dup":81}],114:[function(require,module,exports){ -arguments[4][82][0].apply(exports,arguments) -},{"./GLError":109,"dup":82,"gl-format-compiler-error":115,"weakmap-shim":131}],115:[function(require,module,exports){ -arguments[4][83][0].apply(exports,arguments) -},{"add-line-numbers":116,"dup":83,"gl-constants/lookup":120,"glsl-shader-name":121,"sprintf-js":128}],116:[function(require,module,exports){ -arguments[4][84][0].apply(exports,arguments) -},{"dup":84,"pad-left":117}],117:[function(require,module,exports){ -arguments[4][85][0].apply(exports,arguments) -},{"dup":85,"repeat-string":118}],118:[function(require,module,exports){ -arguments[4][86][0].apply(exports,arguments) -},{"dup":86}],119:[function(require,module,exports){ -arguments[4][87][0].apply(exports,arguments) -},{"dup":87}],120:[function(require,module,exports){ -arguments[4][88][0].apply(exports,arguments) -},{"./1.0/numbers":119,"dup":88}],121:[function(require,module,exports){ -arguments[4][89][0].apply(exports,arguments) -},{"atob-lite":122,"dup":89,"glsl-tokenizer":127}],122:[function(require,module,exports){ -arguments[4][90][0].apply(exports,arguments) -},{"dup":90}],123:[function(require,module,exports){ -arguments[4][91][0].apply(exports,arguments) -},{"./lib/builtins":124,"./lib/literals":125,"./lib/operators":126,"dup":91}],124:[function(require,module,exports){ -arguments[4][92][0].apply(exports,arguments) -},{"dup":92}],125:[function(require,module,exports){ -arguments[4][93][0].apply(exports,arguments) -},{"dup":93}],126:[function(require,module,exports){ -arguments[4][94][0].apply(exports,arguments) -},{"dup":94}],127:[function(require,module,exports){ -arguments[4][95][0].apply(exports,arguments) -},{"./index":123,"dup":95}],128:[function(require,module,exports){ -arguments[4][96][0].apply(exports,arguments) -},{"dup":96}],129:[function(require,module,exports){ -arguments[4][97][0].apply(exports,arguments) -},{"./hidden-store.js":130,"dup":97}],130:[function(require,module,exports){ -arguments[4][98][0].apply(exports,arguments) -},{"dup":98}],131:[function(require,module,exports){ -arguments[4][99][0].apply(exports,arguments) -},{"./create-store.js":129,"dup":99}],132:[function(require,module,exports){ -"use strict" + lineData[--lineDataPtr] = dy + lineData[--lineDataPtr] = dx + lineData[--lineDataPtr] = by + lineData[--lineDataPtr] = bx + pickData[--pickDataPtr] = bkey0 + pickData[--pickDataPtr] = bkey1 -function doBind(gl, elements, attributes) { - if(elements) { - elements.bind() - } else { - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) - } - var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0 - if(attributes) { - if(attributes.length > nattribs) { - throw new Error("gl-vao: Too many vertex attributes") - } - for(var i=0; i= 1 +} +proto.pickSlots = 1 -var createShader = require('gl-shader') +proto.setPickBase = function(id) { + this.pickId = id +} -var vertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}" -var fragSrc = "#define GLSLIFY 1\nprecision mediump float;\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if(any(lessThan(fragPosition, clipBounds[0])) || any(greaterThan(fragPosition, clipBounds[1]))) {\n discard;\n }\n gl_FragColor = opacity * fragColor;\n}" +proto.drawTransparent = proto.draw = function(camera) { + var gl = this.gl + var shader = this.shader + var vao = this.vao + shader.bind() + shader.uniforms = { + model: camera.model || identity, + view: camera.view || identity, + projection: camera.projection || identity, + clipBounds: filterClipBounds(this.clipBounds), + dashTexture: this.texture.bind(), + dashScale: this.dashScale / this.arcLength[this.arcLength.length-1], + opacity: this.opacity, + screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], + pixelRatio: this.pixelRatio + } + vao.bind() + vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) +} -module.exports = function(gl) { - return createShader(gl, vertSrc, fragSrc, null, [ - {name: 'position', type: 'vec3'}, - {name: 'offset', type: 'vec3'}, - {name: 'color', type: 'vec4'} - ]) +proto.drawPick = function(camera) { + var gl = this.gl + var shader = this.pickShader + var vao = this.vao + shader.bind() + shader.uniforms = { + model: camera.model || identity, + view: camera.view || identity, + projection: camera.projection || identity, + pickId: this.pickId, + clipBounds: filterClipBounds(this.clipBounds), + screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], + pixelRatio: this.pixelRatio + } + vao.bind() + vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) } -},{"gl-shader":108}],137:[function(require,module,exports){ +proto.update = function(options) { + this.dirty = true + if('dashScale' in options) { + this.dashScale = options.dashScale + } + if('opacity' in options) { + this.opacity = +options.opacity + } -exports.lineVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nfloat inverse_1_0(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse_1_0(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse_1_0(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse_1_0(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\n\n\nattribute vec2 a, d;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float width;\n\nvarying vec2 direction;\n\nvoid main() {\n vec2 dir = (matrix * vec3(d, 0)).xy;\n vec3 base = matrix * vec3(a, 1);\n vec2 n = 0.5 * width *\n normalize(screenShape.yx * vec2(dir.y, -dir.x)) / screenShape.xy;\n vec2 tangent = normalize(screenShape.xy * dir);\n if(dir.x < 0.0 || (dir.x == 0.0 && dir.y < 0.0)) {\n direction = -tangent;\n } else {\n direction = tangent;\n }\n gl_Position = vec4(base.xy/base.z + n, 0, 1);\n}\n" -exports.lineFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\nuniform vec2 screenShape;\nuniform sampler2D dashPattern;\nuniform float dashLength;\n\nvarying vec2 direction;\n\nvoid main() {\n float t = fract(dot(direction, gl_FragCoord.xy) / dashLength);\n vec4 pcolor = color * texture2D(dashPattern, vec2(t, 0.0)).r;\n gl_FragColor = vec4(pcolor.rgb * pcolor.a, pcolor.a);\n}\n" -exports.mitreVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 p;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float radius;\n\nvoid main() {\n vec3 pp = matrix * vec3(p, 1);\n gl_Position = vec4(pp.xy, 0, pp.z);\n gl_PointSize = radius;\n}\n" -exports.mitreFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n if(length(gl_PointCoord.xy - 0.5) > 0.25) {\n discard;\n }\n gl_FragColor = vec4(color.rgb, color.a);\n}\n" -exports.pickVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 a, d;\nattribute vec4 pick0, pick1;\n\nuniform mat3 matrix;\nuniform vec2 screenShape;\nuniform float width;\n\nvarying vec4 pickA, pickB;\n\nfloat inverse_1_0(float m) {\n return 1.0 / m;\n}\n\nmat2 inverse_1_0(mat2 m) {\n return mat2(m[1][1],-m[0][1],\n -m[1][0], m[0][0]) / (m[0][0]*m[1][1] - m[0][1]*m[1][0]);\n}\n\nmat3 inverse_1_0(mat3 m) {\n float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];\n float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];\n float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];\n\n float b01 = a22 * a11 - a12 * a21;\n float b11 = -a22 * a10 + a12 * a20;\n float b21 = a21 * a10 - a11 * a20;\n\n float det = a00 * b01 + a01 * b11 + a02 * b21;\n\n return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),\n b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),\n b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;\n}\n\nmat4 inverse_1_0(mat4 m) {\n float\n a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3],\n a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3],\n a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3],\n a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3],\n\n b00 = a00 * a11 - a01 * a10,\n b01 = a00 * a12 - a02 * a10,\n b02 = a00 * a13 - a03 * a10,\n b03 = a01 * a12 - a02 * a11,\n b04 = a01 * a13 - a03 * a11,\n b05 = a02 * a13 - a03 * a12,\n b06 = a20 * a31 - a21 * a30,\n b07 = a20 * a32 - a22 * a30,\n b08 = a20 * a33 - a23 * a30,\n b09 = a21 * a32 - a22 * a31,\n b10 = a21 * a33 - a23 * a31,\n b11 = a22 * a33 - a23 * a32,\n\n det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n\n return mat4(\n a11 * b11 - a12 * b10 + a13 * b09,\n a02 * b10 - a01 * b11 - a03 * b09,\n a31 * b05 - a32 * b04 + a33 * b03,\n a22 * b04 - a21 * b05 - a23 * b03,\n a12 * b08 - a10 * b11 - a13 * b07,\n a00 * b11 - a02 * b08 + a03 * b07,\n a32 * b02 - a30 * b05 - a33 * b01,\n a20 * b05 - a22 * b02 + a23 * b01,\n a10 * b10 - a11 * b08 + a13 * b06,\n a01 * b08 - a00 * b10 - a03 * b06,\n a30 * b04 - a31 * b02 + a33 * b00,\n a21 * b02 - a20 * b04 - a23 * b00,\n a11 * b07 - a10 * b09 - a12 * b06,\n a00 * b09 - a01 * b07 + a02 * b06,\n a31 * b01 - a30 * b03 - a32 * b00,\n a20 * b03 - a21 * b01 + a22 * b00) / det;\n}\n\n\n\nvoid main() {\n vec3 base = matrix * vec3(a, 1);\n vec2 n = width *\n normalize(screenShape.yx * vec2(d.y, -d.x)) / screenShape.xy;\n gl_Position = vec4(base.xy/base.z + n, 0, 1);\n pickA = pick0;\n pickB = pick1;\n}\n" -exports.pickFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 pickOffset;\n\nvarying vec4 pickA, pickB;\n\nvoid main() {\n vec4 fragId = vec4(pickA.xyz, 0.0);\n if(pickB.w > pickA.w) {\n fragId.xyz = pickB.xyz;\n }\n\n fragId += pickOffset;\n\n fragId.y += floor(fragId.x / 256.0);\n fragId.x -= floor(fragId.x / 256.0) * 256.0;\n\n fragId.z += floor(fragId.y / 256.0);\n fragId.y -= floor(fragId.y / 256.0) * 256.0;\n\n fragId.w += floor(fragId.z / 256.0);\n fragId.z -= floor(fragId.z / 256.0) * 256.0;\n\n gl_FragColor = fragId / 255.0;\n}\n" -exports.fillVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 a, d;\n\nuniform mat3 matrix;\nuniform vec2 projectAxis;\nuniform float projectValue;\nuniform float depth;\n\nvoid main() {\n vec3 base = matrix * vec3(a, 1);\n vec2 p = base.xy / base.z;\n if(d.y < 0.0 || (d.y == 0.0 && d.x < 0.0)) {\n if(dot(p, projectAxis) < projectValue) {\n p = p * (1.0 - abs(projectAxis)) + projectAxis * projectValue;\n }\n }\n gl_Position = vec4(p, depth, 1);\n}\n" -exports.fillFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n gl_FragColor = vec4(color.rgb * color.a, color.a);\n}\n" + var positions = options.position || options.positions + if(!positions) { + return + } -},{}],138:[function(require,module,exports){ -'use strict' + //Default color + var colors = options.color || options.colors || [0,0,0,1] -module.exports = createLinePlot + var lineWidth = options.lineWidth || 1 -var createShader = require('gl-shader') -var createBuffer = require('gl-buffer') -var createTexture = require('gl-texture2d') -var ndarray = require('ndarray') -var pool = require('typedarray-pool') + //Recalculate buffer data + var buffer = [] + var arcLengthArray = [] + var pointArray = [] + var arcLength = 0.0 + var vertexCount = 0 + var bounds = [[ Infinity, Infinity, Infinity], + [-Infinity,-Infinity,-Infinity]] -var SHADERS = require('./lib/shaders') +fill_loop: + for(var i=1; i 2 && !this.usingDashes) { - var mshader = this.mitreShader - mshader.bind() + if (!det) return null + det = 1.0 / det - var muniforms = mshader.uniforms - muniforms.matrix = MATRIX - muniforms.color = color - muniforms.screenShape = SCREEN_SHAPE - muniforms.radius = width * pixelRatio + out[0] = b01 * det + out[1] = (-a22 * a01 + a02 * a21) * det + out[2] = (a12 * a01 - a02 * a11) * det + out[3] = b11 * det + out[4] = (a22 * a00 - a02 * a20) * det + out[5] = (-a12 * a00 + a02 * a10) * det + out[6] = b21 * det + out[7] = (-a21 * a00 + a01 * a20) * det + out[8] = (a11 * a00 - a01 * a10) * det - mshader.attributes.p.pointer(gl.FLOAT, false, 48, 0) - gl.drawArrays(gl.POINTS, 0, (count/3)|0) - } + return out } -})() -proto.drawPick = (function() { - var MATRIX = [1, 0, 0, - 0, 1, 0, - 0, 0, 1] - var SCREEN_SHAPE = [0,0] - var PICK_OFFSET = [0,0,0,0] - return function(pickOffset) { - var plot = this.plot - var shader = this.pickShader - var buffer = this.lineBuffer - var pickBuffer= this.pickBuffer - var width = this.width - var numPoints = this.numPoints - var bounds = this.bounds - var count = this.vertCount +},{}],88:[function(require,module,exports){ +module.exports = clone; + +/** + * Creates a new mat4 initialized with values from an existing matrix + * + * @param {mat4} a matrix to clone + * @returns {mat4} a new 4x4 matrix + */ +function clone(a) { + var out = new Float32Array(16); + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; +},{}],89:[function(require,module,exports){ +module.exports = create; + +/** + * Creates a new identity mat4 + * + * @returns {mat4} a new 4x4 matrix + */ +function create() { + var out = new Float32Array(16); + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; +},{}],90:[function(require,module,exports){ +module.exports = determinant; - var gl = plot.gl - var viewBox = plot.viewBox - var dataBox = plot.dataBox - var pixelRatio = plot.pickPixelRatio +/** + * Calculates the determinant of a mat4 + * + * @param {mat4} a the source matrix + * @returns {Number} determinant of a + */ +function determinant(a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], - var boundX = bounds[2] - bounds[0] - var boundY = bounds[3] - bounds[1] - var dataX = dataBox[2] - dataBox[0] - var dataY = dataBox[3] - dataBox[1] - var screenX = viewBox[2] - viewBox[0] - var screenY = viewBox[3] - viewBox[1] + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32; - this.pickOffset = pickOffset + // Calculate the determinant + return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; +}; +},{}],91:[function(require,module,exports){ +module.exports = fromQuat; - MATRIX[0] = 2.0 * boundX / dataX - MATRIX[4] = 2.0 * boundY / dataY - MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 - MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 +/** + * Creates a matrix from a quaternion rotation. + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @returns {mat4} out + */ +function fromQuat(out, q) { + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, - SCREEN_SHAPE[0] = screenX - SCREEN_SHAPE[1] = screenY + xx = x * x2, + yx = y * x2, + yy = y * y2, + zx = z * x2, + zy = z * y2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; - PICK_OFFSET[0] = pickOffset & 0xff - PICK_OFFSET[1] = (pickOffset>>>8) & 0xff - PICK_OFFSET[2] = (pickOffset>>>16) & 0xff - PICK_OFFSET[3] = pickOffset>>>24 + out[0] = 1 - yy - zz; + out[1] = yx + wz; + out[2] = zx - wy; + out[3] = 0; - shader.bind() + out[4] = yx - wz; + out[5] = 1 - xx - zz; + out[6] = zy + wx; + out[7] = 0; - var uniforms = shader.uniforms - uniforms.matrix = MATRIX - uniforms.width = width * pixelRatio - uniforms.pickOffset = PICK_OFFSET - uniforms.screenShape = SCREEN_SHAPE + out[8] = zx + wy; + out[9] = zy - wx; + out[10] = 1 - xx - yy; + out[11] = 0; - var attributes = shader.attributes + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; - buffer.bind() - attributes.a.pointer(gl.FLOAT, false, 16, 0) - attributes.d.pointer(gl.FLOAT, false, 16, 8) + return out; +}; +},{}],92:[function(require,module,exports){ +module.exports = fromRotationTranslation; - pickBuffer.bind() - attributes.pick0.pointer(gl.UNSIGNED_BYTE, false, 8, 0) - attributes.pick1.pointer(gl.UNSIGNED_BYTE, false, 8, 4) +/** + * Creates a matrix from a quaternion rotation and vector translation + * This is equivalent to (but much faster than): + * + * mat4.identity(dest); + * mat4.translate(dest, vec); + * var quatMat = mat4.create(); + * quat4.toMat4(quat, quatMat); + * mat4.multiply(dest, quatMat); + * + * @param {mat4} out mat4 receiving operation result + * @param {quat4} q Rotation quaternion + * @param {vec3} v Translation vector + * @returns {mat4} out + */ +function fromRotationTranslation(out, q, v) { + // Quaternion math + var x = q[0], y = q[1], z = q[2], w = q[3], + x2 = x + x, + y2 = y + y, + z2 = z + z, - gl.drawArrays(gl.TRIANGLES, 0, count) + xx = x * x2, + xy = x * y2, + xz = x * z2, + yy = y * y2, + yz = y * z2, + zz = z * z2, + wx = w * x2, + wy = w * y2, + wz = w * z2; - return pickOffset + numPoints - } -})() + out[0] = 1 - (yy + zz); + out[1] = xy + wz; + out[2] = xz - wy; + out[3] = 0; + out[4] = xy - wz; + out[5] = 1 - (xx + zz); + out[6] = yz + wx; + out[7] = 0; + out[8] = xz + wy; + out[9] = yz - wx; + out[10] = 1 - (xx + yy); + out[11] = 0; + out[12] = v[0]; + out[13] = v[1]; + out[14] = v[2]; + out[15] = 1; + + return out; +}; +},{}],93:[function(require,module,exports){ +module.exports = identity; -proto.pick = function(x, y, value) { - var pickOffset = this.pickOffset - var pointCount = this.numPoints - if(value < pickOffset || value >= pickOffset + pointCount) { - return null - } - var pointId = value - pickOffset - var points = this.data - return { - object: this, - pointId: pointId, - dataCoord: [ points[2*pointId], points[2*pointId+1] ] - } -} +/** + * Set a mat4 to the identity matrix + * + * @param {mat4} out the receiving matrix + * @returns {mat4} out + */ +function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = 1; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = 1; + out[11] = 0; + out[12] = 0; + out[13] = 0; + out[14] = 0; + out[15] = 1; + return out; +}; +},{}],94:[function(require,module,exports){ +module.exports = invert; -function deepCopy(arr) { - return arr.map(function(x) { - return x.slice() - }) -} +/** + * Inverts a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +function invert(out, a) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], -proto.update = function(options) { - options = options || {} + b00 = a00 * a11 - a01 * a10, + b01 = a00 * a12 - a02 * a10, + b02 = a00 * a13 - a03 * a10, + b03 = a01 * a12 - a02 * a11, + b04 = a01 * a13 - a03 * a11, + b05 = a02 * a13 - a03 * a12, + b06 = a20 * a31 - a21 * a30, + b07 = a20 * a32 - a22 * a30, + b08 = a20 * a33 - a23 * a30, + b09 = a21 * a32 - a22 * a31, + b10 = a21 * a33 - a23 * a31, + b11 = a22 * a33 - a23 * a32, - var gl = this.plot.gl + // Calculate the determinant + det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; - this.color = (options.color || [0,0,1,1]).slice() - this.width = +(options.width || 1) + if (!det) { + return null; + } + det = 1.0 / det; - this.fill = (options.fill || [false,false,false,false]).slice() - this.fillColor = deepCopy(options.fillColor || [[0,0,0,1], - [0,0,0,1], - [0,0,0,1], - [0,0,0,1]]) + out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; + out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; + out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; + out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; + out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; + out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; + out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; + out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; + out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; + out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; + out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; + out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; + out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; + out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; + out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; + out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; - var dashes = options.dashes || [1] - var dashLength = 0 - for(var i=0; i 1 + return out; +}; +},{}],95:[function(require,module,exports){ +var identity = require('./identity'); - this.dashPattern = createTexture(gl, - ndarray(dashData, [dashLength, 1, 4], [1, 0, 0])) - this.dashPattern.minFilter = gl.NEAREST - this.dashPattern.magFilter = gl.NEAREST - this.dashLength = dashLength - pool.free(dashData) +module.exports = lookAt; - var data = options.positions - this.data = data +/** + * Generates a look-at matrix with the given eye position, focal point, and up axis + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {vec3} eye Position of the viewer + * @param {vec3} center Point the viewer is looking at + * @param {vec3} up vec3 pointing up + * @returns {mat4} out + */ +function lookAt(out, eye, center, up) { + var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, + eyex = eye[0], + eyey = eye[1], + eyez = eye[2], + upx = up[0], + upy = up[1], + upz = up[2], + centerx = center[0], + centery = center[1], + centerz = center[2]; - var bounds = this.bounds - bounds[0] = bounds[1] = Infinity - bounds[2] = bounds[3] = -Infinity + if (Math.abs(eyex - centerx) < 0.000001 && + Math.abs(eyey - centery) < 0.000001 && + Math.abs(eyez - centerz) < 0.000001) { + return identity(out); + } - var numPoints = this.numPoints = data.length>>>1 - if(numPoints === 0) { - return - } + z0 = eyex - centerx; + z1 = eyey - centery; + z2 = eyez - centerz; - for(var i=0; i 1) { - var id = --ptr - var ax = data[2*ptr] - var ay = data[2*ptr+1] + out[0] = x0; + out[1] = y0; + out[2] = z0; + out[3] = 0; + out[4] = x1; + out[5] = y1; + out[6] = z1; + out[7] = 0; + out[8] = x2; + out[9] = y2; + out[10] = z2; + out[11] = 0; + out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); + out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); + out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); + out[15] = 1; - ax = (ax - bounds[0]) / (bounds[2] - bounds[0]) - ay = (ay - bounds[1]) / (bounds[3] - bounds[1]) + return out; +}; +},{"./identity":93}],96:[function(require,module,exports){ +module.exports = multiply; - var next = id-1 - var bx = data[2*next] - var by = data[2*next+1] +/** + * Multiplies two mat4's + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the first operand + * @param {mat4} b the second operand + * @returns {mat4} out + */ +function multiply(out, a, b) { + var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], + a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], + a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], + a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15]; - bx = (bx - bounds[0]) / (bounds[2] - bounds[0]) - by = (by - bounds[1]) / (bounds[3] - bounds[1]) + // Cache only the current line of the second matrix + var b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3]; + out[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - var dx = bx - ax - var dy = by - ay + b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; + out[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - var akey0 = id | (1<<24) - var akey1 = (id-1) - var bkey0 = id - var bkey1 = (id-1) | (1<<24) + b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; + out[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33; - lineData[--lineDataPtr] = -dy - lineData[--lineDataPtr] = -dx - lineData[--lineDataPtr] = ay - lineData[--lineDataPtr] = ax - pickData[--pickDataPtr] = akey0 - pickData[--pickDataPtr] = akey1 + b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; + out[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30; + out[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31; + out[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32; + out[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33; + return out; +}; +},{}],97:[function(require,module,exports){ +module.exports = perspective; - lineData[--lineDataPtr] = dy - lineData[--lineDataPtr] = dx - lineData[--lineDataPtr] = by - lineData[--lineDataPtr] = bx - pickData[--pickDataPtr] = bkey0 - pickData[--pickDataPtr] = bkey1 +/** + * Generates a perspective projection matrix with the given bounds + * + * @param {mat4} out mat4 frustum matrix will be written into + * @param {number} fovy Vertical field of view in radians + * @param {number} aspect Aspect ratio. typically viewport width/height + * @param {number} near Near bound of the frustum + * @param {number} far Far bound of the frustum + * @returns {mat4} out + */ +function perspective(out, fovy, aspect, near, far) { + var f = 1.0 / Math.tan(fovy / 2), + nf = 1 / (near - far); + out[0] = f / aspect; + out[1] = 0; + out[2] = 0; + out[3] = 0; + out[4] = 0; + out[5] = f; + out[6] = 0; + out[7] = 0; + out[8] = 0; + out[9] = 0; + out[10] = (far + near) * nf; + out[11] = -1; + out[12] = 0; + out[13] = 0; + out[14] = (2 * far * near) * nf; + out[15] = 0; + return out; +}; +},{}],98:[function(require,module,exports){ +module.exports = rotate; - lineData[--lineDataPtr] = -dy - lineData[--lineDataPtr] = -dx - lineData[--lineDataPtr] = by - lineData[--lineDataPtr] = bx - pickData[--pickDataPtr] = bkey0 - pickData[--pickDataPtr] = bkey1 +/** + * Rotates a mat4 by the given angle + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @param {vec3} axis the axis to rotate around + * @returns {mat4} out + */ +function rotate(out, a, rad, axis) { + var x = axis[0], y = axis[1], z = axis[2], + len = Math.sqrt(x * x + y * y + z * z), + s, c, t, + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23, + b00, b01, b02, + b10, b11, b12, + b20, b21, b22; - lineData[--lineDataPtr] = dy - lineData[--lineDataPtr] = dx - lineData[--lineDataPtr] = by - lineData[--lineDataPtr] = bx - pickData[--pickDataPtr] = bkey0 - pickData[--pickDataPtr] = bkey1 + if (Math.abs(len) < 0.000001) { return null; } + + len = 1 / len; + x *= len; + y *= len; + z *= len; - lineData[--lineDataPtr] = -dy - lineData[--lineDataPtr] = -dx - lineData[--lineDataPtr] = ay - lineData[--lineDataPtr] = ax - pickData[--pickDataPtr] = akey0 - pickData[--pickDataPtr] = akey1 + s = Math.sin(rad); + c = Math.cos(rad); + t = 1 - c; - lineData[--lineDataPtr] = dy - lineData[--lineDataPtr] = dx - lineData[--lineDataPtr] = ay - lineData[--lineDataPtr] = ax - pickData[--pickDataPtr] = akey0 - pickData[--pickDataPtr] = akey1 - } + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - this.lineBuffer.update(lineData) - this.pickBuffer.update(pickData) + // Construct the elements of the rotation matrix + b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; + b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; + b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; - pool.free(lineData) - pool.free(pickData) -} + // Perform rotation-specific matrix multiplication + out[0] = a00 * b00 + a10 * b01 + a20 * b02; + out[1] = a01 * b00 + a11 * b01 + a21 * b02; + out[2] = a02 * b00 + a12 * b01 + a22 * b02; + out[3] = a03 * b00 + a13 * b01 + a23 * b02; + out[4] = a00 * b10 + a10 * b11 + a20 * b12; + out[5] = a01 * b10 + a11 * b11 + a21 * b12; + out[6] = a02 * b10 + a12 * b11 + a22 * b12; + out[7] = a03 * b10 + a13 * b11 + a23 * b12; + out[8] = a00 * b20 + a10 * b21 + a20 * b22; + out[9] = a01 * b20 + a11 * b21 + a21 * b22; + out[10] = a02 * b20 + a12 * b21 + a22 * b22; + out[11] = a03 * b20 + a13 * b21 + a23 * b22; -proto.dispose = function() { - this.plot.removeObject(this) - this.lineBuffer.dispose() - this.pickBuffer.dispose() - this.lineShader.dispose() - this.mitreShader.dispose() - this.fillShader.dispose() - this.pickShader.dispose() - this.dashPattern.dispose() -} + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } + return out; +}; +},{}],99:[function(require,module,exports){ +module.exports = rotateX; -function createLinePlot(plot, options) { - var gl = plot.gl - var lineBuffer = createBuffer(gl) - var pickBuffer = createBuffer(gl) - var dashPattern = createTexture(gl, [1,1]) - var lineShader = createShader(gl, SHADERS.lineVertex, SHADERS.lineFragment) - var mitreShader = createShader(gl, SHADERS.mitreVertex, SHADERS.mitreFragment) - var fillShader = createShader(gl, SHADERS.fillVertex, SHADERS.fillFragment) - var pickShader = createShader(gl, SHADERS.pickVertex, SHADERS.pickFragment) - var linePlot = new GLLine2D( - plot, - dashPattern, - lineBuffer, - pickBuffer, - lineShader, - mitreShader, - fillShader, - pickShader) - plot.addObject(linePlot) - linePlot.update(options) - return linePlot -} +/** + * Rotates a matrix by the given angle around the X axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateX(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; -},{"./lib/shaders":137,"gl-buffer":139,"gl-shader":140,"gl-texture2d":164,"ndarray":987,"typedarray-pool":167}],139:[function(require,module,exports){ -arguments[4][75][0].apply(exports,arguments) -},{"dup":75,"ndarray":987,"ndarray-ops":982,"typedarray-pool":167}],140:[function(require,module,exports){ -arguments[4][76][0].apply(exports,arguments) -},{"./lib/GLError":141,"./lib/create-attributes":142,"./lib/create-uniforms":143,"./lib/reflect":144,"./lib/runtime-reflect":145,"./lib/shader-cache":146,"dup":76}],141:[function(require,module,exports){ -arguments[4][77][0].apply(exports,arguments) -},{"dup":77}],142:[function(require,module,exports){ -arguments[4][78][0].apply(exports,arguments) -},{"./GLError":141,"dup":78}],143:[function(require,module,exports){ -arguments[4][79][0].apply(exports,arguments) -},{"./GLError":141,"./reflect":144,"dup":79}],144:[function(require,module,exports){ -arguments[4][80][0].apply(exports,arguments) -},{"dup":80}],145:[function(require,module,exports){ -arguments[4][81][0].apply(exports,arguments) -},{"dup":81}],146:[function(require,module,exports){ -arguments[4][82][0].apply(exports,arguments) -},{"./GLError":141,"dup":82,"gl-format-compiler-error":147,"weakmap-shim":163}],147:[function(require,module,exports){ -arguments[4][83][0].apply(exports,arguments) -},{"add-line-numbers":148,"dup":83,"gl-constants/lookup":152,"glsl-shader-name":153,"sprintf-js":160}],148:[function(require,module,exports){ -arguments[4][84][0].apply(exports,arguments) -},{"dup":84,"pad-left":149}],149:[function(require,module,exports){ -arguments[4][85][0].apply(exports,arguments) -},{"dup":85,"repeat-string":150}],150:[function(require,module,exports){ -arguments[4][86][0].apply(exports,arguments) -},{"dup":86}],151:[function(require,module,exports){ -arguments[4][87][0].apply(exports,arguments) -},{"dup":87}],152:[function(require,module,exports){ -arguments[4][88][0].apply(exports,arguments) -},{"./1.0/numbers":151,"dup":88}],153:[function(require,module,exports){ -arguments[4][89][0].apply(exports,arguments) -},{"atob-lite":154,"dup":89,"glsl-tokenizer":159}],154:[function(require,module,exports){ -arguments[4][90][0].apply(exports,arguments) -},{"dup":90}],155:[function(require,module,exports){ -arguments[4][91][0].apply(exports,arguments) -},{"./lib/builtins":156,"./lib/literals":157,"./lib/operators":158,"dup":91}],156:[function(require,module,exports){ -arguments[4][92][0].apply(exports,arguments) -},{"dup":92}],157:[function(require,module,exports){ -arguments[4][93][0].apply(exports,arguments) -},{"dup":93}],158:[function(require,module,exports){ -arguments[4][94][0].apply(exports,arguments) -},{"dup":94}],159:[function(require,module,exports){ -arguments[4][95][0].apply(exports,arguments) -},{"./index":155,"dup":95}],160:[function(require,module,exports){ -arguments[4][96][0].apply(exports,arguments) -},{"dup":96}],161:[function(require,module,exports){ -arguments[4][97][0].apply(exports,arguments) -},{"./hidden-store.js":162,"dup":97}],162:[function(require,module,exports){ -arguments[4][98][0].apply(exports,arguments) -},{"dup":98}],163:[function(require,module,exports){ -arguments[4][99][0].apply(exports,arguments) -},{"./create-store.js":161,"dup":99}],164:[function(require,module,exports){ -'use strict' + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } -var ndarray = require('ndarray') -var ops = require('ndarray-ops') -var pool = require('typedarray-pool') + // Perform axis-specific matrix multiplication + out[4] = a10 * c + a20 * s; + out[5] = a11 * c + a21 * s; + out[6] = a12 * c + a22 * s; + out[7] = a13 * c + a23 * s; + out[8] = a20 * c - a10 * s; + out[9] = a21 * c - a11 * s; + out[10] = a22 * c - a12 * s; + out[11] = a23 * c - a13 * s; + return out; +}; +},{}],100:[function(require,module,exports){ +module.exports = rotateY; -module.exports = createTexture2D +/** + * Rotates a matrix by the given angle around the Y axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateY(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a20 = a[8], + a21 = a[9], + a22 = a[10], + a23 = a[11]; -var linearTypes = null -var filterTypes = null -var wrapTypes = null + if (a !== out) { // If the source and destination differ, copy the unchanged rows + out[4] = a[4]; + out[5] = a[5]; + out[6] = a[6]; + out[7] = a[7]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } -function lazyInitLinearTypes(gl) { - linearTypes = [ - gl.LINEAR, - gl.NEAREST_MIPMAP_LINEAR, - gl.LINEAR_MIPMAP_NEAREST, - gl.LINEAR_MIPMAP_NEAREST - ] - filterTypes = [ - gl.NEAREST, - gl.LINEAR, - gl.NEAREST_MIPMAP_NEAREST, - gl.NEAREST_MIPMAP_LINEAR, - gl.LINEAR_MIPMAP_NEAREST, - gl.LINEAR_MIPMAP_LINEAR - ] - wrapTypes = [ - gl.REPEAT, - gl.CLAMP_TO_EDGE, - gl.MIRRORED_REPEAT - ] -} + // Perform axis-specific matrix multiplication + out[0] = a00 * c - a20 * s; + out[1] = a01 * c - a21 * s; + out[2] = a02 * c - a22 * s; + out[3] = a03 * c - a23 * s; + out[8] = a00 * s + a20 * c; + out[9] = a01 * s + a21 * c; + out[10] = a02 * s + a22 * c; + out[11] = a03 * s + a23 * c; + return out; +}; +},{}],101:[function(require,module,exports){ +module.exports = rotateZ; -var convertFloatToUint8 = function(out, inp) { - ops.muls(out, inp, 255.0) -} +/** + * Rotates a matrix by the given angle around the Z axis + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to rotate + * @param {Number} rad the angle to rotate the matrix by + * @returns {mat4} out + */ +function rotateZ(out, a, rad) { + var s = Math.sin(rad), + c = Math.cos(rad), + a00 = a[0], + a01 = a[1], + a02 = a[2], + a03 = a[3], + a10 = a[4], + a11 = a[5], + a12 = a[6], + a13 = a[7]; -function reshapeTexture(tex, w, h) { - var gl = tex.gl - var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(w < 0 || w > maxSize || h < 0 || h > maxSize) { - throw new Error('gl-texture2d: Invalid texture size') - } - tex._shape = [w, h] - tex.bind() - gl.texImage2D(gl.TEXTURE_2D, 0, tex.format, w, h, 0, tex.format, tex.type, null) - tex._mipLevels = [0] - return tex -} + if (a !== out) { // If the source and destination differ, copy the unchanged last row + out[8] = a[8]; + out[9] = a[9]; + out[10] = a[10]; + out[11] = a[11]; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + } -function Texture2D(gl, handle, width, height, format, type) { - this.gl = gl - this.handle = handle - this.format = format - this.type = type - this._shape = [width, height] - this._mipLevels = [0] - this._magFilter = gl.NEAREST - this._minFilter = gl.NEAREST - this._wrapS = gl.CLAMP_TO_EDGE - this._wrapT = gl.CLAMP_TO_EDGE - this._anisoSamples = 1 + // Perform axis-specific matrix multiplication + out[0] = a00 * c + a10 * s; + out[1] = a01 * c + a11 * s; + out[2] = a02 * c + a12 * s; + out[3] = a03 * c + a13 * s; + out[4] = a10 * c - a00 * s; + out[5] = a11 * c - a01 * s; + out[6] = a12 * c - a02 * s; + out[7] = a13 * c - a03 * s; + return out; +}; +},{}],102:[function(require,module,exports){ +module.exports = scale; - var parent = this - var wrapVector = [this._wrapS, this._wrapT] - Object.defineProperties(wrapVector, [ - { - get: function() { - return parent._wrapS - }, - set: function(v) { - return parent.wrapS = v - } - }, - { - get: function() { - return parent._wrapT - }, - set: function(v) { - return parent.wrapT = v - } - } - ]) - this._wrapVector = wrapVector +/** + * Scales the mat4 by the dimensions in the given vec3 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to scale + * @param {vec3} v the vec3 to scale the matrix by + * @returns {mat4} out + **/ +function scale(out, a, v) { + var x = v[0], y = v[1], z = v[2]; - var shapeVector = [this._shape[0], this._shape[1]] - Object.defineProperties(shapeVector, [ - { - get: function() { - return parent._shape[0] - }, - set: function(v) { - return parent.width = v - } - }, - { - get: function() { - return parent._shape[1] - }, - set: function(v) { - return parent.height = v - } - } - ]) - this._shapeVector = shapeVector -} + out[0] = a[0] * x; + out[1] = a[1] * x; + out[2] = a[2] * x; + out[3] = a[3] * x; + out[4] = a[4] * y; + out[5] = a[5] * y; + out[6] = a[6] * y; + out[7] = a[7] * y; + out[8] = a[8] * z; + out[9] = a[9] * z; + out[10] = a[10] * z; + out[11] = a[11] * z; + out[12] = a[12]; + out[13] = a[13]; + out[14] = a[14]; + out[15] = a[15]; + return out; +}; +},{}],103:[function(require,module,exports){ +module.exports = translate; -var proto = Texture2D.prototype +/** + * Translate a mat4 by the given vector + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the matrix to translate + * @param {vec3} v vector to translate by + * @returns {mat4} out + */ +function translate(out, a, v) { + var x = v[0], y = v[1], z = v[2], + a00, a01, a02, a03, + a10, a11, a12, a13, + a20, a21, a22, a23; -Object.defineProperties(proto, { - minFilter: { - get: function() { - return this._minFilter - }, - set: function(v) { - this.bind() - var gl = this.gl - if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { - if(!gl.getExtension('OES_texture_float_linear')) { - v = gl.NEAREST - } - } - if(filterTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown filter mode ' + v) - } - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, v) - return this._minFilter = v - } - }, - magFilter: { - get: function() { - return this._magFilter - }, - set: function(v) { - this.bind() - var gl = this.gl - if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { - if(!gl.getExtension('OES_texture_float_linear')) { - v = gl.NEAREST - } - } - if(filterTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown filter mode ' + v) - } - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, v) - return this._magFilter = v - } - }, - mipSamples: { - get: function() { - return this._anisoSamples - }, - set: function(i) { - var psamples = this._anisoSamples - this._anisoSamples = Math.max(i, 1)|0 - if(psamples !== this._anisoSamples) { - var ext = gl.getExtension('EXT_texture_filter_anisotropic') - if(ext) { - this.gl.texParameterf(this.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisoSamples) - } - } - return this._anisoSamples - } - }, - wrapS: { - get: function() { - return this._wrapS - }, - set: function(v) { - this.bind() - if(wrapTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, v) - return this._wrapS = v - } - }, - wrapT: { - get: function() { - return this._wrapT - }, - set: function(v) { - this.bind() - if(wrapTypes.indexOf(v) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, v) - return this._wrapT = v - } - }, - wrap: { - get: function() { - return this._wrapVector - }, - set: function(v) { - if(!Array.isArray(v)) { - v = [v,v] - } - if(v.length !== 2) { - throw new Error('gl-texture2d: Must specify wrap mode for rows and columns') - } - for(var i=0; i<2; ++i) { - if(wrapTypes.indexOf(v[i]) < 0) { - throw new Error('gl-texture2d: Unknown wrap mode ' + v) - } - } - this._wrapS = v[0] - this._wrapT = v[1] + if (a === out) { + out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; + out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; + out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; + out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; + } else { + a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; + a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; + a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; - var gl = this.gl - this.bind() - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT) + out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; + out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; + out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; - return v - } - }, - shape: { - get: function() { - return this._shapeVector - }, - set: function(x) { - if(!Array.isArray(x)) { - x = [x|0,x|0] - } else { - if(x.length !== 2) { - throw new Error('gl-texture2d: Invalid texture shape') - } - } - reshapeTexture(this, x[0]|0, x[1]|0) - return [x[0]|0, x[1]|0] - } - }, - width: { - get: function() { - return this._shape[0] - }, - set: function(w) { - w = w|0 - reshapeTexture(this, w, this._shape[1]) - return w - } - }, - height: { - get: function() { - return this._shape[1] - }, - set: function(h) { - h = h|0 - reshapeTexture(this, this._shape[0], h) - return h + out[12] = a00 * x + a10 * y + a20 * z + a[12]; + out[13] = a01 * x + a11 * y + a21 * z + a[13]; + out[14] = a02 * x + a12 * y + a22 * z + a[14]; + out[15] = a03 * x + a13 * y + a23 * z + a[15]; } - } -}) -proto.bind = function(unit) { - var gl = this.gl - if(unit !== undefined) { - gl.activeTexture(gl.TEXTURE0 + (unit|0)) - } - gl.bindTexture(gl.TEXTURE_2D, this.handle) - if(unit !== undefined) { - return (unit|0) - } - return gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0 -} + return out; +}; +},{}],104:[function(require,module,exports){ +module.exports = transpose; -proto.dispose = function() { - this.gl.deleteTexture(this.handle) -} +/** + * Transpose the values of a mat4 + * + * @param {mat4} out the receiving matrix + * @param {mat4} a the source matrix + * @returns {mat4} out + */ +function transpose(out, a) { + // If we are transposing ourselves we can skip a few steps but have to cache some values + if (out === a) { + var a01 = a[1], a02 = a[2], a03 = a[3], + a12 = a[6], a13 = a[7], + a23 = a[11]; -proto.generateMipmap = function() { - this.bind() - this.gl.generateMipmap(this.gl.TEXTURE_2D) + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a01; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a02; + out[9] = a12; + out[11] = a[14]; + out[12] = a03; + out[13] = a13; + out[14] = a23; + } else { + out[0] = a[0]; + out[1] = a[4]; + out[2] = a[8]; + out[3] = a[12]; + out[4] = a[1]; + out[5] = a[5]; + out[6] = a[9]; + out[7] = a[13]; + out[8] = a[2]; + out[9] = a[6]; + out[10] = a[10]; + out[11] = a[14]; + out[12] = a[3]; + out[13] = a[7]; + out[14] = a[11]; + out[15] = a[15]; + } + + return out; +}; +},{}],105:[function(require,module,exports){ +'use strict' - //Update mip levels - var l = Math.min(this._shape[0], this._shape[1]) - for(var i=0; l>0; ++i, l>>>=1) { - if(this._mipLevels.indexOf(i) < 0) { - this._mipLevels.push(i) +var barycentric = require('barycentric') +var closestPointToTriangle = require('polytope-closest-point/lib/closest_point_2d.js') + +module.exports = closestPointToPickLocation + +function xformMatrix(m, v) { + var out = [0,0,0,0] + for(var i=0; i<4; ++i) { + for(var j=0; j<4; ++j) { + out[j] += m[4*i + j] * v[i] } } + return out } -proto.setPixels = function(data, x_off, y_off, mip_level) { - var gl = this.gl - this.bind() - if(Array.isArray(x_off)) { - mip_level = y_off - y_off = x_off[1]|0 - x_off = x_off[0]|0 - } else { - x_off = x_off || 0 - y_off = y_off || 0 +function projectVertex(v, model, view, projection, resolution) { + var p = xformMatrix(projection, + xformMatrix(view, + xformMatrix(model, [v[0], v[1], v[2], 1]))) + for(var i=0; i<3; ++i) { + p[i] /= p[3] } - mip_level = mip_level || 0 - if(data instanceof HTMLCanvasElement || - data instanceof ImageData || - data instanceof HTMLImageElement || - data instanceof HTMLVideoElement) { - var needsMip = this._mipLevels.indexOf(mip_level) < 0 - if(needsMip) { - gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, data) - this._mipLevels.push(mip_level) - } else { - gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, this.format, this.type, data) + return [ 0.5 * resolution[0] * (1.0+p[0]), 0.5 * resolution[1] * (1.0-p[1]) ] +} + +function barycentricCoord(simplex, point) { + if(simplex.length === 2) { + var d0 = 0.0 + var d1 = 0.0 + for(var i=0; i<2; ++i) { + d0 += Math.pow(point[i] - simplex[0][i], 2) + d1 += Math.pow(point[i] - simplex[1][i], 2) } - } else if(data.shape && data.stride && data.data) { - if(data.shape.length < 2 || - x_off + data.shape[1] > this._shape[1]>>>mip_level || - y_off + data.shape[0] > this._shape[0]>>>mip_level || - x_off < 0 || - y_off < 0) { - throw new Error('gl-texture2d: Texture dimensions are out of bounds') + d0 = Math.sqrt(d0) + d1 = Math.sqrt(d1) + if(d0+d1 < 1e-6) { + return [1,0] } - texSubImageArray(gl, x_off, y_off, mip_level, this.format, this.type, this._mipLevels, data) - } else { - throw new Error('gl-texture2d: Unsupported data type') + return [d1/(d0+d1),d0/(d1+d0)] + } else if(simplex.length === 3) { + var closestPoint = [0,0] + closestPointToTriangle(simplex[0], simplex[1], simplex[2], point, closestPoint) + return barycentric(simplex, closestPoint) } + return [] } - -function isPacked(shape, stride) { - if(shape.length === 3) { - return (stride[2] === 1) && - (stride[1] === shape[0]*shape[2]) && - (stride[0] === shape[2]) +function interpolate(simplex, weights) { + var result = [0,0,0] + for(var i=0; i 3) { - throw new Error('gl-texture2d: Invalid ndarray, must be 2d or 3d') - } - var type = 0, format = 0 - var packed = isPacked(shape, array.stride.slice()) - if(dtype === 'float32') { - type = gl.FLOAT - } else if(dtype === 'float64') { - type = gl.FLOAT - packed = false - dtype = 'float32' - } else if(dtype === 'uint8') { - type = gl.UNSIGNED_BYTE - } else { - type = gl.UNSIGNED_BYTE - packed = false - dtype = 'uint8' - } - var channels = 1 - if(shape.length === 2) { - format = gl.LUMINANCE - shape = [shape[0], shape[1], 1] - array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) - } else if(shape.length === 3) { - if(shape[2] === 1) { - format = gl.ALPHA - } else if(shape[2] === 2) { - format = gl.LUMINANCE_ALPHA - } else if(shape[2] === 3) { - format = gl.RGB - } else if(shape[2] === 4) { - format = gl.RGBA - } else { - throw new Error('gl-texture2d: Invalid shape for pixel coords') - } - channels = shape[2] - } else { - throw new Error('gl-texture2d: Invalid shape for texture') - } - //For 1-channel textures allow conversion between formats - if((format === gl.LUMINANCE || format === gl.ALPHA) && - (cformat === gl.LUMINANCE || cformat === gl.ALPHA)) { - format = cformat - } - if(format !== cformat) { - throw new Error('gl-texture2d: Incompatible texture format for setPixels') +function closestPointToPickLocation(simplex, pixelCoord, model, view, projection, resolution) { + if(simplex.length === 1) { + return [0, simplex[0].slice()] } - var size = array.size - var needsMip = mipLevels.indexOf(mip_level) < 0 - if(needsMip) { - mipLevels.push(mip_level) + var simplex2D = new Array(simplex.length) + for(var i=0; i 1.0001) { + return null } + s += weights[i] } + if(Math.abs(s - 1.0) > 0.001) { + return null + } + return [closestIndex, interpolate(simplex, weights), weights] +} +},{"barycentric":108,"polytope-closest-point/lib/closest_point_2d.js":110}],106:[function(require,module,exports){ + + +var triVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position, normal;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec4 m_position = model * vec4(position, 1.0);\n vec4 t_position = view * m_position;\n gl_Position = projection * t_position;\n f_color = color;\n f_normal = normal;\n f_data = position;\n f_eyeDirection = eyePosition - position;\n f_lightDirection = lightPosition - position;\n f_uv = uv;\n}" +var triFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nfloat beckmannDistribution_2_0(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\n\n\nfloat cookTorranceSpecular_1_1(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution_2_0(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\n\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(f_data, clipBounds[0])) || \n any(greaterThan(f_data, clipBounds[1]))) {\n discard;\n }\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n \n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular_1_1(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}" +var edgeVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}" +var edgeFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(f_data, clipBounds[0])) || \n any(greaterThan(f_data, clipBounds[1]))) {\n discard;\n }\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}" +var pointVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || \n any(greaterThan(position, clipBounds[1]))) {\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}" +var pointFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5,0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}" +var pickVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}" +var pickFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if(any(lessThan(f_position, clipBounds[0])) || \n any(greaterThan(f_position, clipBounds[1]))) {\n discard;\n }\n gl_FragColor = vec4(pickId, f_id.xyz);\n}" +var pickPointVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || \n any(greaterThan(position, clipBounds[1]))) {\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}" +var contourVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}" +var contourFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor,1);\n}\n" + +exports.meshShader = { + vertex: triVertSrc, + fragment: triFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'normal', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'} + ] +} +exports.wireShader = { + vertex: edgeVertSrc, + fragment: edgeFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'} + ] +} +exports.pointShader = { + vertex: pointVertSrc, + fragment: pointFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'uv', type: 'vec2'}, + {name: 'pointSize', type: 'float'} + ] +} +exports.pickShader = { + vertex: pickVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'id', type: 'vec4'} + ] +} +exports.pointPickShader = { + vertex: pickPointVertSrc, + fragment: pickFragSrc, + attributes: [ + {name: 'position', type: 'vec3'}, + {name: 'pointSize', type: 'float'}, + {name: 'id', type: 'vec4'} + ] +} +exports.contourShader = { + vertex: contourVertSrc, + fragment: contourFragSrc, + attributes: [ + {name: 'position', type: 'vec3'} + ] +} + +},{}],107:[function(require,module,exports){ +'use strict' + +var createShader = require('gl-shader') +var createBuffer = require('gl-buffer') +var createVAO = require('gl-vao') +var createTexture = require('gl-texture2d') +var normals = require('normals') +var multiply = require('gl-mat4/multiply') +var invert = require('gl-mat4/invert') +var ndarray = require('ndarray') +var colormap = require('colormap') +var getContour = require('simplicial-complex-contour') +var pool = require('typedarray-pool') +var shaders = require('./lib/shaders') +var closestPoint = require('./lib/closest-point') + +var meshShader = shaders.meshShader +var wireShader = shaders.wireShader +var pointShader = shaders.pointShader +var pickShader = shaders.pickShader +var pointPickShader = shaders.pointPickShader +var contourShader = shaders.contourShader + +var identityMatrix = [ + 1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] + +function SimplicialMesh(gl + , texture + , triShader + , lineShader + , pointShader + , pickShader + , pointPickShader + , contourShader + , trianglePositions + , triangleIds + , triangleColors + , triangleUVs + , triangleNormals + , triangleVAO + , edgePositions + , edgeIds + , edgeColors + , edgeUVs + , edgeVAO + , pointPositions + , pointIds + , pointColors + , pointUVs + , pointSizes + , pointVAO + , contourPositions + , contourVAO) { + + this.gl = gl + this.cells = [] + this.positions = [] + this.intensity = [] + this.texture = texture + this.dirty = true + + this.triShader = triShader + this.lineShader = lineShader + this.pointShader = pointShader + this.pickShader = pickShader + this.pointPickShader = pointPickShader + this.contourShader = contourShader + + this.trianglePositions = trianglePositions + this.triangleColors = triangleColors + this.triangleNormals = triangleNormals + this.triangleUVs = triangleUVs + this.triangleIds = triangleIds + this.triangleVAO = triangleVAO + this.triangleCount = 0 + + this.lineWidth = 1 + this.edgePositions = edgePositions + this.edgeColors = edgeColors + this.edgeUVs = edgeUVs + this.edgeIds = edgeIds + this.edgeVAO = edgeVAO + this.edgeCount = 0 + + this.pointPositions = pointPositions + this.pointColors = pointColors + this.pointUVs = pointUVs + this.pointSizes = pointSizes + this.pointIds = pointIds + this.pointVAO = pointVAO + this.pointCount = 0 + + this.contourLineWidth = 1 + this.contourPositions = contourPositions + this.contourVAO = contourVAO + this.contourCount = 0 + this.contourColor = [0,0,0] + this.contourEnable = true + + this.pickId = 1 + this.bounds = [ + [ Infinity, Infinity, Infinity], + [-Infinity,-Infinity,-Infinity] ] + this.clipBounds = [ + [-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity] ] + + this.lightPosition = [1e5, 1e5, 0] + this.ambientLight = 0.8 + this.diffuseLight = 0.8 + this.specularLight = 2.0 + this.roughness = 0.5 + this.fresnel = 1.5 + + this.opacity = 1.0 + + this._model = identityMatrix + this._view = identityMatrix + this._projection = identityMatrix + this._resolution = [1,1] } -function initTexture(gl) { - var tex = gl.createTexture() - gl.bindTexture(gl.TEXTURE_2D, tex) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - return tex +var proto = SimplicialMesh.prototype + +proto.isOpaque = function() { + return this.opacity >= 1 } -function createTextureShape(gl, width, height, format, type) { - var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(width < 0 || width > maxTextureSize || height < 0 || height > maxTextureSize) { - throw new Error('gl-texture2d: Invalid texture shape') - } - if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { - throw new Error('gl-texture2d: Floating point textures not supported on this platform') - } - var tex = initTexture(gl) - gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null) - return new Texture2D(gl, tex, width, height, format, type) +proto.isTransparent = function() { + return this.opacity < 1 } -function createTextureDOM(gl, element, format, type) { - var tex = initTexture(gl) - gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, element) - return new Texture2D(gl, tex, element.width|0, element.height|0, format, type) +proto.pickSlots = 1 + +proto.setPickBase = function(id) { + this.pickId = id } -//Creates a texture from an ndarray -function createTextureArray(gl, array) { - var dtype = array.dtype - var shape = array.shape.slice() - var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) - if(shape[0] < 0 || shape[0] > maxSize || shape[1] < 0 || shape[1] > maxSize) { - throw new Error('gl-texture2d: Invalid texture size') - } - var packed = isPacked(shape, array.stride.slice()) - var type = 0 - if(dtype === 'float32') { - type = gl.FLOAT - } else if(dtype === 'float64') { - type = gl.FLOAT - packed = false - dtype = 'float32' - } else if(dtype === 'uint8') { - type = gl.UNSIGNED_BYTE - } else { - type = gl.UNSIGNED_BYTE - packed = false - dtype = 'uint8' - } - var format = 0 - if(shape.length === 2) { - format = gl.LUMINANCE - shape = [shape[0], shape[1], 1] - array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) - } else if(shape.length === 3) { - if(shape[2] === 1) { - format = gl.ALPHA - } else if(shape[2] === 2) { - format = gl.LUMINANCE_ALPHA - } else if(shape[2] === 3) { - format = gl.RGB - } else if(shape[2] === 4) { - format = gl.RGBA - } else { - throw new Error('gl-texture2d: Invalid shape for pixel coords') +function genColormap(param) { + var colors = colormap({ + colormap: param + , nshades: 256 + , format: 'rgba' + }) + + var result = new Uint8Array(256*4) + for(var i=0; i<256; ++i) { + var c = colors[i] + for(var j=0; j<3; ++j) { + result[4*i+j] = c[j] } - } else { - throw new Error('gl-texture2d: Invalid shape for texture') + result[4*i+3] = c[3]*255 } - if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { - type = gl.UNSIGNED_BYTE - packed = false + + return ndarray(result, [256,256,4], [4,0,1]) +} + +function unpackIntensity(cells, numVerts, cellIntensity) { + var result = new Array(numVerts) + for(var i=0; i= 1 -} + pPos.push(p[0], p[1], p[2]) -proto.pickSlots = 1 + var c + if(vertexColors) { + c = vertexColors[v] + } else if(cellColors) { + c = cellColors[i] + } else { + c = meshColor + } + if(c.length === 3) { + pCol.push(c[0], c[1], c[2], 1) + } else { + pCol.push(c[0], c[1], c[2], c[3]) + } -proto.setPickBase = function(id) { - this.pickId = id -} + var uv + if(vertexUVs) { + uv = vertexUVs[v] + } else if(vertexIntensity) { + uv = [ + (vertexIntensity[v] - intensityLo) / + (intensityHi - intensityLo), 0] + } else if(cellUVs) { + uv = cellUVs[i] + } else if(cellIntensity) { + uv = [ + (cellIntensity[i] - intensityLo) / + (intensityHi - intensityLo), 0] + } else { + uv = [ + (p[2] - intensityLo) / + (intensityHi - intensityLo), 0] + } + pUVs.push(uv[0], uv[1]) -proto.drawTransparent = proto.draw = function(camera) { - var gl = this.gl - var shader = this.shader - var vao = this.vao - shader.bind() - shader.uniforms = { - model: camera.model || identity, - view: camera.view || identity, - projection: camera.projection || identity, - clipBounds: filterClipBounds(this.clipBounds), - dashTexture: this.texture.bind(), - dashScale: this.dashScale / this.arcLength[this.arcLength.length-1], - opacity: this.opacity, - screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], - pixelRatio: this.pixelRatio - } - vao.bind() - vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) -} + if(pointSizes) { + pSiz.push(pointSizes[v]) + } else { + pSiz.push(meshPointSize) + } -proto.drawPick = function(camera) { - var gl = this.gl - var shader = this.pickShader - var vao = this.vao - shader.bind() - shader.uniforms = { - model: camera.model || identity, - view: camera.view || identity, - projection: camera.projection || identity, - pickId: this.pickId, - clipBounds: filterClipBounds(this.clipBounds), - screenShape: [gl.drawingBufferWidth, gl.drawingBufferHeight], - pixelRatio: this.pixelRatio - } - vao.bind() - vao.draw(gl.TRIANGLE_STRIP, this.vertexCount) -} + pIds.push(i) + + pointCount += 1 + break + + case 2: + + //Check NaNs + for(var j=0; j<2; ++j) { + var v = cell[j] + var p = positions[v] + for(var k=0; k<3; ++k) { + if(isNaN(p[k]) || !isFinite(p[k])) { + continue fill_loop + } + } + } + + for(var j=0; j<2; ++j) { + var v = cell[j] + var p = positions[v] + + ePos.push(p[0], p[1], p[2]) + + var c + if(vertexColors) { + c = vertexColors[v] + } else if(cellColors) { + c = cellColors[i] + } else { + c = meshColor + } + if(c.length === 3) { + eCol.push(c[0], c[1], c[2], 1) + } else { + eCol.push(c[0], c[1], c[2], c[3]) + } -proto.update = function(options) { - this.dirty = true + var uv + if(vertexUVs) { + uv = vertexUVs[v] + } else if(vertexIntensity) { + uv = [ + (vertexIntensity[v] - intensityLo) / + (intensityHi - intensityLo), 0] + } else if(cellUVs) { + uv = cellUVs[i] + } else if(cellIntensity) { + uv = [ + (cellIntensity[i] - intensityLo) / + (intensityHi - intensityLo), 0] + } else { + uv = [ + (p[2] - intensityLo) / + (intensityHi - intensityLo), 0] + } + eUVs.push(uv[0], uv[1]) - if('dashScale' in options) { - this.dashScale = options.dashScale - } - if('opacity' in options) { - this.opacity = +options.opacity - } + eIds.push(i) + } + edgeCount += 1 + break - var positions = options.position || options.positions - if(!positions) { - return - } + case 3: + //Check NaNs + for(var j=0; j<3; ++j) { + var v = cell[j] + var p = positions[v] + for(var k=0; k<3; ++k) { + if(isNaN(p[k]) || !isFinite(p[k])) { + continue fill_loop + } + } + } - //Default color - var colors = options.color || options.colors || [0,0,0,1] + for(var j=0; j<3; ++j) { + var v = cell[j] - var lineWidth = options.lineWidth || 1 + var p = positions[v] + tPos.push(p[0], p[1], p[2]) - //Recalculate buffer data - var buffer = [] - var arcLengthArray = [] - var pointArray = [] - var arcLength = 0.0 - var vertexCount = 0 - var bounds = [[ Infinity, Infinity, Infinity], - [-Infinity,-Infinity,-Infinity]] + var c + if(vertexColors) { + c = vertexColors[v] + } else if(cellColors) { + c = cellColors[i] + } else { + c = meshColor + } + if(c.length === 3) { + tCol.push(c[0], c[1], c[2], 1) + } else { + tCol.push(c[0], c[1], c[2], c[3]) + } -fill_loop: - for(var i=1; i 0) { + var shader = this.triShader + shader.bind() + shader.uniforms = uniforms - var pickShader = createPickShader(gl) - pickShader.attributes.position.location = 0 - pickShader.attributes.nextPosition.location = 1 - pickShader.attributes.arcLength.location = 2 - pickShader.attributes.lineWidth.location = 3 - pickShader.attributes.color.location = 4 + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } - var buffer = createBuffer(gl) - var vao = createVAO(gl, [ - { - 'buffer': buffer, - 'size': 3, - 'offset': 0, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 3, - 'offset': 12, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 1, - 'offset': 24, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 1, - 'offset': 28, - 'stride': 48 - }, - { - 'buffer': buffer, - 'size': 4, - 'offset': 32, - 'stride': 48 - } - ]) + if(this.edgeCount > 0 && this.lineWidth > 0) { + var shader = this.lineShader + shader.bind() + shader.uniforms = uniforms - //Create texture for dash pattern - var defaultTexture = ndarray(new Array(256*4), [256,1,4]) - for(var i=0; i<256*4; ++i) { - defaultTexture.data[i] = 255 + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() } - var texture = createTexture(gl, defaultTexture) - texture.wrap = gl.REPEAT - var linePlot = new LinePlot(gl, shader, pickShader, buffer, vao, texture) - linePlot.update(options) - return linePlot -} + if(this.pointCount > 0) { + var shader = this.pointShader + shader.bind() + shader.uniforms = uniforms -},{"./lib/shaders":168,"binary-search-bounds":170,"gl-buffer":171,"gl-texture2d":202,"gl-vao":206,"glsl-read-float":207,"ndarray":987}],170:[function(require,module,exports){ -arguments[4][4][0].apply(exports,arguments) -},{"dup":4}],171:[function(require,module,exports){ -arguments[4][75][0].apply(exports,arguments) -},{"dup":75,"ndarray":987,"ndarray-ops":982,"typedarray-pool":174}],172:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],173:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],174:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":172,"buffer":48,"dup":102}],175:[function(require,module,exports){ -arguments[4][76][0].apply(exports,arguments) -},{"./lib/GLError":176,"./lib/create-attributes":177,"./lib/create-uniforms":178,"./lib/reflect":179,"./lib/runtime-reflect":180,"./lib/shader-cache":181,"dup":76}],176:[function(require,module,exports){ -arguments[4][77][0].apply(exports,arguments) -},{"dup":77}],177:[function(require,module,exports){ -arguments[4][78][0].apply(exports,arguments) -},{"./GLError":176,"dup":78}],178:[function(require,module,exports){ -arguments[4][79][0].apply(exports,arguments) -},{"./GLError":176,"./reflect":179,"dup":79}],179:[function(require,module,exports){ -arguments[4][80][0].apply(exports,arguments) -},{"dup":80}],180:[function(require,module,exports){ -arguments[4][81][0].apply(exports,arguments) -},{"dup":81}],181:[function(require,module,exports){ -arguments[4][82][0].apply(exports,arguments) -},{"./GLError":176,"dup":82,"gl-format-compiler-error":182,"weakmap-shim":198}],182:[function(require,module,exports){ -arguments[4][83][0].apply(exports,arguments) -},{"add-line-numbers":183,"dup":83,"gl-constants/lookup":187,"glsl-shader-name":188,"sprintf-js":195}],183:[function(require,module,exports){ -arguments[4][84][0].apply(exports,arguments) -},{"dup":84,"pad-left":184}],184:[function(require,module,exports){ -arguments[4][85][0].apply(exports,arguments) -},{"dup":85,"repeat-string":185}],185:[function(require,module,exports){ -arguments[4][86][0].apply(exports,arguments) -},{"dup":86}],186:[function(require,module,exports){ -arguments[4][87][0].apply(exports,arguments) -},{"dup":87}],187:[function(require,module,exports){ -arguments[4][88][0].apply(exports,arguments) -},{"./1.0/numbers":186,"dup":88}],188:[function(require,module,exports){ -arguments[4][89][0].apply(exports,arguments) -},{"atob-lite":189,"dup":89,"glsl-tokenizer":194}],189:[function(require,module,exports){ -arguments[4][90][0].apply(exports,arguments) -},{"dup":90}],190:[function(require,module,exports){ -arguments[4][91][0].apply(exports,arguments) -},{"./lib/builtins":191,"./lib/literals":192,"./lib/operators":193,"dup":91}],191:[function(require,module,exports){ -arguments[4][92][0].apply(exports,arguments) -},{"dup":92}],192:[function(require,module,exports){ -arguments[4][93][0].apply(exports,arguments) -},{"dup":93}],193:[function(require,module,exports){ -arguments[4][94][0].apply(exports,arguments) -},{"dup":94}],194:[function(require,module,exports){ -arguments[4][95][0].apply(exports,arguments) -},{"./index":190,"dup":95}],195:[function(require,module,exports){ -arguments[4][96][0].apply(exports,arguments) -},{"dup":96}],196:[function(require,module,exports){ -arguments[4][97][0].apply(exports,arguments) -},{"./hidden-store.js":197,"dup":97}],197:[function(require,module,exports){ -arguments[4][98][0].apply(exports,arguments) -},{"dup":98}],198:[function(require,module,exports){ -arguments[4][99][0].apply(exports,arguments) -},{"./create-store.js":196,"dup":99}],199:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],200:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],201:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":199,"buffer":48,"dup":102}],202:[function(require,module,exports){ -arguments[4][164][0].apply(exports,arguments) -},{"dup":164,"ndarray":987,"ndarray-ops":982,"typedarray-pool":201}],203:[function(require,module,exports){ -arguments[4][132][0].apply(exports,arguments) -},{"dup":132}],204:[function(require,module,exports){ -arguments[4][133][0].apply(exports,arguments) -},{"./do-bind.js":203,"dup":133}],205:[function(require,module,exports){ -arguments[4][134][0].apply(exports,arguments) -},{"./do-bind.js":203,"dup":134}],206:[function(require,module,exports){ -arguments[4][135][0].apply(exports,arguments) -},{"./lib/vao-emulated.js":204,"./lib/vao-native.js":205,"dup":135}],207:[function(require,module,exports){ -module.exports = decodeFloat + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } -var UINT8_VIEW = new Uint8Array(4) -var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer) + if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { + var shader = this.contourShader + shader.bind() + shader.uniforms = uniforms -function decodeFloat(x, y, z, w) { - UINT8_VIEW[0] = w - UINT8_VIEW[1] = z - UINT8_VIEW[2] = y - UINT8_VIEW[3] = x - return FLOAT_VIEW[0] + this.contourVAO.bind() + gl.drawArrays(gl.LINES, 0, this.contourCount) + this.contourVAO.unbind() + } } -},{}],208:[function(require,module,exports){ -module.exports = clone; +proto.drawPick = function(params) { + params = params || {} -/** - * Creates a new mat4 initialized with values from an existing matrix - * - * @param {mat4} a matrix to clone - * @returns {mat4} a new 4x4 matrix - */ -function clone(a) { - var out = new Float32Array(16); - out[0] = a[0]; - out[1] = a[1]; - out[2] = a[2]; - out[3] = a[3]; - out[4] = a[4]; - out[5] = a[5]; - out[6] = a[6]; - out[7] = a[7]; - out[8] = a[8]; - out[9] = a[9]; - out[10] = a[10]; - out[11] = a[11]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; - return out; -}; -},{}],209:[function(require,module,exports){ -module.exports = create; + var gl = this.gl -/** - * Creates a new identity mat4 - * - * @returns {mat4} a new 4x4 matrix - */ -function create() { - var out = new Float32Array(16); - out[0] = 1; - out[1] = 0; - out[2] = 0; - out[3] = 0; - out[4] = 0; - out[5] = 1; - out[6] = 0; - out[7] = 0; - out[8] = 0; - out[9] = 0; - out[10] = 1; - out[11] = 0; - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; - return out; -}; -},{}],210:[function(require,module,exports){ -module.exports = determinant; + var model = params.model || identityMatrix + var view = params.view || identityMatrix + var projection = params.projection || identityMatrix -/** - * Calculates the determinant of a mat4 - * - * @param {mat4} a the source matrix - * @returns {Number} determinant of a - */ -function determinant(a) { - var a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], - a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], - a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], - a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], + var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] + for(var i=0; i<3; ++i) { + clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) + clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) + } - b00 = a00 * a11 - a01 * a10, - b01 = a00 * a12 - a02 * a10, - b02 = a00 * a13 - a03 * a10, - b03 = a01 * a12 - a02 * a11, - b04 = a01 * a13 - a03 * a11, - b05 = a02 * a13 - a03 * a12, - b06 = a20 * a31 - a21 * a30, - b07 = a20 * a32 - a22 * a30, - b08 = a20 * a33 - a23 * a30, - b09 = a21 * a32 - a22 * a31, - b10 = a21 * a33 - a23 * a31, - b11 = a22 * a33 - a23 * a32; + //Save camera parameters + this._model = [].slice.call(model) + this._view = [].slice.call(view) + this._projection = [].slice.call(projection) + this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] - // Calculate the determinant - return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; -}; -},{}],211:[function(require,module,exports){ -module.exports = fromQuat; + var uniforms = { + model: model, + view: view, + projection: projection, + clipBounds: clipBounds, + pickId: this.pickId / 255.0, + } -/** - * Creates a matrix from a quaternion rotation. - * - * @param {mat4} out mat4 receiving operation result - * @param {quat4} q Rotation quaternion - * @returns {mat4} out - */ -function fromQuat(out, q) { - var x = q[0], y = q[1], z = q[2], w = q[3], - x2 = x + x, - y2 = y + y, - z2 = z + z, + var shader = this.pickShader + shader.bind() + shader.uniforms = uniforms + + if(this.triangleCount > 0) { + this.triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) + this.triangleVAO.unbind() + } + + if(this.edgeCount > 0) { + this.edgeVAO.bind() + gl.lineWidth(this.lineWidth) + gl.drawArrays(gl.LINES, 0, this.edgeCount*2) + this.edgeVAO.unbind() + } - xx = x * x2, - yx = y * x2, - yy = y * y2, - zx = z * x2, - zy = z * y2, - zz = z * z2, - wx = w * x2, - wy = w * y2, - wz = w * z2; + if(this.pointCount > 0) { + var shader = this.pointPickShader + shader.bind() + shader.uniforms = uniforms - out[0] = 1 - yy - zz; - out[1] = yx + wz; - out[2] = zx - wy; - out[3] = 0; + this.pointVAO.bind() + gl.drawArrays(gl.POINTS, 0, this.pointCount) + this.pointVAO.unbind() + } +} - out[4] = yx - wz; - out[5] = 1 - xx - zz; - out[6] = zy + wx; - out[7] = 0; - out[8] = zx + wy; - out[9] = zy - wx; - out[10] = 1 - xx - yy; - out[11] = 0; +proto.pick = function(pickData) { + if(!pickData) { + return null + } + if(pickData.id !== this.pickId) { + return null + } - out[12] = 0; - out[13] = 0; - out[14] = 0; - out[15] = 1; + var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] + var cell = this.cells[cellId] + var positions = this.positions - return out; -}; -},{}],212:[function(require,module,exports){ -module.exports = fromRotationTranslation; + var simplex = new Array(cell.length) + for(var i=0; i EPSILON) { + var norm = normals[c]; + var w = 1.0 / Math.sqrt(m01 * m21); + for(var k=0; k<3; ++k) { + var u = (k+1)%3; + var v = (k+2)%3; + norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]); + } + } + } + } + + //Scale all normals to unit length + for(var i=0; i EPSILON) { + var w = 1.0 / Math.sqrt(m); + for(var k=0; k<3; ++k) { + norm[k] *= w; + } + } else { + for(var k=0; k<3; ++k) { + norm[k] = 0.0; + } + } + } - if (a !== out) { // If the source and destination differ, copy the unchanged rows - out[4] = a[4]; - out[5] = a[5]; - out[6] = a[6]; - out[7] = a[7]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; + //Return the resulting set of patches + return normals; +} + +//Compute face normals of a mesh +exports.faceNormals = function(faces, positions) { + var N = faces.length; + var normals = new Array(N); + + for(var i=0; i EPSILON) { + l = 1.0 / Math.sqrt(l); + } else { + l = 0.0; + } + for(var j=0; j<3; ++j) { + n[j] *= l; } + normals[i] = n; + } + return normals; +} - // Perform axis-specific matrix multiplication - out[0] = a00 * c - a20 * s; - out[1] = a01 * c - a21 * s; - out[2] = a02 * c - a22 * s; - out[3] = a03 * c - a23 * s; - out[8] = a00 * s + a20 * c; - out[9] = a01 * s + a21 * c; - out[10] = a02 * s + a22 * c; - out[11] = a03 * s + a23 * c; - return out; -}; -},{}],221:[function(require,module,exports){ -module.exports = rotateZ; -/** - * Rotates a matrix by the given angle around the Z axis - * - * @param {mat4} out the receiving matrix - * @param {mat4} a the matrix to rotate - * @param {Number} rad the angle to rotate the matrix by - * @returns {mat4} out - */ -function rotateZ(out, a, rad) { - var s = Math.sin(rad), - c = Math.cos(rad), - a00 = a[0], - a01 = a[1], - a02 = a[2], - a03 = a[3], - a10 = a[4], - a11 = a[5], - a12 = a[6], - a13 = a[7]; - if (a !== out) { // If the source and destination differ, copy the unchanged last row - out[8] = a[8]; - out[9] = a[9]; - out[10] = a[10]; - out[11] = a[11]; - out[12] = a[12]; - out[13] = a[13]; - out[14] = a[14]; - out[15] = a[15]; +},{}],110:[function(require,module,exports){ +//Optimized version for triangle closest point +// Based on Eberly's WildMagick codes +// http://www.geometrictools.com/LibMathematics/Distance/Distance.html +"use strict"; + +var diff = new Float64Array(4); +var edge0 = new Float64Array(4); +var edge1 = new Float64Array(4); + +function closestPoint2d(V0, V1, V2, point, result) { + //Reallocate buffers if necessary + if(diff.length < point.length) { + diff = new Float64Array(point.length); + edge0 = new Float64Array(point.length); + edge1 = new Float64Array(point.length); + } + //Compute edges + for(var i=0; i= a00) { + s = 1.0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } else { + s = 0; + if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else if (-b1 >= a11) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else { // region 3 + s = 0; + if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else if (-b1 >= a11) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else if (t < 0) { // region 5 + t = 0; + if (b0 >= 0) { + s = 0; + sqrDistance = c; + } else if (-b0 >= a00) { + s = 1; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } else { // region 0 + // minimum at interior point + var invDet = 1.0 / det; + s *= invDet; + t *= invDet; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + var tmp0, tmp1, numer, denom; + + if (s < 0) { // region 2 + tmp0 = a01 + b0; + tmp1 = a11 + b1; + if (tmp1 > tmp0) { + numer = tmp1 - tmp0; + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + s = 1; + t = 0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = numer/denom; + t = 1 - s; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + s = 0; + if (tmp1 <= 0) { + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else if (b1 >= 0) { + t = 0; + sqrDistance = c; + } else { + t = -b1/a11; + sqrDistance = b1*t + c; + } + } + } else if (t < 0) { // region 6 + tmp0 = a01 + b1; + tmp1 = a00 + b0; + if (tmp1 > tmp0) { + numer = tmp1 - tmp0; + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + t = 1; + s = 0; + sqrDistance = a11 + 2.0*b1 + c; + } else { + t = numer/denom; + s = 1 - t; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } else { + t = 0; + if (tmp1 <= 0) { + s = 1; + sqrDistance = a00 + 2.0*b0 + c; + } else if (b0 >= 0) { + s = 0; + sqrDistance = c; + } else { + s = -b0/a00; + sqrDistance = b0*s + c; + } + } + } else { // region 1 + numer = a11 + b1 - a01 - b0; + if (numer <= 0) { + s = 0; + t = 1; + sqrDistance = a11 + 2.0*b1 + c; + } else { + denom = a00 - 2.0*a01 + a11; + if (numer >= denom) { + s = 1; + t = 0; + sqrDistance = a00 + 2.0*b0 + c; + } else { + s = numer/denom; + t = 1 - s; + sqrDistance = s*(a00*s + a01*t + 2.0*b0) + + t*(a01*s + a11*t + 2.0*b1) + c; + } + } } + } + var u = 1.0 - s - t; + for(var i=0; i 1.0001) { - return null + //Count number of cells + var numCells = cells.length + if(numCells === 0 || d < 1) { + return { + cells: [], + vertexIds: [], + vertexWeights: [] } - s += weights[i] - } - if(Math.abs(s - 1.0) > 0.001) { - return null } - return [closestIndex, interpolate(simplex, weights), weights] -} -},{"barycentric":228,"polytope-closest-point/lib/closest_point_2d.js":269}],226:[function(require,module,exports){ + //Read in vertex signs + var vertexSigns = getSigns(values, +level) -var triVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position, normal;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model\n , view\n , projection;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec4 m_position = model * vec4(position, 1.0);\n vec4 t_position = view * m_position;\n gl_Position = projection * t_position;\n f_color = color;\n f_normal = normal;\n f_data = position;\n f_eyeDirection = eyePosition - position;\n f_lightDirection = lightPosition - position;\n f_uv = uv;\n}" -var triFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nfloat beckmannDistribution_2_0(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\n\n\nfloat cookTorranceSpecular_1_1(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution_2_0(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\n\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular\n , opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(f_data, clipBounds[0])) || \n any(greaterThan(f_data, clipBounds[1]))) {\n discard;\n }\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n \n if(!gl_FrontFacing) {\n N = -N;\n }\n\n float specular = cookTorranceSpecular_1_1(L, V, N, roughness, fresnel);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}" -var edgeVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}" -var edgeFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(f_data, clipBounds[0])) || \n any(greaterThan(f_data, clipBounds[1]))) {\n discard;\n }\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}" -var pointVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || \n any(greaterThan(position, clipBounds[1]))) {\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}" -var pointFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5,0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}" -var pickVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}" -var pickFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if(any(lessThan(f_position, clipBounds[0])) || \n any(greaterThan(f_position, clipBounds[1]))) {\n discard;\n }\n gl_FragColor = vec4(pickId, f_id.xyz);\n}" -var pickPointVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || \n any(greaterThan(position, clipBounds[1]))) {\n gl_Position = vec4(0,0,0,0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}" -var contourVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}" -var contourFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor,1);\n}\n" + //First get 1-skeleton, find all crossings + var edges = getEdges(cells, d) + var weights = getCrossingWeights(edges, values, vertexSigns, +level) -exports.meshShader = { - vertex: triVertSrc, - fragment: triFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'normal', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'} - ] -} -exports.wireShader = { - vertex: edgeVertSrc, - fragment: edgeFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'} - ] -} -exports.pointShader = { - vertex: pointVertSrc, - fragment: pointFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'color', type: 'vec4'}, - {name: 'uv', type: 'vec2'}, - {name: 'pointSize', type: 'float'} - ] -} -exports.pickShader = { - vertex: pickVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'id', type: 'vec4'} - ] -} -exports.pointPickShader = { - vertex: pickPointVertSrc, - fragment: pickFragSrc, - attributes: [ - {name: 'position', type: 'vec3'}, - {name: 'pointSize', type: 'float'}, - {name: 'id', type: 'vec4'} - ] -} -exports.contourShader = { - vertex: contourVertSrc, - fragment: contourFragSrc, - attributes: [ - {name: 'position', type: 'vec3'} - ] -} + //Build vertex cascade to speed up binary search + var vcascade = getCascade(edges, values.length|0) + + //Then construct cells + var faces = contourAlgorithm(d)(cells, edges.data, vcascade, vertexSigns) + + //Unpack data into pretty format + var uedges = unpackEdges(edges) + var uweights = [].slice.call(weights.data, 0, weights.shape[0]) -},{}],227:[function(require,module,exports){ + //Release data + pool.free(vertexSigns) + pool.free(edges.data) + pool.free(weights.data) + pool.free(vcascade) + + return { + cells: faces, + vertexIds: uedges, + vertexWeights: uweights + } +} +},{"./lib/codegen":112,"ndarray":208,"ndarray-sort":115,"typedarray-pool":233}],112:[function(require,module,exports){ 'use strict' -var createShader = require('gl-shader') -var createBuffer = require('gl-buffer') -var createVAO = require('gl-vao') -var createTexture = require('gl-texture2d') -var normals = require('normals') -var multiply = require('gl-mat4/multiply') -var invert = require('gl-mat4/invert') -var ndarray = require('ndarray') -var colormap = require('colormap') -var getContour = require('simplicial-complex-contour') -var pool = require('typedarray-pool') -var shaders = require('./lib/shaders') -var closestPoint = require('./lib/closest-point') +module.exports = getPolygonizer -var meshShader = shaders.meshShader -var wireShader = shaders.wireShader -var pointShader = shaders.pointShader -var pickShader = shaders.pickShader -var pointPickShader = shaders.pointPickShader -var contourShader = shaders.contourShader +var pool = require('typedarray-pool') +var createMSTable = require('marching-simplex-table') -var identityMatrix = [ - 1,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,1] +var CACHE = {} -function SimplicialMesh(gl - , texture - , triShader - , lineShader - , pointShader - , pickShader - , pointPickShader - , contourShader - , trianglePositions - , triangleIds - , triangleColors - , triangleUVs - , triangleNormals - , triangleVAO - , edgePositions - , edgeIds - , edgeColors - , edgeUVs - , edgeVAO - , pointPositions - , pointIds - , pointColors - , pointUVs - , pointSizes - , pointVAO - , contourPositions - , contourVAO) { +function createCellPolygonizer(d) { + var maxCellSize = 0 + var tables = new Array(d+1) + tables[0] = [ [] ] + for(var i=1; i<=d; ++i) { + var tab = tables[i] = createMSTable(i) + for(var j=0; j>1,v=E[2*m+1];', + 'if(v===b){return m}', + 'if(b 0) { + code.push(',') + } + code.push('[') + for(var j=0; j 0) { + code.push(',') + } + code.push('B(C,E,c[', f[0], '],c[', f[1], '])') + } + code.push(']') + } + code.push(');') + } - this.triShader = triShader - this.lineShader = lineShader - this.pointShader = pointShader - this.pickShader = pickShader - this.pointPickShader = pointPickShader - this.contourShader = contourShader + for(var i=d+1; i>1; --i) { + if(i < d+1) { + code.push('else ') + } + code.push('if(l===', i, '){') - this.trianglePositions = trianglePositions - this.triangleColors = triangleColors - this.triangleNormals = triangleNormals - this.triangleUVs = triangleUVs - this.triangleIds = triangleIds - this.triangleVAO = triangleVAO - this.triangleCount = 0 + //Generate mask + var maskStr = [] + for(var j=0; j= 1 +function constructCell(dimension, mask) { + if(mask === 0 || mask === (1<<(dimension+1))-1) { + return [] + } + var points = [] + var index = [] + for(var i=0; i<=dimension; ++i) { + if(mask & (1< 1) { + var scratch_shape = [] + for(var i=1; i 1) { + + //Copy data into scratch + code.push("dptr=0;sptr=ptr") + for(var i=order.length-1; i>=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"left){", + "dptr=0", + "sptr=cptr-s0") + for(var i=1; ib){break __l}"].join("")) + for(var i=order.length-1; i>=1; --i) { + code.push( + "sptr+=e"+i, + "dptr+=f"+i, + "}") + } + + //Copy data back + code.push("dptr=cptr;sptr=cptr-s0") + for(var i=order.length-1; i>=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j,"left)&&("+dataRead("cptr-s0")+">scratch)){", + dataWrite("cptr", dataRead("cptr-s0")), + "cptr-=s0", + "}", + dataWrite("cptr", "scratch")) + } + + //Close outer loop body + code.push("}") + if(order.length > 1 && allocator) { + code.push("free(scratch)") + } + code.push("} return " + funcName) + + //Compile and link function + if(allocator) { + var result = new Function("malloc", "free", code.join("\n")) + return result(allocator[0], allocator[1]) + } else { + var result = new Function(code.join("\n")) + return result() + } +} + +function createQuickSort(order, dtype, insertionSort) { + var code = [ "'use strict'" ] + var funcName = ["ndarrayQuickSort", order.join("d"), dtype].join("") + var funcArgs = ["left", "right", "data", "offset" ].concat(shapeArgs(order.length)) + var allocator = getMallocFree(dtype) + var labelCounter=0 + + code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) + + var vars = [ + "sixth=((right-left+1)/6)|0", + "index1=left+sixth", + "index5=right-sixth", + "index3=(left+right)>>1", + "index2=index3-sixth", + "index4=index3+sixth", + "el1=index1", + "el2=index2", + "el3=index3", + "el4=index4", + "el5=index5", + "less=left+1", + "great=right-1", + "pivots_are_equal=true", + "tmp", + "tmp0", + "x", + "y", + "z", + "k", + "ptr0", + "ptr1", + "ptr2", + "comp_pivot1=0", + "comp_pivot2=0", + "comp=0" + ] + + if(order.length > 1) { + var ele_size = [] + for(var i=1; i=0; --i) { + var j = order[i] + if(j === 0) { + continue + } + code.push(["for(i",j,"=0;i",j," 1) { + for(var i=0; i1) { + code.push("ptr_shift+=d"+j) + } else { + code.push("ptr0+=d"+j) + } + code.push("}") + } + } + + function lexicoLoop(label, ptrs, usePivot, body) { + if(ptrs.length === 1) { + code.push("ptr0="+toPointer(ptrs[0])) + } else { + for(var i=0; i 1) { + for(var i=0; i=1; --i) { + if(usePivot) { + code.push("pivot_ptr+=f"+i) + } + if(ptrs.length > 1) { + code.push("ptr_shift+=e"+i) + } else { + code.push("ptr0+=e"+i) + } + code.push("}") } - result[4*i+3] = c[3]*255 } - - return ndarray(result, [256,256,4], [4,0,1]) -} - -function unpackIntensity(cells, numVerts, cellIntensity) { - var result = new Array(numVerts) - for(var i=0; i 1 && allocator) { + code.push("free(pivot1)", "free(pivot2)") + } } - var numCells = cells.length - for(var i=0; i 1) { + var lbl = "__l" + (++labelCounter) + lexicoLoop(lbl, [a, b], false, [ + "comp=",dataRead("ptr0"),"-",dataRead("ptr1"),"\n", + "if(comp>0){tmp0=", a, ";",a,"=",b,";", b,"=tmp0;break ", lbl,"}\n", + "if(comp<0){break ", lbl, "}" + ].join("")) + } else { + code.push(["if(", dataRead(toPointer(a)), ">", dataRead(toPointer(b)), "){tmp0=", a, ";",a,"=",b,";", b,"=tmp0}"].join("")) } } - return result -} - -function takeZComponent(array) { - var n = array.length - var result = new Array(n) - for(var i=0; i 1) { + cacheLoop(["el1", "el2", "el3", "el4", "el5", "index1", "index3", "index5"], true, [ + "pivot1[pivot_ptr]=",dataRead("ptr1"),"\n", + "pivot2[pivot_ptr]=",dataRead("ptr3"),"\n", + "pivots_are_equal=pivots_are_equal&&(pivot1[pivot_ptr]===pivot2[pivot_ptr])\n", + "x=",dataRead("ptr0"),"\n", + "y=",dataRead("ptr2"),"\n", + "z=",dataRead("ptr4"),"\n", + dataWrite("ptr5", "x"),"\n", + dataWrite("ptr6", "y"),"\n", + dataWrite("ptr7", "z") + ].join("")) + } else { + code.push([ + "pivot1=", dataRead(toPointer("el2")), "\n", + "pivot2=", dataRead(toPointer("el4")), "\n", + "pivots_are_equal=pivot1===pivot2\n", + "x=", dataRead(toPointer("el1")), "\n", + "y=", dataRead(toPointer("el3")), "\n", + "z=", dataRead(toPointer("el5")), "\n", + dataWrite(toPointer("index1"), "x"), "\n", + dataWrite(toPointer("index3"), "y"), "\n", + dataWrite(toPointer("index5"), "z") + ].join("")) } - return result -} + -proto.highlight = function(selection) { - if(!selection || !this.contourEnable) { - this.contourCount = 0 - return - } - var level = getContour(this.cells, this.intensity, selection.intensity) - var cells = level.cells - var vertexIds = level.vertexIds - var vertexWeights = level.vertexWeights - var numCells = cells.length - var result = pool.mallocFloat32(2 * 3 * numCells) - var ptr = 0 - for(var i=0; i 1) { + cacheLoop([dst, src], false, + dataWrite("ptr0", dataRead("ptr1")) + ) + } else { + code.push(dataWrite(toPointer(dst), dataRead(toPointer(src)))) } } - this.contourCount = (ptr / 3)|0 - this.contourPositions.update(result.subarray(0, ptr)) - pool.free(result) -} - -proto.update = function(params) { - params = params || {} - var gl = this.gl - - this.dirty = true - - if('contourEnable' in params) { - this.contourEnable = params.contourEnable + + moveElement("index2", "left") + moveElement("index4", "right") + + function comparePivot(result, ptr, n) { + if(order.length > 1) { + var lbl = "__l" + (++labelCounter) + lexicoLoop(lbl, [ptr], true, [ + result,"=",dataRead("ptr0"),"-pivot",n,"[pivot_ptr]\n", + "if(",result,"!==0){break ", lbl, "}" + ].join("")) + } else { + code.push([result,"=", dataRead(toPointer(ptr)), "-pivot", n].join("")) + } } - if('contourColor' in params) { - this.contourColor = params.contourColor + + function swapElements(a, b) { + if(order.length > 1) { + cacheLoop([a,b],false,[ + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", "tmp") + ].join("")) + } else { + code.push([ + "ptr0=",toPointer(a),"\n", + "ptr1=",toPointer(b),"\n", + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", "tmp") + ].join("")) + } } - if('lineWidth' in params) { - this.lineWidth = params.lineWidth + + function tripleSwap(k, less, great) { + if(order.length > 1) { + cacheLoop([k,less,great], false, [ + "tmp=",dataRead("ptr0"),"\n", + dataWrite("ptr0", dataRead("ptr1")),"\n", + dataWrite("ptr1", dataRead("ptr2")),"\n", + dataWrite("ptr2", "tmp") + ].join("")) + code.push("++"+less, "--"+great) + } else { + code.push([ + "ptr0=",toPointer(k),"\n", + "ptr1=",toPointer(less),"\n", + "ptr2=",toPointer(great),"\n", + "++",less,"\n", + "--",great,"\n", + "tmp=", dataRead("ptr0"), "\n", + dataWrite("ptr0", dataRead("ptr1")), "\n", + dataWrite("ptr1", dataRead("ptr2")), "\n", + dataWrite("ptr2", "tmp") + ].join("")) + } } - if('opacity' in params) { - this.opacity = params.opacity + + function swapAndDecrement(k, great) { + swapElements(k, great) + code.push("--"+great) } - - if(params.texture) { - this.texture.dispose() - this.texture = createTexture(gl, params.texture) - } else if (params.colormap) { - this.texture.shape = [256,256] - this.texture.minFilter = gl.LINEAR_MIPMAP_LINEAR - this.texture.magFilter = gl.LINEAR - this.texture.setPixels(genColormap(params.colormap)) - this.texture.generateMipmap() + + code.push("if(pivots_are_equal){") + //Pivots are equal case + code.push("for(k=less;k<=great;++k){") + comparePivot("comp", "k", 1) + code.push("if(comp===0){continue}") + code.push("if(comp<0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + code.push("while(true){") + comparePivot("comp", "great", 1) + code.push("if(comp>0){") + code.push("great--") + code.push("}else if(comp<0){") + tripleSwap("k", "less", "great") + code.push("break") + code.push("}else{") + swapAndDecrement("k", "great") + code.push("break") + code.push("}") + code.push("}") + code.push("}") + code.push("}") + code.push("}else{") + //Pivots not equal case + code.push("for(k=less;k<=great;++k){") + comparePivot("comp_pivot1", "k", 1) + code.push("if(comp_pivot1<0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + comparePivot("comp_pivot2", "k", 2) + code.push("if(comp_pivot2>0){") + code.push("while(true){") + comparePivot("comp", "great", 2) + code.push("if(comp>0){") + code.push("if(--great1) { + cacheLoop([mem_dest, pivot_dest], true, [ + dataWrite("ptr0", dataRead("ptr1")), "\n", + dataWrite("ptr1", ["pivot",pivot,"[pivot_ptr]"].join("")) + ].join("")) + } else { + code.push( + dataWrite(toPointer(mem_dest), dataRead(toPointer(pivot_dest))), + dataWrite(toPointer(pivot_dest), "pivot"+pivot)) + } } + + storePivot("left", "(less-1)", 1) + storePivot("right", "(great+1)", 2) - var cells = params.cells - var positions = params.positions - - if(!positions || !cells) { - return + //Recursive sort call + function doSort(left, right) { + code.push([ + "if((",right,"-",left,")<=",INSERTION_SORT_THRESHOLD,"){\n", + "insertionSort(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", + "}else{\n", + funcName, "(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", + "}" + ].join("")) } - - var tPos = [] - var tCol = [] - var tNor = [] - var tUVs = [] - var tIds = [] - - var ePos = [] - var eCol = [] - var eUVs = [] - var eIds = [] - - var pPos = [] - var pCol = [] - var pUVs = [] - var pSiz = [] - var pIds = [] - - //Save geometry data for picking calculations - this.cells = cells - this.positions = positions - - //Compute normals - var vertexNormals = params.vertexNormals - var cellNormals = params.cellNormals - if(params.useFacetNormals && !cellNormals) { - cellNormals = normals.faceNormals(cells, positions) + doSort("left", "(less-2)") + doSort("(great+2)", "right") + + //If pivots are equal, then early out + code.push("if(pivots_are_equal){") + cleanUp() + code.push("return") + code.push("}") + + function walkPointer(ptr, pivot, body) { + if(order.length > 1) { + code.push(["__l",++labelCounter,":while(true){"].join("")) + cacheLoop([ptr], true, [ + "if(", dataRead("ptr0"), "!==pivot", pivot, "[pivot_ptr]){break __l", labelCounter, "}" + ].join("")) + code.push(body, "}") + } else { + code.push(["while(", dataRead(toPointer(ptr)), "===pivot", pivot, "){", body, "}"].join("")) + } } - if(!cellNormals && !vertexNormals) { - vertexNormals = normals.vertexNormals(cells, positions) + + //Check bounds + code.push("if(lessindex5){") + + walkPointer("less", 1, "++less") + walkPointer("great", 2, "--great") + + code.push("for(k=less;k<=great;++k){") + comparePivot("comp_pivot1", "k", 1) + code.push("if(comp_pivot1===0){") + code.push("if(k!==less){") + swapElements("k", "less") + code.push("}") + code.push("++less") + code.push("}else{") + comparePivot("comp_pivot2", "k", 2) + code.push("if(comp_pivot2===0){") + code.push("while(true){") + comparePivot("comp", "great", 2) + code.push("if(comp===0){") + code.push("if(--great 1 && allocator) { + var compiled = new Function("insertionSort", "malloc", "free", code.join("\n")) + return compiled(insertionSort, allocator[0], allocator[1]) } + var compiled = new Function("insertionSort", code.join("\n")) + return compiled(insertionSort) +} - //Compute colors - var vertexColors = params.vertexColors - var cellColors = params.cellColors - var meshColor = params.meshColor || [1,1,1,1] - - //UVs - var vertexUVs = params.vertexUVs - var vertexIntensity = params.vertexIntensity - var cellUVs = params.cellUVs - var cellIntensity = params.cellIntensity - - var intensityLo = Infinity - var intensityHi = -Infinity - if(!vertexUVs && !cellUVs) { - if(vertexIntensity) { - for(var i=0; i 0) { + vars.push(["d",j,"=s",j,"-d",p,"*n",p].join("")) + } else { + vars.push(["d",j,"=s",j].join("")) + } + p = j + } + var k = order.length-1-i + if(k !== 0) { + if(q > 0) { + vars.push(["e",k,"=s",k,"-e",q,"*n",q, + ",f",k,"=",scratch_stride[k],"-f",q,"*n",q].join("")) + } else { + vars.push(["e",k,"=s",k,",f",k,"=",scratch_stride[k]].join("")) } - this.bounds[0][j] = Math.min(this.bounds[0][j], p[j]) - this.bounds[1][j] = Math.max(this.bounds[1][j], p[j]) + q = k } } + + //Declare local variables + code.push("var " + vars.join(",")) + + //Create arguments for subroutine + var sortArgs = ["0", "n0-1", "data", "offset"].concat(shapeArgs(order.length)) + + //Call main sorting routine + code.push([ + "if(n0<=",INSERTION_SORT_THRESHOLD,"){", + "insertionSort(", sortArgs.join(","), ")}else{", + "quickSort(", sortArgs.join(","), + ")}" + ].join("")) + + //Return + code.push("}return " + funcName) + + //Link everything together + var result = new Function("insertionSort", "quickSort", code.join("\n")) + var insertionSort = createInsertionSort(order, dtype) + var quickSort = createQuickSort(order, dtype, insertionSort) + return result(insertionSort, quickSort) +} - //Pack cells into buffers - var triangleCount = 0 - var edgeCount = 0 - var pointCount = 0 - -fill_loop: - for(var i=0; i 0) { - var shader = this.triShader - shader.bind() - shader.uniforms = uniforms +proto.drawTickMarks = (function() { + var DATA_SHIFT = [0,0] + var DATA_SCALE = [0,0] + var X_AXIS = [1,0] + var Y_AXIS = [0,1] + var SCR_OFFSET = [0,0] + var TICK_SCALE = [0,0] - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } + return function() { + var plot = this.plot + var vbo = this.vbo + var shader = this.tickShader + var ticks = this.ticks + var gl = plot.gl + var bounds = plot._tickBounds + var dataBox = plot.dataBox + var viewBox = plot.viewBox + var pixelRatio = plot.pixelRatio + var screenBox = plot.screenBox - if(this.edgeCount > 0 && this.lineWidth > 0) { - var shader = this.lineShader - shader.bind() - shader.uniforms = uniforms + var screenWidth = screenBox[2] - screenBox[0] + var screenHeight = screenBox[3] - screenBox[1] + var viewWidth = viewBox[2] - viewBox[0] + var viewHeight = viewBox[3] - viewBox[1] - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } + for(var i=0; i<2; ++i) { + var lo = bounds[i] + var hi = bounds[i+2] + var boundScale = hi - lo + var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) + var dataWidth = (dataBox[i+2] - dataBox[i]) + DATA_SCALE[i] = 2.0 * boundScale / dataWidth + DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth + } - if(this.pointCount > 0) { - var shader = this.pointShader - shader.bind() - shader.uniforms = uniforms + DATA_SCALE[0] *= viewWidth / screenWidth + DATA_SHIFT[0] *= viewWidth / screenWidth - this.pointVAO.bind() - gl.drawArrays(gl.POINTS, 0, this.pointCount) - this.pointVAO.unbind() - } + DATA_SCALE[1] *= viewHeight / screenHeight + DATA_SHIFT[1] *= viewHeight / screenHeight - if(this.contourEnable && this.contourCount > 0 && this.contourLineWidth > 0) { - var shader = this.contourShader shader.bind() - shader.uniforms = uniforms + vbo.bind() - this.contourVAO.bind() - gl.drawArrays(gl.LINES, 0, this.contourCount) - this.contourVAO.unbind() - } -} + shader.attributes.dataCoord.pointer() -proto.drawPick = function(params) { - params = params || {} + var uniforms = shader.uniforms + uniforms.dataShift = DATA_SHIFT + uniforms.dataScale = DATA_SCALE - var gl = this.gl + var tickMarkLength = plot.tickMarkLength + var tickMarkWidth = plot.tickMarkWidth + var tickMarkColor = plot.tickMarkColor - var model = params.model || identityMatrix - var view = params.view || identityMatrix - var projection = params.projection || identityMatrix + var xTicksOffset = 0 + var yTicksOffset = ticks[0].length * 6 - var clipBounds = [[-1e6,-1e6,-1e6],[1e6,1e6,1e6]] - for(var i=0; i<3; ++i) { - clipBounds[0][i] = Math.max(clipBounds[0][i], this.clipBounds[0][i]) - clipBounds[1][i] = Math.min(clipBounds[1][i], this.clipBounds[1][i]) - } + var xStart = Math.min(bsearch.ge(ticks[0], (dataBox[0] - bounds[0]) / (bounds[2] - bounds[0]), compareTickNum), ticks[0].length) + var xEnd = Math.min(bsearch.gt(ticks[0], (dataBox[2] - bounds[0]) / (bounds[2] - bounds[0]), compareTickNum), ticks[0].length) + var xOffset = xTicksOffset + 6 * xStart + var xCount = 6 * Math.max(0, xEnd - xStart) - //Save camera parameters - this._model = [].slice.call(model) - this._view = [].slice.call(view) - this._projection = [].slice.call(projection) - this._resolution = [gl.drawingBufferWidth, gl.drawingBufferHeight] + var yStart = Math.min(bsearch.ge(ticks[1], (dataBox[1] - bounds[1]) / (bounds[3] - bounds[1]), compareTickNum), ticks[1].length) + var yEnd = Math.min(bsearch.gt(ticks[1], (dataBox[3] - bounds[1]) / (bounds[3] - bounds[1]), compareTickNum), ticks[1].length) + var yOffset = yTicksOffset + 6 * yStart + var yCount = 6 * Math.max(0, yEnd - yStart) - var uniforms = { - model: model, - view: view, - projection: projection, - clipBounds: clipBounds, - pickId: this.pickId / 255.0, - } + SCR_OFFSET[0] = 2.0 * (viewBox[0] - tickMarkLength[1]) / screenWidth - 1.0 + SCR_OFFSET[1] = (viewBox[3] + viewBox[1]) / screenHeight - 1.0 + TICK_SCALE[0] = tickMarkLength[1] * pixelRatio / screenWidth + TICK_SCALE[1] = tickMarkWidth[1] * pixelRatio / screenHeight - var shader = this.pickShader - shader.bind() - shader.uniforms = uniforms + uniforms.color = tickMarkColor[1] + uniforms.tickScale = TICK_SCALE + uniforms.dataAxis = Y_AXIS + uniforms.screenOffset = SCR_OFFSET + gl.drawArrays(gl.TRIANGLES, yOffset, yCount) - if(this.triangleCount > 0) { - this.triangleVAO.bind() - gl.drawArrays(gl.TRIANGLES, 0, this.triangleCount*3) - this.triangleVAO.unbind() - } + SCR_OFFSET[0] = (viewBox[2] + viewBox[0]) / screenWidth - 1.0 + SCR_OFFSET[1] = 2.0 * (viewBox[1] - tickMarkLength[0]) / screenHeight - 1.0 + TICK_SCALE[0] = tickMarkWidth[0] * pixelRatio / screenWidth + TICK_SCALE[1] = tickMarkLength[0] * pixelRatio / screenHeight - if(this.edgeCount > 0) { - this.edgeVAO.bind() - gl.lineWidth(this.lineWidth) - gl.drawArrays(gl.LINES, 0, this.edgeCount*2) - this.edgeVAO.unbind() - } + uniforms.color = tickMarkColor[0] + uniforms.tickScale = TICK_SCALE + uniforms.dataAxis = X_AXIS + uniforms.screenOffset = SCR_OFFSET + gl.drawArrays(gl.TRIANGLES, xOffset, xCount) - if(this.pointCount > 0) { - var shader = this.pointPickShader - shader.bind() - shader.uniforms = uniforms + SCR_OFFSET[0] = 2.0 * (viewBox[2] + tickMarkLength[3]) / screenWidth - 1.0 + SCR_OFFSET[1] = (viewBox[3] + viewBox[1]) / screenHeight - 1.0 + TICK_SCALE[0] = tickMarkLength[3] * pixelRatio / screenWidth + TICK_SCALE[1] = tickMarkWidth[3] * pixelRatio / screenHeight - this.pointVAO.bind() - gl.drawArrays(gl.POINTS, 0, this.pointCount) - this.pointVAO.unbind() - } -} + uniforms.color = tickMarkColor[3] + uniforms.tickScale = TICK_SCALE + uniforms.dataAxis = Y_AXIS + uniforms.screenOffset = SCR_OFFSET + gl.drawArrays(gl.TRIANGLES, yOffset, yCount) + SCR_OFFSET[0] = (viewBox[2] + viewBox[0]) / screenWidth - 1.0 + SCR_OFFSET[1] = 2.0 * (viewBox[3] + tickMarkLength[2]) / screenHeight - 1.0 + TICK_SCALE[0] = tickMarkWidth[2] * pixelRatio / screenWidth + TICK_SCALE[1] = tickMarkLength[2] * pixelRatio / screenHeight -proto.pick = function(pickData) { - if(!pickData) { - return null - } - if(pickData.id !== this.pickId) { - return null + uniforms.color = tickMarkColor[2] + uniforms.tickScale = TICK_SCALE + uniforms.dataAxis = X_AXIS + uniforms.screenOffset = SCR_OFFSET + gl.drawArrays(gl.TRIANGLES, xOffset, xCount) } +})() - var cellId = pickData.value[0] + 256*pickData.value[1] + 65536*pickData.value[2] - var cell = this.cells[cellId] - var positions = this.positions +proto.update = (function() { + var OFFSET_X = [1, 1, -1, -1, 1, -1] + var OFFSET_Y = [1, -1, 1, 1, -1, -1] - var simplex = new Array(cell.length) - for(var i=0; i nshades) { - throw new Error(colormap + - ' map requires nshades to be at least size ' + - cmap.length); - } + shader.bind() - /* - * map index points from 0->1 to 0 -> n-1 - */ - indicies = cmap.map(function(c) { - return Math.round(c.index * nshades); - }); + //Set up coordinate scaling uniforms + for(var i=0; i<2; ++i) { - /* - * Add alpha channel to the map - */ - if (alpha[0] < 0) alpha[0] = 0; - if (alpha[1] < 0) alpha[0] = 0; - if (alpha[0] > 1) alpha[0] = 1; - if (alpha[1] > 1) alpha[0] = 1; + var lo = bounds[i] + var hi = bounds[i+2] + var boundScale = hi - lo + var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) + var dataWidth = (dataBox[i+2] - dataBox[i]) - for (i = 0; i < indicies.length; ++i) { - index = cmap[i].index; - rgba = cmap[i].rgb; - // if user supplies their own map use theirs - if (rgba.length === 4 && rgba[3] >= 0 && rgba[3] <= 1) continue; - rgba[3] = alpha[0] + (alpha[1] - alpha[0])*index; - } + var viewLo = viewBox[i] + var viewHi = viewBox[i+2] + var viewScale = viewHi - viewLo + var screenLo = screenBox[i] + var screenHi = screenBox[i+2] + var screenScale = screenHi - screenLo - /* - * map increasing linear values between indicies to - * linear steps in colorvalues - */ - for (i = 0; i < indicies.length-1; ++i) { - nsteps = indicies[i+1] - indicies[i]; - fromrgba = cmap[i].rgb; - torgba = cmap[i+1].rgb; - r = r.concat(at.linspace(fromrgba[0], torgba[0], nsteps ) ); - g = g.concat(at.linspace(fromrgba[1], torgba[1], nsteps ) ); - b = b.concat(at.linspace(fromrgba[2], torgba[2], nsteps ) ); - a = a.concat(at.linspace(fromrgba[3], torgba[3], nsteps ) ); + DATA_SCALE[i] = 2.0 * boundScale / dataWidth * viewScale / screenScale + DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth * viewScale / screenScale } - r = r.map( Math.round ); - g = g.map( Math.round ); - b = b.map( Math.round ); + TEXT_SCALE[1] = 2.0 * plot.pixelRatio / (screenBox[3] - screenBox[1]) + TEXT_SCALE[0] = TEXT_SCALE[1] * (screenBox[3] - screenBox[1]) / (screenBox[2] - screenBox[0]) - colors = at.zip(r, g, b, a); + shader.uniforms.dataScale = DATA_SCALE + shader.uniforms.dataShift = DATA_SHIFT + shader.uniforms.textScale = TEXT_SCALE - if (format === 'hex') colors = colors.map( rgb2hex ); - if (format === 'rgbaString') colors = colors.map( rgbaStr ); + //Set attributes + this.vbo.bind() + shader.attributes.textCoordinate.pointer() + } +})() - return colors; -}; +proto.update = function(options) { + var vertices = [] + var axesTicks = options.ticks + var bounds = options.bounds + for(var dimension=0; dimension<2; ++dimension) { + var offsets = [Math.floor(vertices.length/3)], tickX = [-Infinity] -function rgb2hex (rgba) { - var dig, hex = '#'; - for (var i = 0; i < 3; ++i) { - dig = rgba[i]; - dig = dig.toString(16); - hex += ('00' + dig).substr( dig.length ); - } - return hex; -} + //Copy vertices over to buffer + var ticks = axesTicks[dimension] + for(var i=0; i EPSILON) { - var norm = normals[c]; - var w = 1.0 / Math.sqrt(m01 * m21); - for(var k=0; k<3; ++k) { - var u = (k+1)%3; - var v = (k+2)%3; - norm[k] += w * (d21[u] * d01[v] - d21[v] * d01[u]); - } - } - } - } - - //Scale all normals to unit length - for(var i=0; i EPSILON) { - var w = 1.0 / Math.sqrt(m); - for(var k=0; k<3; ++k) { - norm[k] *= w; - } - } else { - for(var k=0; k<3; ++k) { - norm[k] = 0.0; - } + offsets.push(Math.floor(vertices.length/3)) + tickX.push(x) } + + this.tickOffset[dimension] = offsets + this.tickX[dimension] = tickX } - //Return the resulting set of patches - return normals; -} + //Add labels + for(var dimension=0; dimension<2; ++dimension) { + this.labelOffset[dimension] = Math.floor(vertices.length/3) -//Compute face normals of a mesh -exports.faceNormals = function(faces, positions) { - var N = faces.length; - var normals = new Array(N); - - for(var i=0; i EPSILON) { - l = 1.0 / Math.sqrt(l); - } else { - l = 0.0; - } - for(var j=0; j<3; ++j) { - n[j] *= l; + var data = getText(options.labelFont[dimension], options.labels[dimension]).data + var scale = options.labelSize[dimension] + for(var i=0; i= a00) { - s = 1.0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } else { - s = 0; - if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else if (-b1 >= a11) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else { // region 3 - s = 0; - if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else if (-b1 >= a11) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else if (t < 0) { // region 5 - t = 0; - if (b0 >= 0) { - s = 0; - sqrDistance = c; - } else if (-b0 >= a00) { - s = 1; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } else { // region 0 - // minimum at interior point - var invDet = 1.0 / det; - s *= invDet; - t *= invDet; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - var tmp0, tmp1, numer, denom; - - if (s < 0) { // region 2 - tmp0 = a01 + b0; - tmp1 = a11 + b1; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - s = 1; - t = 0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = numer/denom; - t = 1 - s; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - s = 0; - if (tmp1 <= 0) { - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else if (b1 >= 0) { - t = 0; - sqrDistance = c; - } else { - t = -b1/a11; - sqrDistance = b1*t + c; - } - } - } else if (t < 0) { // region 6 - tmp0 = a01 + b1; - tmp1 = a00 + b0; - if (tmp1 > tmp0) { - numer = tmp1 - tmp0; - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - t = 1; - s = 0; - sqrDistance = a11 + 2.0*b1 + c; - } else { - t = numer/denom; - s = 1 - t; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } else { - t = 0; - if (tmp1 <= 0) { - s = 1; - sqrDistance = a00 + 2.0*b0 + c; - } else if (b0 >= 0) { - s = 0; - sqrDistance = c; - } else { - s = -b0/a00; - sqrDistance = b0*s + c; - } - } - } else { // region 1 - numer = a11 + b1 - a01 - b0; - if (numer <= 0) { - s = 0; - t = 1; - sqrDistance = a11 + 2.0*b1 + c; - } else { - denom = a00 - 2.0*a01 + a11; - if (numer >= denom) { - s = 1; - t = 0; - sqrDistance = a00 + 2.0*b0 + c; - } else { - s = numer/denom; - t = 1 - s; - sqrDistance = s*(a00*s + a01*t + 2.0*b0) + - t*(a01*s + a11*t + 2.0*b1) + c; - } - } +},{"./shaders":119,"binary-search-bounds":121,"gl-buffer":75,"gl-shader":154,"text-cache":228}],121:[function(require,module,exports){ +"use strict" + +function compileSearch(funcName, predicate, reversed, extraArgs, earlyOut) { + var code = [ + "function ", funcName, "(a,l,h,", extraArgs.join(","), "){", +earlyOut ? "" : "var i=", (reversed ? "l-1" : "h+1"), +";while(l<=h){\ +var m=(l+h)>>>1,x=a[m]"] + if(earlyOut) { + if(predicate.indexOf("c") < 0) { + code.push(";if(x===y){return m}else if(x<=y){") + } else { + code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") } + } else { + code.push(";if(", predicate, "){i=m;") } - var u = 1.0 - s - t; - for(var i=0; i=", false, "GE"), + gt: compileBoundsSearch(">", false, "GT"), + lt: compileBoundsSearch("<", true, "LT"), + le: compileBoundsSearch("<=", true, "LE"), + eq: compileBoundsSearch("-", true, "EQ", true) +} -},{}],270:[function(require,module,exports){ +},{}],122:[function(require,module,exports){ 'use strict' -module.exports = extractContour +module.exports = createGLPlot2D -var ndarray = require('ndarray') -var pool = require('typedarray-pool') -var ndsort = require('ndarray-sort') +var createPick = require('gl-select-static') -var contourAlgorithm = require('./lib/codegen') +var createGrid = require('./lib/grid') +var createText = require('./lib/text') +var createLine = require('./lib/line') +var createBox = require('./lib/box') -function getDimension(cells) { - var numCells = cells.length - var d = 0 - for(var i=0; i= 0)) { + continue + } + + var zeroIntercept = screenBox[i] - + dataBox[i] * (screenBox[i+2] - screenBox[i]) / (dataBox[i+2] - dataBox[i]) + + if(i === 0) { + line.drawLine( + zeroIntercept, screenBox[1], zeroIntercept, screenBox[3], + zeroLineWidth[i], + zeroLineColor[i]) + } else { + line.drawLine( + screenBox[0], zeroIntercept, screenBox[2], zeroIntercept, + zeroLineWidth[i], + zeroLineColor[i]) + } } } - //Read in vertex signs - var vertexSigns = getSigns(values, +level) + //Draw traces + for(var i=0; i>1,v=E[2*m+1];', - 'if(v===b){return m}', - 'if(b 0) { - code.push(',') - } - code.push('[') - for(var j=0; j 0) { - code.push(',') - } - code.push('B(C,E,c[', f[0], '],c[', f[1], '])') - } - code.push(']') - } - code.push(');') - } +proto.pick = (function() { +return function(x, y) { + var pixelRatio = this.pixelRatio + var pickPixelRatio = this.pickPixelRatio + var viewBox = this.viewBox - for(var i=d+1; i>1; --i) { - if(i < d+1) { - code.push('else ') - } - code.push('if(l===', i, '){') + var scrX = Math.round((x - viewBox[0] / pixelRatio) * pickPixelRatio)|0 + var scrY = Math.round((y - viewBox[1] / pixelRatio) * pickPixelRatio)|0 - //Generate mask - var maskStr = [] - for(var j=0; j 1) { - var scratch_shape = [] - for(var i=1; i 1) { - - //Copy data into scratch - code.push("dptr=0;sptr=ptr") - for(var i=order.length-1; i>=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"left){", - "dptr=0", - "sptr=cptr-s0") - for(var i=1; ib){break __l}"].join("")) - for(var i=order.length-1; i>=1; --i) { - code.push( - "sptr+=e"+i, - "dptr+=f"+i, - "}") - } - - //Copy data back - code.push("dptr=cptr;sptr=cptr-s0") - for(var i=order.length-1; i>=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j,"left)&&("+dataRead("cptr-s0")+">scratch)){", - dataWrite("cptr", dataRead("cptr-s0")), - "cptr-=s0", - "}", - dataWrite("cptr", "scratch")) + //Update text + this.text.update({ + bounds: bounds, + ticks: ticks, + labels: options.labels || ['x', 'y'], + labelSize: options.labelSize || [12,12], + labelFont: options.labelFont || ['sans-serif', 'sans-serif'], + title: options.title || '', + titleSize: options.titleSize || 18, + titleFont: options.titleFont || 'sans-serif' + }) + + this.setDirty() +} + +proto.dispose = function() { + this.box.dispose() + this.grid.dispose() + this.text.dispose() + this.line.dispose() + for(var i=this.objects.length-1; i>=0; --i) { + this.objects[i].dispose() } - - //Close outer loop body - code.push("}") - if(order.length > 1 && allocator) { - code.push("free(scratch)") + this.objects.length = 0 + for(var i=this.overlays.length-1; i>=0; --i) { + this.overlays[i].dispose() } - code.push("} return " + funcName) - - //Compile and link function - if(allocator) { - var result = new Function("malloc", "free", code.join("\n")) - return result(allocator[0], allocator[1]) - } else { - var result = new Function(code.join("\n")) - return result() + this.overlays.length = 0 + + this.gl = null +} + +proto.addObject = function(object) { + if(this.objects.indexOf(object) < 0) { + this.objects.push(object) + this.setDirty() } } -function createQuickSort(order, dtype, insertionSort) { - var code = [ "'use strict'" ] - var funcName = ["ndarrayQuickSort", order.join("d"), dtype].join("") - var funcArgs = ["left", "right", "data", "offset" ].concat(shapeArgs(order.length)) - var allocator = getMallocFree(dtype) - var labelCounter=0 - - code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) - - var vars = [ - "sixth=((right-left+1)/6)|0", - "index1=left+sixth", - "index5=right-sixth", - "index3=(left+right)>>1", - "index2=index3-sixth", - "index4=index3+sixth", - "el1=index1", - "el2=index2", - "el3=index3", - "el4=index4", - "el5=index5", - "less=left+1", - "great=right-1", - "pivots_are_equal=true", - "tmp", - "tmp0", - "x", - "y", - "z", - "k", - "ptr0", - "ptr1", - "ptr2", - "comp_pivot1=0", - "comp_pivot2=0", - "comp=0" - ] - - if(order.length > 1) { - var ele_size = [] - for(var i=1; i=0; --i) { - var j = order[i] - if(j === 0) { - continue - } - code.push(["for(i",j,"=0;i",j," 1) { - for(var i=0; i1) { - code.push("ptr_shift+=d"+j) - } else { - code.push("ptr0+=d"+j) + var sizeChanged = + element.clientWidth === width && + element.clientHeight === height + width = element.clientWidth + height = element.clientHeight + if(allEqual) { + return !sizeChanged } - code.push("}") + distance = Math.exp(view.computedRadius[0]) + return true + }, + lookAt: function(center, eye, up) { + view.lookAt(view.lastT(), center, eye, up) + }, + rotate: function(pitch, yaw, roll) { + view.rotate(view.lastT(), pitch, yaw, roll) + }, + pan: function(dx, dy, dz) { + view.pan(view.lastT(), dx, dy, dz) + }, + translate: function(dx, dy, dz) { + view.translate(view.lastT(), dx, dy, dz) } } - - function lexicoLoop(label, ptrs, usePivot, body) { - if(ptrs.length === 1) { - code.push("ptr0="+toPointer(ptrs[0])) - } else { - for(var i=0; i 1) { - for(var i=0; i=1; --i) { - if(usePivot) { - code.push("pivot_ptr+=f"+i) - } - if(ptrs.length > 1) { - code.push("ptr_shift+=e"+i) + }) + + element.addEventListener('contextmenu', function(ev) { + ev.preventDefault() + return false + }) + + var lastX = 0, lastY = 0 + mouseChange(element, function(buttons, x, y, mods) { + var scale = 1.0 / element.clientHeight + var dx = scale * (x - lastX) + var dy = scale * (y - lastY) + + var flipX = camera.flipX ? 1 : -1 + var flipY = camera.flipY ? 1 : -1 + + var drot = Math.PI * camera.rotateSpeed + + var t = now() + + if(buttons & 1) { + if(mods.shift) { + view.rotate(t, 0, 0, -dx * drot) } else { - code.push("ptr0+=e"+i) + view.rotate(t, flipX * drot * dx, -flipY * drot * dy, 0) } - code.push("}") - } - } - - function cleanUp() { - if(order.length > 1 && allocator) { - code.push("free(pivot1)", "free(pivot2)") - } - } - - function compareSwap(a_id, b_id) { - var a = "el"+a_id - var b = "el"+b_id - if(order.length > 1) { - var lbl = "__l" + (++labelCounter) - lexicoLoop(lbl, [a, b], false, [ - "comp=",dataRead("ptr0"),"-",dataRead("ptr1"),"\n", - "if(comp>0){tmp0=", a, ";",a,"=",b,";", b,"=tmp0;break ", lbl,"}\n", - "if(comp<0){break ", lbl, "}" - ].join("")) - } else { - code.push(["if(", dataRead(toPointer(a)), ">", dataRead(toPointer(b)), "){tmp0=", a, ";",a,"=",b,";", b,"=tmp0}"].join("")) + } else if(buttons & 2) { + view.pan(t, -camera.translateSpeed * dx * distance, camera.translateSpeed * dy * distance, 0) + } else if(buttons & 4) { + var kzoom = camera.zoomSpeed * dy / window.innerHeight * (t - view.lastT()) * 50.0 + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) } - } - - compareSwap(1, 2) - compareSwap(4, 5) - compareSwap(1, 3) - compareSwap(2, 3) - compareSwap(1, 4) - compareSwap(3, 4) - compareSwap(2, 5) - compareSwap(2, 3) - compareSwap(4, 5) - - if(order.length > 1) { - cacheLoop(["el1", "el2", "el3", "el4", "el5", "index1", "index3", "index5"], true, [ - "pivot1[pivot_ptr]=",dataRead("ptr1"),"\n", - "pivot2[pivot_ptr]=",dataRead("ptr3"),"\n", - "pivots_are_equal=pivots_are_equal&&(pivot1[pivot_ptr]===pivot2[pivot_ptr])\n", - "x=",dataRead("ptr0"),"\n", - "y=",dataRead("ptr2"),"\n", - "z=",dataRead("ptr4"),"\n", - dataWrite("ptr5", "x"),"\n", - dataWrite("ptr6", "y"),"\n", - dataWrite("ptr7", "z") - ].join("")) - } else { - code.push([ - "pivot1=", dataRead(toPointer("el2")), "\n", - "pivot2=", dataRead(toPointer("el4")), "\n", - "pivots_are_equal=pivot1===pivot2\n", - "x=", dataRead(toPointer("el1")), "\n", - "y=", dataRead(toPointer("el3")), "\n", - "z=", dataRead(toPointer("el5")), "\n", - dataWrite(toPointer("index1"), "x"), "\n", - dataWrite(toPointer("index3"), "y"), "\n", - dataWrite(toPointer("index5"), "z") - ].join("")) - } - - function moveElement(dst, src) { - if(order.length > 1) { - cacheLoop([dst, src], false, - dataWrite("ptr0", dataRead("ptr1")) - ) - } else { - code.push(dataWrite(toPointer(dst), dataRead(toPointer(src)))) - } - } - - moveElement("index2", "left") - moveElement("index4", "right") - - function comparePivot(result, ptr, n) { - if(order.length > 1) { - var lbl = "__l" + (++labelCounter) - lexicoLoop(lbl, [ptr], true, [ - result,"=",dataRead("ptr0"),"-pivot",n,"[pivot_ptr]\n", - "if(",result,"!==0){break ", lbl, "}" - ].join("")) - } else { - code.push([result,"=", dataRead(toPointer(ptr)), "-pivot", n].join("")) - } - } - - function swapElements(a, b) { - if(order.length > 1) { - cacheLoop([a,b],false,[ - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", "tmp") - ].join("")) + lastX = x + lastY = y + }) + + mouseWheel(element, function(dx, dy, dz) { + var flipX = camera.flipX ? 1 : -1 + var flipY = camera.flipY ? 1 : -1 + var t = now() + if(Math.abs(dx) > Math.abs(dy)) { + view.rotate(t, 0, 0, -dx * flipX * Math.PI * camera.rotateSpeed / window.innerWidth) } else { - code.push([ - "ptr0=",toPointer(a),"\n", - "ptr1=",toPointer(b),"\n", - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", "tmp") - ].join("")) + var kzoom = camera.zoomSpeed * flipY * dy / window.innerHeight * (t - view.lastT()) / 100.0 + view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) } + }, true) + + return camera +} +},{"3d-view":38,"mouse-change":196,"mouse-wheel":200,"right-now":210}],125:[function(require,module,exports){ +// Copyright (C) 2011 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Install a leaky WeakMap emulation on platforms that + * don't provide a built-in one. + * + *

Assumes that an ES5 platform where, if {@code WeakMap} is + * already present, then it conforms to the anticipated ES6 + * specification. To run this file on an ES5 or almost ES5 + * implementation where the {@code WeakMap} specification does not + * quite conform, run repairES5.js first. + * + *

Even though WeakMapModule is not global, the linter thinks it + * is, which is why it is in the overrides list below. + * + *

NOTE: Before using this WeakMap emulation in a non-SES + * environment, see the note below about hiddenRecord. + * + * @author Mark S. Miller + * @requires crypto, ArrayBuffer, Uint8Array, navigator, console + * @overrides WeakMap, ses, Proxy + * @overrides WeakMapModule + */ + +/** + * This {@code WeakMap} emulation is observably equivalent to the + * ES-Harmony WeakMap, but with leakier garbage collection properties. + * + *

As with true WeakMaps, in this emulation, a key does not + * retain maps indexed by that key and (crucially) a map does not + * retain the keys it indexes. A map by itself also does not retain + * the values associated with that map. + * + *

However, the values associated with a key in some map are + * retained so long as that key is retained and those associations are + * not overridden. For example, when used to support membranes, all + * values exported from a given membrane will live for the lifetime + * they would have had in the absence of an interposed membrane. Even + * when the membrane is revoked, all objects that would have been + * reachable in the absence of revocation will still be reachable, as + * far as the GC can tell, even though they will no longer be relevant + * to ongoing computation. + * + *

The API implemented here is approximately the API as implemented + * in FF6.0a1 and agreed to by MarkM, Andreas Gal, and Dave Herman, + * rather than the offially approved proposal page. TODO(erights): + * upgrade the ecmascript WeakMap proposal page to explain this API + * change and present to EcmaScript committee for their approval. + * + *

The first difference between the emulation here and that in + * FF6.0a1 is the presence of non enumerable {@code get___, has___, + * set___, and delete___} methods on WeakMap instances to represent + * what would be the hidden internal properties of a primitive + * implementation. Whereas the FF6.0a1 WeakMap.prototype methods + * require their {@code this} to be a genuine WeakMap instance (i.e., + * an object of {@code [[Class]]} "WeakMap}), since there is nothing + * unforgeable about the pseudo-internal method names used here, + * nothing prevents these emulated prototype methods from being + * applied to non-WeakMaps with pseudo-internal methods of the same + * names. + * + *

Another difference is that our emulated {@code + * WeakMap.prototype} is not itself a WeakMap. A problem with the + * current FF6.0a1 API is that WeakMap.prototype is itself a WeakMap + * providing ambient mutability and an ambient communications + * channel. Thus, if a WeakMap is already present and has this + * problem, repairES5.js wraps it in a safe wrappper in order to + * prevent access to this channel. (See + * PATCH_MUTABLE_FROZEN_WEAKMAP_PROTO in repairES5.js). + */ + +/** + * If this is a full secureable ES5 platform and the ES-Harmony {@code WeakMap} is + * absent, install an approximate emulation. + * + *

If WeakMap is present but cannot store some objects, use our approximate + * emulation as a wrapper. + * + *

If this is almost a secureable ES5 platform, then WeakMap.js + * should be run after repairES5.js. + * + *

See {@code WeakMap} for documentation of the garbage collection + * properties of this WeakMap emulation. + */ +(function WeakMapModule() { + "use strict"; + + if (typeof ses !== 'undefined' && ses.ok && !ses.ok()) { + // already too broken, so give up + return; } - - function tripleSwap(k, less, great) { - if(order.length > 1) { - cacheLoop([k,less,great], false, [ - "tmp=",dataRead("ptr0"),"\n", - dataWrite("ptr0", dataRead("ptr1")),"\n", - dataWrite("ptr1", dataRead("ptr2")),"\n", - dataWrite("ptr2", "tmp") - ].join("")) - code.push("++"+less, "--"+great) - } else { - code.push([ - "ptr0=",toPointer(k),"\n", - "ptr1=",toPointer(less),"\n", - "ptr2=",toPointer(great),"\n", - "++",less,"\n", - "--",great,"\n", - "tmp=", dataRead("ptr0"), "\n", - dataWrite("ptr0", dataRead("ptr1")), "\n", - dataWrite("ptr1", dataRead("ptr2")), "\n", - dataWrite("ptr2", "tmp") - ].join("")) + + /** + * In some cases (current Firefox), we must make a choice betweeen a + * WeakMap which is capable of using all varieties of host objects as + * keys and one which is capable of safely using proxies as keys. See + * comments below about HostWeakMap and DoubleWeakMap for details. + * + * This function (which is a global, not exposed to guests) marks a + * WeakMap as permitted to do what is necessary to index all host + * objects, at the cost of making it unsafe for proxies. + * + * Do not apply this function to anything which is not a genuine + * fresh WeakMap. + */ + function weakMapPermitHostObjects(map) { + // identity of function used as a secret -- good enough and cheap + if (map.permitHostObjects___) { + map.permitHostObjects___(weakMapPermitHostObjects); } } - - function swapAndDecrement(k, great) { - swapElements(k, great) - code.push("--"+great) + if (typeof ses !== 'undefined') { + ses.weakMapPermitHostObjects = weakMapPermitHostObjects; } - - code.push("if(pivots_are_equal){") - //Pivots are equal case - code.push("for(k=less;k<=great;++k){") - comparePivot("comp", "k", 1) - code.push("if(comp===0){continue}") - code.push("if(comp<0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - code.push("while(true){") - comparePivot("comp", "great", 1) - code.push("if(comp>0){") - code.push("great--") - code.push("}else if(comp<0){") - tripleSwap("k", "less", "great") - code.push("break") - code.push("}else{") - swapAndDecrement("k", "great") - code.push("break") - code.push("}") - code.push("}") - code.push("}") - code.push("}") - code.push("}else{") - //Pivots not equal case - code.push("for(k=less;k<=great;++k){") - comparePivot("comp_pivot1", "k", 1) - code.push("if(comp_pivot1<0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - comparePivot("comp_pivot2", "k", 2) - code.push("if(comp_pivot2>0){") - code.push("while(true){") - comparePivot("comp", "great", 2) - code.push("if(comp>0){") - code.push("if(--great1) { - cacheLoop([mem_dest, pivot_dest], true, [ - dataWrite("ptr0", dataRead("ptr1")), "\n", - dataWrite("ptr1", ["pivot",pivot,"[pivot_ptr]"].join("")) - ].join("")) + + // IE 11 has no Proxy but has a broken WeakMap such that we need to patch + // it using DoubleWeakMap; this flag tells DoubleWeakMap so. + var doubleWeakMapCheckSilentFailure = false; + + // Check if there is already a good-enough WeakMap implementation, and if so + // exit without replacing it. + if (typeof WeakMap === 'function') { + var HostWeakMap = WeakMap; + // There is a WeakMap -- is it good enough? + if (typeof navigator !== 'undefined' && + /Firefox/.test(navigator.userAgent)) { + // We're now *assuming not*, because as of this writing (2013-05-06) + // Firefox's WeakMaps have a miscellany of objects they won't accept, and + // we don't want to make an exhaustive list, and testing for just one + // will be a problem if that one is fixed alone (as they did for Event). + + // If there is a platform that we *can* reliably test on, here's how to + // do it: + // var problematic = ... ; + // var testHostMap = new HostWeakMap(); + // try { + // testHostMap.set(problematic, 1); // Firefox 20 will throw here + // if (testHostMap.get(problematic) === 1) { + // return; + // } + // } catch (e) {} + } else { - code.push( - dataWrite(toPointer(mem_dest), dataRead(toPointer(pivot_dest))), - dataWrite(toPointer(pivot_dest), "pivot"+pivot)) + // IE 11 bug: WeakMaps silently fail to store frozen objects. + var testMap = new HostWeakMap(); + var testObject = Object.freeze({}); + testMap.set(testObject, 1); + if (testMap.get(testObject) !== 1) { + doubleWeakMapCheckSilentFailure = true; + // Fall through to installing our WeakMap. + } else { + module.exports = WeakMap; + return; + } } } - - storePivot("left", "(less-1)", 1) - storePivot("right", "(great+1)", 2) - //Recursive sort call - function doSort(left, right) { - code.push([ - "if((",right,"-",left,")<=",INSERTION_SORT_THRESHOLD,"){\n", - "insertionSort(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", - "}else{\n", - funcName, "(", left, ",", right, ",data,offset,", shapeArgs(order.length).join(","), ")\n", - "}" - ].join("")) + var hop = Object.prototype.hasOwnProperty; + var gopn = Object.getOwnPropertyNames; + var defProp = Object.defineProperty; + var isExtensible = Object.isExtensible; + + /** + * Security depends on HIDDEN_NAME being both unguessable and + * undiscoverable by untrusted code. + * + *

Given the known weaknesses of Math.random() on existing + * browsers, it does not generate unguessability we can be confident + * of. + * + *

It is the monkey patching logic in this file that is intended + * to ensure undiscoverability. The basic idea is that there are + * three fundamental means of discovering properties of an object: + * The for/in loop, Object.keys(), and Object.getOwnPropertyNames(), + * as well as some proposed ES6 extensions that appear on our + * whitelist. The first two only discover enumerable properties, and + * we only use HIDDEN_NAME to name a non-enumerable property, so the + * only remaining threat should be getOwnPropertyNames and some + * proposed ES6 extensions that appear on our whitelist. We monkey + * patch them to remove HIDDEN_NAME from the list of properties they + * returns. + * + *

TODO(erights): On a platform with built-in Proxies, proxies + * could be used to trap and thereby discover the HIDDEN_NAME, so we + * need to monkey patch Proxy.create, Proxy.createFunction, etc, in + * order to wrap the provided handler with the real handler which + * filters out all traps using HIDDEN_NAME. + * + *

TODO(erights): Revisit Mike Stay's suggestion that we use an + * encapsulated function at a not-necessarily-secret name, which + * uses the Stiegler shared-state rights amplification pattern to + * reveal the associated value only to the WeakMap in which this key + * is associated with that value. Since only the key retains the + * function, the function can also remember the key without causing + * leakage of the key, so this doesn't violate our general gc + * goals. In addition, because the name need not be a guarded + * secret, we could efficiently handle cross-frame frozen keys. + */ + var HIDDEN_NAME_PREFIX = 'weakmap:'; + var HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'ident:' + Math.random() + '___'; + + if (typeof crypto !== 'undefined' && + typeof crypto.getRandomValues === 'function' && + typeof ArrayBuffer === 'function' && + typeof Uint8Array === 'function') { + var ab = new ArrayBuffer(25); + var u8s = new Uint8Array(ab); + crypto.getRandomValues(u8s); + HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'rand:' + + Array.prototype.map.call(u8s, function(u8) { + return (u8 % 36).toString(36); + }).join('') + '___'; } - doSort("left", "(less-2)") - doSort("(great+2)", "right") - - //If pivots are equal, then early out - code.push("if(pivots_are_equal){") - cleanUp() - code.push("return") - code.push("}") - - function walkPointer(ptr, pivot, body) { - if(order.length > 1) { - code.push(["__l",++labelCounter,":while(true){"].join("")) - cacheLoop([ptr], true, [ - "if(", dataRead("ptr0"), "!==pivot", pivot, "[pivot_ptr]){break __l", labelCounter, "}" - ].join("")) - code.push(body, "}") - } else { - code.push(["while(", dataRead(toPointer(ptr)), "===pivot", pivot, "){", body, "}"].join("")) + + function isNotHiddenName(name) { + return !( + name.substr(0, HIDDEN_NAME_PREFIX.length) == HIDDEN_NAME_PREFIX && + name.substr(name.length - 3) === '___'); + } + + /** + * Monkey patch getOwnPropertyNames to avoid revealing the + * HIDDEN_NAME. + * + *

The ES5.1 spec requires each name to appear only once, but as + * of this writing, this requirement is controversial for ES6, so we + * made this code robust against this case. If the resulting extra + * search turns out to be expensive, we can probably relax this once + * ES6 is adequately supported on all major browsers, iff no browser + * versions we support at that time have relaxed this constraint + * without providing built-in ES6 WeakMaps. + */ + defProp(Object, 'getOwnPropertyNames', { + value: function fakeGetOwnPropertyNames(obj) { + return gopn(obj).filter(isNotHiddenName); } + }); + + /** + * getPropertyNames is not in ES5 but it is proposed for ES6 and + * does appear in our whitelist, so we need to clean it too. + */ + if ('getPropertyNames' in Object) { + var originalGetPropertyNames = Object.getPropertyNames; + defProp(Object, 'getPropertyNames', { + value: function fakeGetPropertyNames(obj) { + return originalGetPropertyNames(obj).filter(isNotHiddenName); + } + }); } - - //Check bounds - code.push("if(lessindex5){") - - walkPointer("less", 1, "++less") - walkPointer("great", 2, "--great") - - code.push("for(k=less;k<=great;++k){") - comparePivot("comp_pivot1", "k", 1) - code.push("if(comp_pivot1===0){") - code.push("if(k!==less){") - swapElements("k", "less") - code.push("}") - code.push("++less") - code.push("}else{") - comparePivot("comp_pivot2", "k", 2) - code.push("if(comp_pivot2===0){") - code.push("while(true){") - comparePivot("comp", "great", 2) - code.push("if(comp===0){") - code.push("if(--great 1 && allocator) { - var compiled = new Function("insertionSort", "malloc", "free", code.join("\n")) - return compiled(insertionSort, allocator[0], allocator[1]) + + /** + *

To treat objects as identity-keys with reasonable efficiency + * on ES5 by itself (i.e., without any object-keyed collections), we + * need to add a hidden property to such key objects when we + * can. This raises several issues: + *

    + *
  • Arranging to add this property to objects before we lose the + * chance, and + *
  • Hiding the existence of this new property from most + * JavaScript code. + *
  • Preventing certification theft, where one object is + * created falsely claiming to be the key of an association + * actually keyed by another object. + *
  • Preventing value theft, where untrusted code with + * access to a key object but not a weak map nevertheless + * obtains access to the value associated with that key in that + * weak map. + *
+ * We do so by + *
    + *
  • Making the name of the hidden property unguessable, so "[]" + * indexing, which we cannot intercept, cannot be used to access + * a property without knowing the name. + *
  • Making the hidden property non-enumerable, so we need not + * worry about for-in loops or {@code Object.keys}, + *
  • monkey patching those reflective methods that would + * prevent extensions, to add this hidden property first, + *
  • monkey patching those methods that would reveal this + * hidden property. + *
+ * Unfortunately, because of same-origin iframes, we cannot reliably + * add this hidden property before an object becomes + * non-extensible. Instead, if we encounter a non-extensible object + * without a hidden record that we can detect (whether or not it has + * a hidden record stored under a name secret to us), then we just + * use the key object itself to represent its identity in a brute + * force leaky map stored in the weak map, losing all the advantages + * of weakness for these. + */ + function getHiddenRecord(key) { + if (key !== Object(key)) { + throw new TypeError('Not an object: ' + key); + } + var hiddenRecord = key[HIDDEN_NAME]; + if (hiddenRecord && hiddenRecord.key === key) { return hiddenRecord; } + if (!isExtensible(key)) { + // Weak map must brute force, as explained in doc-comment above. + return void 0; + } + + // The hiddenRecord and the key point directly at each other, via + // the "key" and HIDDEN_NAME properties respectively. The key + // field is for quickly verifying that this hidden record is an + // own property, not a hidden record from up the prototype chain. + // + // NOTE: Because this WeakMap emulation is meant only for systems like + // SES where Object.prototype is frozen without any numeric + // properties, it is ok to use an object literal for the hiddenRecord. + // This has two advantages: + // * It is much faster in a performance critical place + // * It avoids relying on Object.create(null), which had been + // problematic on Chrome 28.0.1480.0. See + // https://code.google.com/p/google-caja/issues/detail?id=1687 + hiddenRecord = { key: key }; + + // When using this WeakMap emulation on platforms where + // Object.prototype might not be frozen and Object.create(null) is + // reliable, use the following two commented out lines instead. + // hiddenRecord = Object.create(null); + // hiddenRecord.key = key; + + // Please contact us if you need this to work on platforms where + // Object.prototype might not be frozen and + // Object.create(null) might not be reliable. + + try { + defProp(key, HIDDEN_NAME, { + value: hiddenRecord, + writable: false, + enumerable: false, + configurable: false + }); + return hiddenRecord; + } catch (error) { + // Under some circumstances, isExtensible seems to misreport whether + // the HIDDEN_NAME can be defined. + // The circumstances have not been isolated, but at least affect + // Node.js v0.10.26 on TravisCI / Linux, but not the same version of + // Node.js on OS X. + return void 0; + } } - var compiled = new Function("insertionSort", code.join("\n")) - return compiled(insertionSort) -} -function compileSort(order, dtype) { - var code = ["'use strict'"] - var funcName = ["ndarraySortWrapper", order.join("d"), dtype].join("") - var funcArgs = [ "array" ] - - code.push(["function ", funcName, "(", funcArgs.join(","), "){"].join("")) - - //Unpack local variables from array - var vars = ["data=array.data,offset=array.offset|0,shape=array.shape,stride=array.stride"] - for(var i=0; iThe monkey patched versions throw a TypeError if their + * argument is not an object, so it should only be done to functions + * that should throw a TypeError anyway if their argument is not an + * object. + */ + (function(){ + var oldFreeze = Object.freeze; + defProp(Object, 'freeze', { + value: function identifyingFreeze(obj) { + getHiddenRecord(obj); + return oldFreeze(obj); + } + }); + var oldSeal = Object.seal; + defProp(Object, 'seal', { + value: function identifyingSeal(obj) { + getHiddenRecord(obj); + return oldSeal(obj); + } + }); + var oldPreventExtensions = Object.preventExtensions; + defProp(Object, 'preventExtensions', { + value: function identifyingPreventExtensions(obj) { + getHiddenRecord(obj); + return oldPreventExtensions(obj); + } + }); + })(); + + function constFunc(func) { + func.prototype = null; + return Object.freeze(func); } - - var scratch_stride = new Array(order.length) - var nprod = [] - for(var i=0; i 0) { - vars.push(["d",j,"=s",j,"-d",p,"*n",p].join("")) + + var nextId = 0; + + var OurWeakMap = function() { + if (!(this instanceof OurWeakMap)) { // approximate test for new ...() + calledAsFunctionWarning(); + } + + // We are currently (12/25/2012) never encountering any prematurely + // non-extensible keys. + var keys = []; // brute force for prematurely non-extensible keys. + var values = []; // brute force for corresponding values. + var id = nextId++; + + function get___(key, opt_default) { + var index; + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + return id in hiddenRecord ? hiddenRecord[id] : opt_default; } else { - vars.push(["d",j,"=s",j].join("")) + index = keys.indexOf(key); + return index >= 0 ? values[index] : opt_default; } - p = j } - var k = order.length-1-i - if(k !== 0) { - if(q > 0) { - vars.push(["e",k,"=s",k,"-e",q,"*n",q, - ",f",k,"=",scratch_stride[k],"-f",q,"*n",q].join("")) + + function has___(key) { + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + return id in hiddenRecord; } else { - vars.push(["e",k,"=s",k,",f",k,"=",scratch_stride[k]].join("")) + return keys.indexOf(key) >= 0; } - q = k } - } - - //Declare local variables - code.push("var " + vars.join(",")) - - //Create arguments for subroutine - var sortArgs = ["0", "n0-1", "data", "offset"].concat(shapeArgs(order.length)) - - //Call main sorting routine - code.push([ - "if(n0<=",INSERTION_SORT_THRESHOLD,"){", - "insertionSort(", sortArgs.join(","), ")}else{", - "quickSort(", sortArgs.join(","), - ")}" - ].join("")) - - //Return - code.push("}return " + funcName) - - //Link everything together - var result = new Function("insertionSort", "quickSort", code.join("\n")) - var insertionSort = createInsertionSort(order, dtype) - var quickSort = createQuickSort(order, dtype, insertionSort) - return result(insertionSort, quickSort) -} - -module.exports = compileSort -},{"typedarray-pool":277}],274:[function(require,module,exports){ -"use strict" - -var compile = require("./lib/compile_sort.js") -var CACHE = {} - -function sort(array) { - var order = array.order - var dtype = array.dtype - var typeSig = [order, dtype ] - var typeName = typeSig.join(":") - var compiled = CACHE[typeName] - if(!compiled) { - CACHE[typeName] = compiled = compile(order, dtype) - } - compiled(array) - return array -} -module.exports = sort -},{"./lib/compile_sort.js":273}],275:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],276:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],277:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":275,"buffer":48,"dup":102}],278:[function(require,module,exports){ -'use strict' + function set___(key, value) { + var index; + var hiddenRecord = getHiddenRecord(key); + if (hiddenRecord) { + hiddenRecord[id] = value; + } else { + index = keys.indexOf(key); + if (index >= 0) { + values[index] = value; + } else { + // Since some browsers preemptively terminate slow turns but + // then continue computing with presumably corrupted heap + // state, we here defensively get keys.length first and then + // use it to update both the values and keys arrays, keeping + // them in sync. + index = keys.length; + values[index] = value; + // If we crash here, values will be one longer than keys. + keys[index] = key; + } + } + return this; + } -module.exports = createBoxes + function delete___(key) { + var hiddenRecord = getHiddenRecord(key); + var index, lastIndex; + if (hiddenRecord) { + return id in hiddenRecord && delete hiddenRecord[id]; + } else { + index = keys.indexOf(key); + if (index < 0) { + return false; + } + // Since some browsers preemptively terminate slow turns but + // then continue computing with potentially corrupted heap + // state, we here defensively get keys.length first and then use + // it to update both the keys and the values array, keeping + // them in sync. We update the two with an order of assignments, + // such that any prefix of these assignments will preserve the + // key/value correspondence, either before or after the delete. + // Note that this needs to work correctly when index === lastIndex. + lastIndex = keys.length - 1; + keys[index] = void 0; + // If we crash here, there's a void 0 in the keys array, but + // no operation will cause a "keys.indexOf(void 0)", since + // getHiddenRecord(void 0) will always throw an error first. + values[index] = values[lastIndex]; + // If we crash here, values[index] cannot be found here, + // because keys[index] is void 0. + keys[index] = keys[lastIndex]; + // If index === lastIndex and we crash here, then keys[index] + // is still void 0, since the aliasing killed the previous key. + keys.length = lastIndex; + // If we crash here, keys will be one shorter than values. + values.length = lastIndex; + return true; + } + } -var createBuffer = require('gl-buffer') -var createShader = require('gl-shader') + return Object.create(OurWeakMap.prototype, { + get___: { value: constFunc(get___) }, + has___: { value: constFunc(has___) }, + set___: { value: constFunc(set___) }, + delete___: { value: constFunc(delete___) } + }); + }; -var shaders = require('./shaders') + OurWeakMap.prototype = Object.create(Object.prototype, { + get: { + /** + * Return the value most recently associated with key, or + * opt_default if none. + */ + value: function get(key, opt_default) { + return this.get___(key, opt_default); + }, + writable: true, + configurable: true + }, -function Boxes(plot, vbo, shader) { - this.plot = plot - this.vbo = vbo - this.shader = shader -} + has: { + /** + * Is there a value associated with key in this WeakMap? + */ + value: function has(key) { + return this.has___(key); + }, + writable: true, + configurable: true + }, -var proto = Boxes.prototype + set: { + /** + * Associate value with key in this WeakMap, overwriting any + * previous association if present. + */ + value: function set(key, value) { + return this.set___(key, value); + }, + writable: true, + configurable: true + }, -proto.bind = function() { - var shader = this.shader - this.vbo.bind() - this.shader.bind() - shader.attributes.coord.pointer() - shader.uniforms.screenBox = this.plot.screenBox -} + 'delete': { + /** + * Remove any association for key in this WeakMap, returning + * whether there was one. + * + *

Note that the boolean return here does not work like the + * {@code delete} operator. The {@code delete} operator returns + * whether the deletion succeeds at bringing about a state in + * which the deleted property is absent. The {@code delete} + * operator therefore returns true if the property was already + * absent, whereas this {@code delete} method returns false if + * the association was already absent. + */ + value: function remove(key) { + return this.delete___(key); + }, + writable: true, + configurable: true + } + }); -proto.drawBox = (function() { - var lo = [0,0] - var hi = [0,0] - return function(loX, loY, hiX, hiY, color) { - var plot = this.plot - var shader = this.shader - var gl = plot.gl + if (typeof HostWeakMap === 'function') { + (function() { + // If we got here, then the platform has a WeakMap but we are concerned + // that it may refuse to store some key types. Therefore, make a map + // implementation which makes use of both as possible. - lo[0] = loX - lo[1] = loY - hi[0] = hiX - hi[1] = hiY + // In this mode we are always using double maps, so we are not proxy-safe. + // This combination does not occur in any known browser, but we had best + // be safe. + if (doubleWeakMapCheckSilentFailure && typeof Proxy !== 'undefined') { + Proxy = undefined; + } - shader.uniforms.lo = lo - shader.uniforms.hi = hi - shader.uniforms.color = color + function DoubleWeakMap() { + if (!(this instanceof OurWeakMap)) { // approximate test for new ...() + calledAsFunctionWarning(); + } - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) - } -}()) + // Preferable, truly weak map. + var hmap = new HostWeakMap(); -proto.dispose = function() { - this.vbo.dispose() - this.shader.dispose() -} + // Our hidden-property-based pseudo-weak-map. Lazily initialized in the + // 'set' implementation; thus we can avoid performing extra lookups if + // we know all entries actually stored are entered in 'hmap'. + var omap = undefined; -function createBoxes(plot) { - var gl = plot.gl - var vbo = createBuffer(gl, [ - 0,0, - 0,1, - 1,0, - 1,1]) - var shader = createShader(gl, shaders.boxVert, shaders.lineFrag) - return new Boxes(plot, vbo, shader) -} + // Hidden-property maps are not compatible with proxies because proxies + // can observe the hidden name and either accidentally expose it or fail + // to allow the hidden property to be set. Therefore, we do not allow + // arbitrary WeakMaps to switch to using hidden properties, but only + // those which need the ability, and unprivileged code is not allowed + // to set the flag. + // + // (Except in doubleWeakMapCheckSilentFailure mode in which case we + // disable proxies.) + var enableSwitching = false; -},{"./shaders":281,"gl-buffer":284,"gl-shader":299}],279:[function(require,module,exports){ -'use strict' + function dget(key, opt_default) { + if (omap) { + return hmap.has(key) ? hmap.get(key) + : omap.get___(key, opt_default); + } else { + return hmap.get(key, opt_default); + } + } -module.exports = createGrid + function dhas(key) { + return hmap.has(key) || (omap ? omap.has___(key) : false); + } -var createBuffer = require('gl-buffer') -var createShader = require('gl-shader') -var bsearch = require('binary-search-bounds') -var shaders = require('./shaders') + var dset; + if (doubleWeakMapCheckSilentFailure) { + dset = function(key, value) { + hmap.set(key, value); + if (!hmap.has(key)) { + if (!omap) { omap = new OurWeakMap(); } + omap.set(key, value); + } + return this; + }; + } else { + dset = function(key, value) { + if (enableSwitching) { + try { + hmap.set(key, value); + } catch (e) { + if (!omap) { omap = new OurWeakMap(); } + omap.set___(key, value); + } + } else { + hmap.set(key, value); + } + return this; + }; + } -function Grid(plot, vbo, shader, tickShader) { - this.plot = plot - this.vbo = vbo - this.shader = shader - this.tickShader = tickShader - this.ticks = [[], []] -} + function ddelete(key) { + var result = !!hmap['delete'](key); + if (omap) { return omap.delete___(key) || result; } + return result; + } -function compareTickNum(a, b) { - return a - b -} + return Object.create(OurWeakMap.prototype, { + get___: { value: constFunc(dget) }, + has___: { value: constFunc(dhas) }, + set___: { value: constFunc(dset) }, + delete___: { value: constFunc(ddelete) }, + permitHostObjects___: { value: constFunc(function(token) { + if (token === weakMapPermitHostObjects) { + enableSwitching = true; + } else { + throw new Error('bogus call to permitHostObjects___'); + } + })} + }); + } + DoubleWeakMap.prototype = OurWeakMap.prototype; + module.exports = DoubleWeakMap; -var proto = Grid.prototype + // define .constructor to hide OurWeakMap ctor + Object.defineProperty(WeakMap.prototype, 'constructor', { + value: WeakMap, + enumerable: false, // as default .constructor is + configurable: true, + writable: true + }); + })(); + } else { + // There is no host WeakMap, so we must use the emulation. -proto.draw = (function() { + // Emulated WeakMaps are incompatible with native proxies (because proxies + // can observe the hidden name), so we must disable Proxy usage (in + // ArrayLike and Domado, currently). + if (typeof Proxy !== 'undefined') { + Proxy = undefined; + } - var DATA_SHIFT = [0,0] - var DATA_SCALE = [0,0] - var DATA_AXIS = [0,0] + module.exports = OurWeakMap; + } +})(); - return function() { - var plot = this.plot - var vbo = this.vbo - var shader = this.shader - var ticks = this.ticks - var gl = plot.gl - var bounds = plot._tickBounds - var dataBox = plot.dataBox - var viewPixels = plot.viewBox - var lineWidth = plot.gridLineWidth - var gridColor = plot.gridLineColor - var gridEnable = plot.gridLineEnable - var pixelRatio = plot.pixelRatio +},{}],126:[function(require,module,exports){ +'use strict' - for(var i=0; i<2; ++i) { - var lo = bounds[i] - var hi = bounds[i+2] - var boundScale = hi - lo - var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) - var dataWidth = dataBox[i+2] - dataBox[i] - DATA_SCALE[i] = 2.0 * boundScale / dataWidth - DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth - } +var weakMap = typeof WeakMap === 'undefined' ? require('weak-map') : WeakMap +var createBuffer = require('gl-buffer') +var createVAO = require('gl-vao') - shader.bind() - vbo.bind() - shader.attributes.dataCoord.pointer() - shader.uniforms.dataShift = DATA_SHIFT - shader.uniforms.dataScale = DATA_SCALE +var TriangleCache = new weakMap() - var offset = 0 - for(var i=0; i<2; ++i) { - DATA_AXIS[0] = DATA_AXIS[1] = 0 - DATA_AXIS[i] = 1 - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.lineWidth = lineWidth[i] / (viewPixels[i+2] - viewPixels[i]) * pixelRatio - shader.uniforms.color = gridColor[i] +function createABigTriangle(gl) { - var size = ticks[i].length * 6 - if(gridEnable[i]) { - gl.drawArrays(gl.TRIANGLES, offset, size) + var triangleVAO = TriangleCache.get(gl) + if(!triangleVAO || !gl.isBuffer(triangleVAO._triangleBuffer.buffer)) { + var buf = createBuffer(gl, new Float32Array([-1, -1, -1, 4, 4, -1])) + triangleVAO = createVAO(gl, [ + { buffer: buf, + type: gl.FLOAT, + size: 2 } - offset += size - } + ]) + triangleVAO._triangleBuffer = buf + TriangleCache.set(gl, triangleVAO) } -})() + triangleVAO.bind() + gl.drawArrays(gl.TRIANGLES, 0, 3) + triangleVAO.unbind() +} -proto.drawTickMarks = (function() { - var DATA_SHIFT = [0,0] - var DATA_SCALE = [0,0] - var X_AXIS = [1,0] - var Y_AXIS = [0,1] - var SCR_OFFSET = [0,0] - var TICK_SCALE = [0,0] +module.exports = createABigTriangle - return function() { - var plot = this.plot - var vbo = this.vbo - var shader = this.tickShader - var ticks = this.ticks - var gl = plot.gl - var bounds = plot._tickBounds - var dataBox = plot.dataBox - var viewBox = plot.viewBox - var pixelRatio = plot.pixelRatio - var screenBox = plot.screenBox +},{"gl-buffer":75,"gl-vao":189,"weak-map":125}],127:[function(require,module,exports){ +'use strict' - var screenWidth = screenBox[2] - screenBox[0] - var screenHeight = screenBox[3] - screenBox[1] - var viewWidth = viewBox[2] - viewBox[0] - var viewHeight = viewBox[3] - viewBox[1] +module.exports = createAxes - for(var i=0; i<2; ++i) { - var lo = bounds[i] - var hi = bounds[i+2] - var boundScale = hi - lo - var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) - var dataWidth = (dataBox[i+2] - dataBox[i]) - DATA_SCALE[i] = 2.0 * boundScale / dataWidth - DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth - } +var createText = require('./lib/text.js') +var createLines = require('./lib/lines.js') +var createBackground = require('./lib/background.js') +var getCubeProperties = require('./lib/cube.js') +var Ticks = require('./lib/ticks.js') - DATA_SCALE[0] *= viewWidth / screenWidth - DATA_SHIFT[0] *= viewWidth / screenWidth +var identity = new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1]) - DATA_SCALE[1] *= viewHeight / screenHeight - DATA_SHIFT[1] *= viewHeight / screenHeight +function copyVec3(a, b) { + a[0] = b[0] + a[1] = b[1] + a[2] = b[2] + return a +} - shader.bind() - vbo.bind() +function Axes(gl) { + this.gl = gl - shader.attributes.dataCoord.pointer() + this.pixelRatio = 1 - var uniforms = shader.uniforms - uniforms.dataShift = DATA_SHIFT - uniforms.dataScale = DATA_SCALE + this.bounds = [ [-10, -10, -10], + [ 10, 10, 10] ] + this.ticks = [ [], [], [] ] + this.autoTicks = true + this.tickSpacing = [ 1, 1, 1 ] - var tickMarkLength = plot.tickMarkLength - var tickMarkWidth = plot.tickMarkWidth - var tickMarkColor = plot.tickMarkColor + this.tickEnable = [ true, true, true ] + this.tickFont = [ 'sans-serif', 'sans-serif', 'sans-serif' ] + this.tickSize = [ 12, 12, 12 ] + this.tickAngle = [ 0, 0, 0 ] + this.tickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.tickPad = [ 10, 10, 10 ] - var xTicksOffset = 0 - var yTicksOffset = ticks[0].length * 6 + this.lastCubeProps = { + cubeEdges: [0,0,0], + axis: [0,0,0] + } - var xStart = Math.min(bsearch.ge(ticks[0], (dataBox[0] - bounds[0]) / (bounds[2] - bounds[0]), compareTickNum), ticks[0].length) - var xEnd = Math.min(bsearch.gt(ticks[0], (dataBox[2] - bounds[0]) / (bounds[2] - bounds[0]), compareTickNum), ticks[0].length) - var xOffset = xTicksOffset + 6 * xStart - var xCount = 6 * Math.max(0, xEnd - xStart) + this.labels = [ 'x', 'y', 'z' ] + this.labelEnable = [ true, true, true ] + this.labelFont = 'sans-serif' + this.labelSize = [ 20, 20, 20 ] + this.labelAngle = [ 0, 0, 0 ] + this.labelColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.labelPad = [ 10, 10, 10 ] - var yStart = Math.min(bsearch.ge(ticks[1], (dataBox[1] - bounds[1]) / (bounds[3] - bounds[1]), compareTickNum), ticks[1].length) - var yEnd = Math.min(bsearch.gt(ticks[1], (dataBox[3] - bounds[1]) / (bounds[3] - bounds[1]), compareTickNum), ticks[1].length) - var yOffset = yTicksOffset + 6 * yStart - var yCount = 6 * Math.max(0, yEnd - yStart) + this.lineEnable = [ true, true, true ] + this.lineMirror = [ false, false, false ] + this.lineWidth = [ 1, 1, 1 ] + this.lineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - SCR_OFFSET[0] = 2.0 * (viewBox[0] - tickMarkLength[1]) / screenWidth - 1.0 - SCR_OFFSET[1] = (viewBox[3] + viewBox[1]) / screenHeight - 1.0 - TICK_SCALE[0] = tickMarkLength[1] * pixelRatio / screenWidth - TICK_SCALE[1] = tickMarkWidth[1] * pixelRatio / screenHeight + this.lineTickEnable = [ true, true, true ] + this.lineTickMirror = [ false, false, false ] + this.lineTickLength = [ 0, 0, 0 ] + this.lineTickWidth = [ 1, 1, 1 ] + this.lineTickColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - uniforms.color = tickMarkColor[1] - uniforms.tickScale = TICK_SCALE - uniforms.dataAxis = Y_AXIS - uniforms.screenOffset = SCR_OFFSET - gl.drawArrays(gl.TRIANGLES, yOffset, yCount) + this.gridEnable = [ true, true, true ] + this.gridWidth = [ 1, 1, 1 ] + this.gridColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] - SCR_OFFSET[0] = (viewBox[2] + viewBox[0]) / screenWidth - 1.0 - SCR_OFFSET[1] = 2.0 * (viewBox[1] - tickMarkLength[0]) / screenHeight - 1.0 - TICK_SCALE[0] = tickMarkWidth[0] * pixelRatio / screenWidth - TICK_SCALE[1] = tickMarkLength[0] * pixelRatio / screenHeight + this.zeroEnable = [ true, true, true ] + this.zeroLineColor = [ [0,0,0,1], [0,0,0,1], [0,0,0,1] ] + this.zeroLineWidth = [ 2, 2, 2 ] - uniforms.color = tickMarkColor[0] - uniforms.tickScale = TICK_SCALE - uniforms.dataAxis = X_AXIS - uniforms.screenOffset = SCR_OFFSET - gl.drawArrays(gl.TRIANGLES, xOffset, xCount) + this.backgroundEnable = [ false, false, false ] + this.backgroundColor = [ [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5], + [0.8, 0.8, 0.8, 0.5] ] - SCR_OFFSET[0] = 2.0 * (viewBox[2] + tickMarkLength[3]) / screenWidth - 1.0 - SCR_OFFSET[1] = (viewBox[3] + viewBox[1]) / screenHeight - 1.0 - TICK_SCALE[0] = tickMarkLength[3] * pixelRatio / screenWidth - TICK_SCALE[1] = tickMarkWidth[3] * pixelRatio / screenHeight + this._firstInit = true + this._text = null + this._lines = null + this._background = createBackground(gl) +} - uniforms.color = tickMarkColor[3] - uniforms.tickScale = TICK_SCALE - uniforms.dataAxis = Y_AXIS - uniforms.screenOffset = SCR_OFFSET - gl.drawArrays(gl.TRIANGLES, yOffset, yCount) +var proto = Axes.prototype - SCR_OFFSET[0] = (viewBox[2] + viewBox[0]) / screenWidth - 1.0 - SCR_OFFSET[1] = 2.0 * (viewBox[3] + tickMarkLength[2]) / screenHeight - 1.0 - TICK_SCALE[0] = tickMarkWidth[2] * pixelRatio / screenWidth - TICK_SCALE[1] = tickMarkLength[2] * pixelRatio / screenHeight +proto.update = function(options) { + options = options || {} - uniforms.color = tickMarkColor[2] - uniforms.tickScale = TICK_SCALE - uniforms.dataAxis = X_AXIS - uniforms.screenOffset = SCR_OFFSET - gl.drawArrays(gl.TRIANGLES, xOffset, xCount) + //Option parsing helper functions + function parseOption(nest, cons, name) { + if(name in options) { + var opt = options[name] + var prev = this[name] + var next + if(nest ? (Array.isArray(opt) && Array.isArray(opt[0])) : + Array.isArray(opt) ) { + this[name] = next = [ cons(opt[0]), cons(opt[1]), cons(opt[2]) ] + } else { + this[name] = next = [ cons(opt), cons(opt), cons(opt) ] + } + for(var i=0; i<3; ++i) { + if(next[i] !== prev[i]) { + return true + } + } + } + return false } -})() -proto.update = (function() { - var OFFSET_X = [1, 1, -1, -1, 1, -1] - var OFFSET_Y = [1, -1, 1, 1, -1, -1] + var NUMBER = parseOption.bind(this, false, Number) + var BOOLEAN = parseOption.bind(this, false, Boolean) + var STRING = parseOption.bind(this, false, String) + var COLOR = parseOption.bind(this, true, function(v) { + if(Array.isArray(v)) { + if(v.length === 3) { + return [ +v[0], +v[1], +v[2], 1.0 ] + } else if(v.length === 4) { + return [ +v[0], +v[1], +v[2], +v[3] ] + } + } + return [ 0, 0, 0, 1 ] + }) - return function(options) { - var ticks = options.ticks + //Tick marks and bounds + var nextTicks + var ticksUpdate = false + var boundsChanged = false + if('bounds' in options) { var bounds = options.bounds - var data = new Float32Array(6 * 3 * (ticks[0].length + ticks[1].length)) - - var zeroLineEnable = this.plot.zeroLineEnable - - var ptr = 0 - var gridTicks = [[], []] - for(var dim=0; dim<2; ++dim) { - var localTicks = gridTicks[dim] - var axisTicks = ticks[dim] - var lo = bounds[dim] - var hi = bounds[dim+2] - for(var i=0; i 0) { + c[j] = -1 + d[j] = 0 + } else { + c[j] = 0 + d[j] = +1 + } } -}()) - -proto.dispose = function() { - this.vbo.dispose() - this.shader.dispose() } -function createLines(plot) { - var gl = plot.gl - var vbo = createBuffer(gl, [ - -1,-1, - -1,1, - 1,-1, - 1,1]) - var shader = createShader(gl, shaders.lineVert, shaders.lineFrag) - var lines = new Lines(plot, vbo, shader) - return lines +var CUBE_ENABLE = [0,0,0] +var DEFAULT_PARAMS = { + model: identity, + view: identity, + projection: identity } -},{"./shaders":281,"gl-buffer":284,"gl-shader":299}],281:[function(require,module,exports){ -'use strict' +proto.isOpaque = function() { + return true +} +proto.isTransparent = function() { + return false +} +proto.drawTransparent = function(params) {} -var FRAGMENT = "#define GLSLIFY 1\nprecision lowp float;\nuniform vec4 color;\nvoid main() {\n gl_FragColor = vec4(color.xyz * color.w, color.w);\n}\n" -module.exports = { - lineVert: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 coord;\n\nuniform vec4 screenBox;\nuniform vec2 start, end;\nuniform float width;\n\nvec2 perp(vec2 v) {\n return vec2(v.y, -v.x);\n}\n\nvec2 screen(vec2 v) {\n return 2.0 * (v - screenBox.xy) / (screenBox.zw - screenBox.xy) - 1.0;\n}\n\nvoid main() {\n vec2 delta = normalize(perp(start - end));\n vec2 offset = mix(start, end, 0.5 * (coord.y+1.0));\n gl_Position = vec4(screen(offset + 0.5 * width * delta * coord.x), 0, 1);\n}\n", - lineFrag: FRAGMENT, - textVert: "#define GLSLIFY 1\nattribute vec3 textCoordinate;\n\nuniform vec2 dataScale, dataShift, dataAxis, screenOffset, textScale;\nuniform float angle;\n\nvoid main() {\n float dataOffset = textCoordinate.z;\n vec2 glyphOffset = textCoordinate.xy;\n mat2 glyphMatrix = mat2(cos(angle), sin(angle), -sin(angle), cos(angle));\n vec2 screenCoordinate = dataAxis * (dataScale * dataOffset + dataShift) +\n glyphMatrix * glyphOffset * textScale + screenOffset;\n gl_Position = vec4(screenCoordinate, 0, 1);\n}\n", - textFrag: FRAGMENT, - gridVert: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 dataCoord;\n\nuniform vec2 dataAxis, dataShift, dataScale;\nuniform float lineWidth;\n\nvoid main() {\n vec2 pos = dataAxis * (dataScale * dataCoord.x + dataShift);\n pos += 10.0 * dataCoord.y * vec2(dataAxis.y, -dataAxis.x) + dataCoord.z * lineWidth;\n gl_Position = vec4(pos, 0, 1);\n}\n", - gridFrag: FRAGMENT, - boxVert: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 coord;\n\nuniform vec4 screenBox;\nuniform vec2 lo, hi;\n\nvec2 screen(vec2 v) {\n return 2.0 * (v - screenBox.xy) / (screenBox.zw - screenBox.xy) - 1.0;\n}\n\nvoid main() {\n gl_Position = vec4(screen(mix(lo, hi, coord)), 0, 1);\n}\n", - tickVert: "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 dataCoord;\n\nuniform vec2 dataAxis, dataShift, dataScale, screenOffset, tickScale;\n\nvoid main() {\n vec2 pos = dataAxis * (dataScale * dataCoord.x + dataShift);\n gl_Position = vec4(pos + tickScale*dataCoord.yz + screenOffset, 0, 1);\n}\n" -} +var PRIMAL_MINOR = [0,0,0] +var MIRROR_MINOR = [0,0,0] +var PRIMAL_OFFSET = [0,0,0] -},{}],282:[function(require,module,exports){ -'use strict' +proto.draw = function(params) { + params = params || DEFAULT_PARAMS -module.exports = createTextElements + var gl = this.gl -var createBuffer = require('gl-buffer') -var createShader = require('gl-shader') -var getText = require('text-cache') -var bsearch = require('binary-search-bounds') -var shaders = require('./shaders') + //Geometry for camera and axes + var model = params.model || identity + var view = params.view || identity + var projection = params.projection || identity + var bounds = this.bounds -function TextElements(plot, vbo, shader) { - this.plot = plot - this.vbo = vbo - this.shader = shader - this.tickOffset = [[],[]] - this.tickX = [[],[]] - this.labelOffset = [0,0] - this.labelCount = [0,0] -} + //Unpack axis info + var cubeParams = getCubeProperties(model, view, projection, bounds) + var cubeEdges = cubeParams.cubeEdges + var cubeAxis = cubeParams.axis -var proto = TextElements.prototype + var cx = view[12] + var cy = view[13] + var cz = view[14] + var cw = view[15] -proto.drawTicks = (function() { - var DATA_AXIS = [0,0] - var SCREEN_OFFSET = [0,0] - var ZERO_2 = [0,0] + var pixelScaleF = this.pixelRatio * (projection[3]*cx + projection[7]*cy + projection[11]*cz + projection[15]*cw) / gl.drawingBufferHeight - return function(axis) { - var plot = this.plot - var shader = this.shader - var tickX = this.tickX[axis] - var tickOffset = this.tickOffset[axis] - var gl = plot.gl - var viewBox = plot.viewBox - var dataBox = plot.dataBox - var screenBox = plot.screenBox - var pixelRatio = plot.pixelRatio - var tickEnable = plot.tickEnable - var tickPad = plot.tickPad - var textColor = plot.tickColor - var textAngle = plot.tickAngle - var tickLength = plot.tickMarkLength + for(var i=0; i<3; ++i) { + this.lastCubeProps.cubeEdges[i] = cubeEdges[i] + this.lastCubeProps.axis[i] = cubeAxis[i] + } - var labelEnable = plot.labelEnable - var labelPad = plot.labelPad - var labelColor = plot.labelColor - var labelAngle = plot.labelAngle - var labelOffset = this.labelOffset[axis] - var labelCount = this.labelCount[axis] + //Compute axis info + var lineOffset = LINE_OFFSET + for(var i=0; i<3; ++i) { + computeLineOffset( + LINE_OFFSET[i], + i, + this.bounds, + cubeEdges, + cubeAxis) + } - var start = bsearch.lt(tickX, dataBox[axis]) - var end = bsearch.le(tickX, dataBox[axis+2]) + //Set up state parameters + var gl = this.gl - DATA_AXIS[0] = DATA_AXIS[1] = 0 - DATA_AXIS[axis] = 1 + //Draw background first + var cubeEnable = CUBE_ENABLE + for(var i=0; i<3; ++i) { + if(this.backgroundEnable[i]) { + cubeEnable[i] = cubeAxis[i] + } else { + cubeEnable[i] = 0 + } + } - SCREEN_OFFSET[axis] = (viewBox[2+axis] + viewBox[axis]) / (screenBox[2+axis] - screenBox[axis]) - 1.0 + this._background.draw( + model, + view, + projection, + bounds, + cubeEnable, + this.backgroundColor) - var screenScale = 2.0 / screenBox[2+(axis^1)] - screenBox[axis^1] + //Draw lines + this._lines.bind( + model, + view, + projection, + this) - SCREEN_OFFSET[axis^1] = screenScale * viewBox[axis^1] - 1.0 - if(tickEnable[axis]) { - SCREEN_OFFSET[axis^1] -= screenScale * pixelRatio * tickPad[axis] - if(start < end) { - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = textColor[axis] - shader.uniforms.angle = textAngle[axis] - gl.drawArrays( - gl.TRIANGLES, - tickOffset[start], - tickOffset[end] - tickOffset[start]) - } + //First draw grid lines and zero lines + for(var i=0; i<3; ++i) { + var x = [0,0,0] + if(cubeAxis[i] > 0) { + x[i] = bounds[1][i] + } else { + x[i] = bounds[0][i] } - if(labelEnable[axis]) { - SCREEN_OFFSET[axis^1] -= screenScale * pixelRatio * labelPad[axis] - shader.uniforms.dataAxis = ZERO_2 - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = labelColor[axis] - shader.uniforms.angle = labelAngle[axis] - gl.drawArrays( - gl.TRIANGLES, - labelOffset, - labelCount) + + //Draw grid lines + for(var j=0; j<2; ++j) { + var u = (i + 1 + j) % 3 + var v = (i + 1 + (j^1)) % 3 + if(this.gridEnable[u]) { + this._lines.drawGrid(u, v, this.bounds, x, this.gridColor[u], this.gridWidth[u]*this.pixelRatio) + } } - SCREEN_OFFSET[axis^1] = screenScale * viewBox[2+(axis^1)] - 1.0 - if(tickEnable[axis+2]) { - SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * tickPad[axis+2] - if(start < end) { - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = textColor[axis+2] - shader.uniforms.angle = textAngle[axis+2] - gl.drawArrays( - gl.TRIANGLES, - tickOffset[start], - tickOffset[end] - tickOffset[start]) + //Draw zero lines (need to do this AFTER all grid lines are drawn) + for(var j=0; j<2; ++j) { + var u = (i + 1 + j) % 3 + var v = (i + 1 + (j^1)) % 3 + if(this.zeroEnable[v]) { + //Check if zero line in bounds + if(bounds[0][v] <= 0 && bounds[1][v] >= 0) { + this._lines.drawZero(u, v, this.bounds, x, this.zeroLineColor[v], this.zeroLineWidth[v]*this.pixelRatio) + } } } - if(labelEnable[axis+2]) { - SCREEN_OFFSET[axis^1] += screenScale * pixelRatio * labelPad[axis+2] - shader.uniforms.dataAxis = ZERO_2 - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.color = labelColor[axis+2] - shader.uniforms.angle = labelAngle[axis+2] - gl.drawArrays( - gl.TRIANGLES, - labelOffset, - labelCount) - } - } -})() - -proto.drawTitle = (function() { - var DATA_AXIS = [0,0] - var SCREEN_OFFSET = [0,0] - return function() { - var plot = this.plot - var shader = this.shader - var gl = plot.gl - var screenBox = plot.screenBox - var titleCenter = plot.titleCenter - var titleAngle = plot.titleAngle - var titleColor = plot.titleColor - var titleCenter = plot.titleCenter - var pixelRatio = plot.pixelRatio + //Then draw axis lines and tick marks + for(var i=0; i<3; ++i) { - for(var i=0; i<2; ++i) { - SCREEN_OFFSET[i] = 2.0 * (titleCenter[i]*pixelRatio - screenBox[i]) / - (screenBox[2+i] - screenBox[i]) - 1 + //Draw axis lines + if(this.lineEnable[i]) { + this._lines.drawAxisLine(i, this.bounds, lineOffset[i].primalOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) + } + if(this.lineMirror[i]) { + this._lines.drawAxisLine(i, this.bounds, lineOffset[i].mirrorOffset, this.lineColor[i], this.lineWidth[i]*this.pixelRatio) } - shader.bind() - shader.uniforms.dataAxis = DATA_AXIS - shader.uniforms.screenOffset = SCREEN_OFFSET - shader.uniforms.angle = titleAngle - shader.uniforms.color = titleColor + //Compute minor axes + var primalMinor = copyVec3(PRIMAL_MINOR, lineOffset[i].primalMinor) + var mirrorMinor = copyVec3(MIRROR_MINOR, lineOffset[i].mirrorMinor) + var tickLength = this.lineTickLength + var op = 0 + for(var j=0; j<3; ++j) { + var scaleFactor = pixelScaleF / model[5*j] + primalMinor[j] *= tickLength[j] * scaleFactor + mirrorMinor[j] *= tickLength[j] * scaleFactor + } - gl.drawArrays(gl.TRIANGLES, this.titleOffset, this.titleCount) + //Draw axis line ticks + if(this.lineTickEnable[i]) { + this._lines.drawAxisTicks(i, lineOffset[i].primalOffset, primalMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) + } + if(this.lineTickMirror[i]) { + this._lines.drawAxisTicks(i, lineOffset[i].mirrorOffset, mirrorMinor, this.lineTickColor[i], this.lineTickWidth[i]*this.pixelRatio) + } } -})() -proto.bind = (function() { - var DATA_SHIFT = [0,0] - var DATA_SCALE = [0,0] - var TEXT_SCALE = [0,0] + //Draw text sprites + this._text.bind( + model, + view, + projection, + this.pixelRatio) - return function() { - var plot = this.plot - var shader = this.shader - var bounds = plot._tickBounds - var dataBox = plot.dataBox - var screenBox = plot.screenBox - var viewBox = plot.viewBox + for(var i=0; i<3; ++i) { - shader.bind() + var minor = lineOffset[i].primalMinor + var offset = copyVec3(PRIMAL_OFFSET, lineOffset[i].primalOffset) - //Set up coordinate scaling uniforms - for(var i=0; i<2; ++i) { + for(var j=0; j<3; ++j) { + if(this.lineTickEnable[i]) { + offset[j] += pixelScaleF * minor[j] * Math.max(this.lineTickLength[j], 0) / model[5*j] + } + } - var lo = bounds[i] - var hi = bounds[i+2] - var boundScale = hi - lo - var dataCenter = 0.5 * (dataBox[i+2] + dataBox[i]) - var dataWidth = (dataBox[i+2] - dataBox[i]) + //Draw tick text + if(this.tickEnable[i]) { - var viewLo = viewBox[i] - var viewHi = viewBox[i+2] - var viewScale = viewHi - viewLo - var screenLo = screenBox[i] - var screenHi = screenBox[i+2] - var screenScale = screenHi - screenLo + //Add tick padding + for(var j=0; j<3; ++j) { + offset[j] += pixelScaleF * minor[j] * this.tickPad[j] / model[5*j] + } - DATA_SCALE[i] = 2.0 * boundScale / dataWidth * viewScale / screenScale - DATA_SHIFT[i] = 2.0 * (lo - dataCenter) / dataWidth * viewScale / screenScale + //Draw axis + this._text.drawTicks( + i, + this.tickSize[i], + this.tickAngle[i], + offset, + this.tickColor[i]) } - TEXT_SCALE[1] = 2.0 * plot.pixelRatio / (screenBox[3] - screenBox[1]) - TEXT_SCALE[0] = TEXT_SCALE[1] * (screenBox[3] - screenBox[1]) / (screenBox[2] - screenBox[0]) + //Draw labels + if(this.labelEnable[i]) { - shader.uniforms.dataScale = DATA_SCALE - shader.uniforms.dataShift = DATA_SHIFT - shader.uniforms.textScale = TEXT_SCALE + //Add label padding + for(var j=0; j<3; ++j) { + offset[j] += pixelScaleF * minor[j] * this.labelPad[j] / model[5*j] + } + offset[i] += 0.5 * (bounds[0][i] + bounds[1][i]) - //Set attributes - this.vbo.bind() - shader.attributes.textCoordinate.pointer() + //Draw axis + this._text.drawLabel( + i, + this.labelSize[i], + this.labelAngle[i], + offset, + this.labelColor[i]) + } } -})() +} -proto.update = function(options) { - var vertices = [] - var axesTicks = options.ticks - var bounds = options.bounds +proto.dispose = function() { + this._text.dispose() + this._lines.dispose() + this._background.dispose() + this._lines = null + this._text = null + this._background = null + this.gl = null +} - for(var dimension=0; dimension<2; ++dimension) { - var offsets = [Math.floor(vertices.length/3)], tickX = [-Infinity] +function createAxes(gl, options) { + var axes = new Axes(gl) + axes.update(options) + return axes +} - //Copy vertices over to buffer - var ticks = axesTicks[dimension] - for(var i=0; i>>1,x=a[m]"] - if(earlyOut) { - if(predicate.indexOf("c") < 0) { - code.push(";if(x===y){return m}else if(x<=y){") - } else { - code.push(";var p=c(x,y);if(p===0){return m}else if(p<=0){") +module.exports = getCubeEdges + +var bits = require('bit-twiddle') +var multiply = require('gl-mat4/multiply') +var invert = require('gl-mat4/invert') +var splitPoly = require('split-polygon') +var orient = require('robust-orientation') + +var mvp = new Array(16) +var imvp = new Array(16) +var pCubeVerts = new Array(8) +var cubeVerts = new Array(8) +var x = new Array(3) +var zero3 = [0,0,0] + +;(function() { + for(var i=0; i<8; ++i) { + pCubeVerts[i] =[1,1,1,1] + cubeVerts[i] = [1,1,1] + } +})() + + +function transformHg(result, x, mat) { + for(var i=0; i<4; ++i) { + result[i] = mat[12+i] + for(var j=0; j<3; ++j) { + result[i] += x[j]*mat[4*j+i] } - } else { - code.push(";if(", predicate, "){i=m;") } - if(reversed) { - code.push("l=m+1}else{h=m-1}") - } else { - code.push("h=m-1}else{l=m+1}") +} + +var FRUSTUM_PLANES = [ + [ 0, 0, 1, 0, 0], + [ 0, 0,-1, 1, 0], + [ 0,-1, 0, 1, 0], + [ 0, 1, 0, 1, 0], + [-1, 0, 0, 1, 0], + [ 1, 0, 0, 1, 0] +] + +function polygonArea(p) { + for(var i=0; i=", false, "GE"), - gt: compileBoundsSearch(">", false, "GT"), - lt: compileBoundsSearch("<", true, "LT"), - le: compileBoundsSearch("<=", true, "LE"), - eq: compileBoundsSearch("-", true, "EQ", true) -} +function getCubeEdges(model, view, projection, bounds) { + + //Concatenate matrices + multiply(mvp, view, model) + multiply(mvp, projection, mvp) + + //First project cube vertices + var ptr = 0 + for(var i=0; i<2; ++i) { + x[2] = bounds[i][2] + for(var j=0; j<2; ++j) { + x[1] = bounds[j][1] + for(var k=0; k<2; ++k) { + x[0] = bounds[k][0] + transformHg(pCubeVerts[ptr], x, mvp) + ptr += 1 + } + } + } + + //Classify camera against cube faces + var closest = -1 + + for(var i=0; i<8; ++i) { + var w = pCubeVerts[i][3] + for(var l=0; l<3; ++l) { + cubeVerts[i][l] = pCubeVerts[i][l] / w + } + if(w < 0) { + if(closest < 0) { + closest = i + } else if(cubeVerts[i][2] < cubeVerts[closest][2]) { + closest = i + } + } + } + + if(closest < 0) { + closest = 0 + for(var d=0; d<3; ++d) { + var u = (d+2) % 3 + var v = (d+1) % 3 + var o0 = -1 + var o1 = -1 + for(var s=0; s<2; ++s) { + var f0 = (s< o0) { + closest |= 1< o0) { + closest |= 1<0) { - throw new Error("cwise: pre() block may not reference array args") - } - if(i < proc.post.args.length && proc.post.args[i].count>0) { - throw new Error("cwise: post() block may not reference array args") - } - } else if(arg_type === "scalar") { - proc.scalarArgs.push(i) - proc.shimArgs.push("scalar" + i) - } else if(arg_type === "index") { - proc.indexArgs.push(i) - if(i < proc.pre.args.length && proc.pre.args[i].count > 0) { - throw new Error("cwise: pre() block may not reference array index") - } - if(i < proc.body.args.length && proc.body.args[i].lvalue) { - throw new Error("cwise: body() block may not write to array index") - } - if(i < proc.post.args.length && proc.post.args[i].count > 0) { - throw new Error("cwise: post() block may not reference array index") - } - } else if(arg_type === "shape") { - proc.shapeArgs.push(i) - if(i < proc.pre.args.length && proc.pre.args[i].lvalue) { - throw new Error("cwise: pre() block may not write to array shape") - } - if(i < proc.body.args.length && proc.body.args[i].lvalue) { - throw new Error("cwise: body() block may not write to array shape") - } - if(i < proc.post.args.length && proc.post.args[i].lvalue) { - throw new Error("cwise: post() block may not write to array shape") - } - } else if(typeof arg_type === "object" && arg_type.offset) { - proc.argTypes[i] = "offset" - proc.offsetArgs.push({ array: arg_type.array, offset:arg_type.offset }) - proc.offsetArgIndex.push(i) - } else { - throw new Error("cwise: Unknown argument type " + proc_args[i]) - } - } - - //Make sure at least one array argument was specified - if(proc.arrayArgs.length <= 0) { - throw new Error("cwise: No array arguments specified") - } - - //Make sure arguments are correct - if(proc.pre.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in pre() block") - } - if(proc.body.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in body() block") - } - if(proc.post.args.length > proc_args.length) { - throw new Error("cwise: Too many arguments in post() block") - } - - //Check debug flag - proc.debug = !!user_args.printCode || !!user_args.debug - - //Retrieve name - proc.funcName = user_args.funcName || "cwise" - - //Read in block size - proc.blockSize = user_args.blockSize || 64 - - return createThunk(proc) -} - -module.exports = compileCwise + //Find lowest vertex which is not closest closest + var bottom = -1 + for(var i=0; i<8; ++i) { + if(i === closest || i === farthest) { + continue + } + if(bottom < 0) { + bottom = i + } else if(cubeVerts[bottom][1] > cubeVerts[i][1]) { + bottom = i + } + } -},{"./lib/thunk.js":292}],291:[function(require,module,exports){ -"use strict" - -var uniq = require("uniq") - -// This function generates very simple loops analogous to how you typically traverse arrays (the outermost loop corresponds to the slowest changing index, the innermost loop to the fastest changing index) -// TODO: If two arrays have the same strides (and offsets) there is potential for decreasing the number of "pointers" and related variables. The drawback is that the type signature would become more specific and that there would thus be less potential for caching, but it might still be worth it, especially when dealing with large numbers of arguments. -function innerFill(order, proc, body) { - var dimension = order.length - , nargs = proc.arrayArgs.length - , has_index = proc.indexArgs.length>0 - , code = [] - , vars = [] - , idx=0, pidx=0, i, j - for(i=0; i=0; --i) { // Start at largest stride and work your way inwards - idx = order[i] - code.push(["for(i",i,"=0;i",i," 0) { - code.push(["index[",pidx,"]-=s",pidx].join("")) - } - code.push(["++index[",idx,"]"].join("")) - } - code.push("}") - } - return code.join("\n") -} - -// Generate "outer" loops that loop over blocks of data, applying "inner" loops to the blocks by manipulating the local variables in such a way that the inner loop only "sees" the current block. -// TODO: If this is used, then the previous declaration (done by generateCwiseOp) of s* is essentially unnecessary. -// I believe the s* are not used elsewhere (in particular, I don't think they're used in the pre/post parts and "shape" is defined independently), so it would be possible to make defining the s* dependent on what loop method is being used. -function outerFill(matched, order, proc, body) { - var dimension = order.length - , nargs = proc.arrayArgs.length - , blockSize = proc.blockSize - , has_index = proc.indexArgs.length > 0 - , code = [] - for(var i=0; i0;){"].join("")) // Iterate back to front - code.push(["if(j",i,"<",blockSize,"){"].join("")) // Either decrease j by blockSize (s = blockSize), or set it to zero (after setting s = j). - code.push(["s",order[i],"=j",i].join("")) - code.push(["j",i,"=0"].join("")) - code.push(["}else{s",order[i],"=",blockSize].join("")) - code.push(["j",i,"-=",blockSize,"}"].join("")) - if(has_index) { - code.push(["index[",order[i],"]=j",i].join("")) - } - } - for(var i=0; i 0) { - allEqual = allEqual && summary[i] === summary[i-1] - } - } - if(allEqual) { - return summary[0] - } - return summary.join("") -} - -//Generates a cwise operator -function generateCWiseOp(proc, typesig) { - - //Compute dimension - // Arrays get put first in typesig, and there are two entries per array (dtype and order), so this gets the number of dimensions in the first array arg. - var dimension = (typesig[1].length - Math.abs(proc.arrayBlockIndices[0]))|0 - var orders = new Array(proc.arrayArgs.length) - var dtypes = new Array(proc.arrayArgs.length) - for(var i=0; i 0) { - vars.push("shape=SS.slice(0)") // Makes the shape over which we iterate available to the user defined functions (so you can use width/height for example) - } - if(proc.indexArgs.length > 0) { - // Prepare an array to keep track of the (logical) indices, initialized to dimension zeroes. - var zeros = new Array(dimension) - for(var i=0; i 3) { - code.push(processBlock(proc.pre, proc, dtypes)) - } - - //Process body - var body = processBlock(proc.body, proc, dtypes) - var matched = countMatches(loopOrders) - if(matched < dimension) { - code.push(outerFill(matched, loopOrders[0], proc, body)) // TODO: Rather than passing loopOrders[0], it might be interesting to look at passing an order that represents the majority of the arguments for example. - } else { - code.push(innerFill(loopOrders[0], proc, body)) - } - - //Inline epilog - if(proc.post.body.length > 3) { - code.push(processBlock(proc.post, proc, dtypes)) - } - - if(proc.debug) { - console.log("-----Generated cwise routine for ", typesig, ":\n" + code.join("\n") + "\n----------") - } - - var loopName = [(proc.funcName||"unnamed"), "_cwise_loop_", orders[0].join("s"),"m",matched,typeSummary(dtypes)].join("") - var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join("")) - return f() -} -module.exports = generateCWiseOp + //Find left/right neighbors of bottom vertex + var left = -1 + for(var i=0; i<3; ++i) { + var idx = bottom ^ (1< cubeVerts[right][0]) { + right = idx + } + } -},{"uniq":293}],292:[function(require,module,exports){ -"use strict" - -// The function below is called when constructing a cwise function object, and does the following: -// A function object is constructed which accepts as argument a compilation function and returns another function. -// It is this other function that is eventually returned by createThunk, and this function is the one that actually -// checks whether a certain pattern of arguments has already been used before and compiles new loops as needed. -// The compilation passed to the first function object is used for compiling new functions. -// Once this function object is created, it is called with compile as argument, where the first argument of compile -// is bound to "proc" (essentially containing a preprocessed version of the user arguments to cwise). -// So createThunk roughly works like this: -// function createThunk(proc) { -// var thunk = function(compileBound) { -// var CACHED = {} -// return function(arrays and scalars) { -// if (dtype and order of arrays in CACHED) { -// var func = CACHED[dtype and order of arrays] -// } else { -// var func = CACHED[dtype and order of arrays] = compileBound(dtype and order of arrays) -// } -// return func(arrays and scalars) -// } -// } -// return thunk(compile.bind1(proc)) -// } - -var compile = require("./compile.js") - -function createThunk(proc) { - var code = ["'use strict'", "var CACHED={}"] - var vars = [] - var thunkName = proc.funcName + "_cwise_thunk" - - //Build thunk - code.push(["return function ", thunkName, "(", proc.shimArgs.join(","), "){"].join("")) - var typesig = [] - var string_typesig = [] - var proc_args = [["array",proc.arrayArgs[0],".shape.slice(", // Slice shape so that we only retain the shape over which we iterate (which gets passed to the cwise operator as SS). - Math.max(0,proc.arrayBlockIndices[0]),proc.arrayBlockIndices[0]<0?(","+proc.arrayBlockIndices[0]+")"):")"].join("")] - var shapeLengthConditions = [], shapeConditions = [] - // Process array arguments - for(var i=0; i0) { // Gather conditions to check for shape equality (ignoring block indices) - shapeLengthConditions.push("array" + proc.arrayArgs[0] + ".shape.length===array" + j + ".shape.length+" + (Math.abs(proc.arrayBlockIndices[0])-Math.abs(proc.arrayBlockIndices[i]))) - shapeConditions.push("array" + proc.arrayArgs[0] + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[0]) + "]===array" + j + ".shape[shapeIndex+" + Math.max(0,proc.arrayBlockIndices[i]) + "]") - } - } - // Check for shape equality - if (proc.arrayArgs.length > 1) { - code.push("if (!(" + shapeLengthConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same dimensionality!')") - code.push("for(var shapeIndex=array" + proc.arrayArgs[0] + ".shape.length-" + Math.abs(proc.arrayBlockIndices[0]) + "; shapeIndex-->0;) {") - code.push("if (!(" + shapeConditions.join(" && ") + ")) throw new Error('cwise: Arrays do not all have the same shape!')") - code.push("}") - } - // Process scalar arguments - for(var i=0; i 1) { - ext.drawBuffersWEBGL(colorAttachmentArrays[numColors]) - } + var screenAxis = zeroVec(SCREEN_AXIS) + screenAxis[i] = 1 + this.shader.uniforms.screenAxis = screenAxis + this.shader.uniforms.lineWidth = lineWidth - //Allocate depth/stencil buffers - var WEBGL_depth_texture = gl.getExtension('WEBGL_depth_texture') - if(WEBGL_depth_texture) { - if(useStencil) { - fbo.depth = initTexture(gl, width, height, - WEBGL_depth_texture.UNSIGNED_INT_24_8_WEBGL, - gl.DEPTH_STENCIL, - gl.DEPTH_STENCIL_ATTACHMENT) - } else if(useDepth) { - fbo.depth = initTexture(gl, width, height, - gl.UNSIGNED_SHORT, - gl.DEPTH_COMPONENT, - gl.DEPTH_ATTACHMENT) - } - } else { - if(useDepth && useStencil) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT) - } else if(useDepth) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) - } else if(useStencil) { - fbo._depth_rb = initRenderBuffer(gl, width, height, gl.STENCIL_INDEX, gl.STENCIL_ATTACHMENT) - } - } + this.shader.uniforms.color = color + this.vao.draw(this.gl.TRIANGLES, this.gridCount[i], this.gridOffset[i]) +} - //Check frame buffer state - var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER) - if(status !== gl.FRAMEBUFFER_COMPLETE) { +proto.drawZero = function(j, i, bounds, offset, color, lineWidth) { + var minorAxis = zeroVec(MINOR_AXIS) + this.shader.uniforms.majorAxis = minorAxis - //Release all partially allocated resources - fbo._destroyed = true + minorAxis[j] = bounds[1][j] - bounds[0][j] + this.shader.uniforms.minorAxis = minorAxis - //Release all resources - gl.bindFramebuffer(gl.FRAMEBUFFER, null) - gl.deleteFramebuffer(fbo.handle) - fbo.handle = null - if(fbo.depth) { - fbo.depth.dispose() - fbo.depth = null - } - if(fbo._depth_rb) { - gl.deleteRenderbuffer(fbo._depth_rb) - fbo._depth_rb = null + var noffset = copyVec(OFFSET_VEC, offset) + noffset[j] += bounds[0][j] + this.shader.uniforms.offset = noffset + + var screenAxis = zeroVec(SCREEN_AXIS) + screenAxis[i] = 1 + this.shader.uniforms.screenAxis = screenAxis + this.shader.uniforms.lineWidth = lineWidth + + this.shader.uniforms.color = color + this.vao.draw(this.gl.TRIANGLES, 6) +} + +proto.dispose = function() { + this.vao.dispose() + this.vertBuffer.dispose() + this.shader.dispose() +} + +function createLines(gl, bounds, ticks) { + var vertices = [] + var tickOffset = [0,0,0] + var tickCount = [0,0,0] + + //Create grid lines for each axis/direction + var gridOffset = [0,0,0] + var gridCount = [0,0,0] + + //Add zero line + vertices.push( + 0,0,1, 0,1,1, 0,0,-1, + 0,0,-1, 0,1,1, 0,1,-1) + + for(var i=0; i<3; ++i) { + //Axis tick marks + var start = ((vertices.length / 3)|0) + for(var j=0; j=0; --j) { + var p = positions[c[j]] + data.push(scale*p[0], -scale*p[1], t) } } - }) - this._shapeVector = shapeVector - - //Initialize all attachments - rebuildFBO(this) -} + } -var proto = Framebuffer.prototype + //Generate sprites for all 3 axes, store data in texture atlases + var tickOffset = [0,0,0] + var tickCount = [0,0,0] + var labelOffset = [0,0,0] + var labelCount = [0,0,0] + for(var d=0; d<3; ++d) { -function reshapeFBO(fbo, w, h) { - //If fbo is invalid, just skip this - if(fbo._destroyed) { - throw new Error('gl-fbo: Can\'t resize destroyed FBO') - } + //Generate label + labelOffset[d] = (data.length/VERTEX_SIZE)|0 + addItem(0.5*(bounds[0][d]+bounds[1][d]), labels[d], labelFont) + labelCount[d] = ((data.length/VERTEX_SIZE)|0) - labelOffset[d] - //Don't resize if no change in shape - if( (fbo._shape[0] === w) && - (fbo._shape[1] === h) ) { - return + //Generate sprites for tick marks + tickOffset[d] = (data.length/VERTEX_SIZE)|0 + for(var i=0; i maxFBOSize || - h < 0 || h > maxFBOSize) { - throw new Error('gl-fbo: Can\'t resize FBO, invalid dimensions') - } +//Draws the tick marks for an axis +var AXIS = [0,0,0] +proto.drawTicks = function(d, scale, angle, offset, color) { + var v = AXIS + v[0] = v[1] = v[2] = 0 + v[d] = 1 + this.shader.uniforms.axis = v + this.shader.uniforms.color = color + this.shader.uniforms.angle = angle + this.shader.uniforms.scale = scale + this.shader.uniforms.offset = offset + this.vao.draw(this.gl.TRIANGLES, this.tickCount[d], this.tickOffset[d]) +} - //Update shape - fbo._shape[0] = w - fbo._shape[1] = h +//Draws the text label for an axis +var ZERO = [0,0,0] +proto.drawLabel = function(d, scale, angle, offset, color) { + this.shader.uniforms.axis = ZERO + this.shader.uniforms.color = color + this.shader.uniforms.angle = angle + this.shader.uniforms.scale = scale + this.shader.uniforms.offset = offset + this.vao.draw(this.gl.TRIANGLES, this.labelCount[d], this.labelOffset[d]) +} - //Save framebuffer state - var state = saveFBOState(gl) +//Releases all resources attached to this object +proto.dispose = function() { + this.shader.dispose() + this.vao.dispose() + this.buffer.dispose() +} - //Resize framebuffer attachments - for(var i=0; i= 0) { + sigFigs = stepStr.length - u - 1 } - - //Lazily initialize color attachment arrays - var WEBGL_draw_buffers = gl.getExtension('WEBGL_draw_buffers') - if(!colorAttachmentArrays && WEBGL_draw_buffers) { - lazyInitColorAttachments(gl, WEBGL_draw_buffers) + var shift = Math.pow(10, sigFigs) + var x = Math.round(spacing * i * shift) + var xstr = x + "" + if(xstr.indexOf("e") >= 0) { + return xstr } - - //Special case: Can accept an array as argument - if(Array.isArray(width)) { - options = height - height = width[1]|0 - width = width[0]|0 + var xi = x / shift, xf = x % shift + if(x < 0) { + xi = -Math.ceil(xi)|0 + xf = (-xf)|0 + } else { + xi = Math.floor(xi)|0 + xf = xf|0 } - - if(typeof width !== 'number') { - throw new Error('gl-fbo: Missing shape parameter') + var xis = "" + xi + if(x < 0) { + xis = "-" + xis } - - //Validate width/height properties - var maxFBOSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) - if(width < 0 || width > maxFBOSize || height < 0 || height > maxFBOSize) { - throw new Error('gl-fbo: Parameters are too large for FBO') + if(sigFigs) { + var xs = "" + xf + while(xs.length < sigFigs) { + xs = "0" + xs + } + return xis + "." + xs + } else { + return xis } +} - //Handle each option type - options = options || {} - - //Figure out number of color buffers to use - var numColors = 1 - if('color' in options) { - numColors = Math.max(options.color|0, 0) - if(numColors < 0) { - throw new Error('gl-fbo: Must specify a nonnegative number of colors') +function defaultTicks(bounds, tickSpacing) { + var array = [] + for(var d=0; d<3; ++d) { + var ticks = [] + var m = 0.5*(bounds[0][d]+bounds[1][d]) + for(var t=0; t*tickSpacing[d]<=bounds[1][d]; ++t) { + ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) } - if(numColors > 1) { - //Check if multiple render targets supported - if(!WEBGL_draw_buffers) { - throw new Error('gl-fbo: Multiple draw buffer extension not supported') - } else if(numColors > gl.getParameter(WEBGL_draw_buffers.MAX_COLOR_ATTACHMENTS_WEBGL)) { - throw new Error('gl-fbo: Context does not support ' + numColors + ' draw buffers') - } + for(var t=-1; t*tickSpacing[d]>=bounds[0][d]; --t) { + ticks.push({x: t*tickSpacing[d], text: prettyPrint(tickSpacing[d], t)}) } + array.push(ticks) } + return array +} - //Determine whether to use floating point textures - var colorType = gl.UNSIGNED_BYTE - var OES_texture_float = gl.getExtension('OES_texture_float') - if(options.float && numColors > 0) { - if(!OES_texture_float) { - throw new Error('gl-fbo: Context does not support floating point textures') +function ticksEqual(ticksA, ticksB) { + for(var i=0; i<3; ++i) { + if(ticksA[i].length !== ticksB[i].length) { + return false } - colorType = gl.FLOAT - } else if(options.preferFloat && numColors > 0) { - if(OES_texture_float) { - colorType = gl.FLOAT + for(var j=0; j_inline_1_arg0_||255>_inline_1_arg1_||255>_inline_1_arg2_||255>_inline_1_arg3_){var _inline_1_l=_inline_1_arg4_-_inline_1_arg6_[0],_inline_1_a=_inline_1_arg5_-_inline_1_arg6_[1],_inline_1_f=_inline_1_l*_inline_1_l+_inline_1_a*_inline_1_a;_inline_1_f 1.0) { + t = 1.0 + } + var ti = 1.0 - t + var n = a.length + var r = new Array(n) + for(var i=0; i 0) || (a > 0 && b < 0)) { + var p = lerpW(s, b, t, a) + pos.push(p) + neg.push(p.slice()) + } + if(b < 0) { + neg.push(t.slice()) + } else if(b > 0) { + pos.push(t.slice()) + } else { + pos.push(t.slice()) + neg.push(t.slice()) + } + a = b + } + return { positive: pos, negative: neg } +} - this._readCallback = function() { - if(!self.gl) { - return +function positive(points, plane) { + var pos = [] + var a = planeT(points[points.length-1], plane) + for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { + pos.push(lerpW(s, b, t, a)) + } + if(b >= 0) { + pos.push(t.slice()) } - fbo.bind() - gl.readPixels(0,0,fbo.shape[0],fbo.shape[1],gl.RGBA,gl.UNSIGNED_BYTE,self.buffer) - self._readTimeout = null + a = b } + return pos } -var proto = SelectBuffer.prototype - -Object.defineProperty(proto, 'shape', { - get: function() { - if(!this.gl) { - return [0,0] - } - return this.fbo.shape.slice() - }, - set: function(v) { - if(!this.gl) { - return +function negative(points, plane) { + var neg = [] + var a = planeT(points[points.length-1], plane) + for(var s=points[points.length-1], t=points[0], i=0; i 0) || (a > 0 && b < 0)) { + neg.push(lerpW(s, b, t, a)) } - this.fbo.shape = v - var c = this.fbo.shape[0] - var r = this.fbo.shape[1] - if(r*c*4 > this.buffer.length) { - pool.free(this.buffer) - var buffer = this.buffer = pool.mallocUint8(nextPow2(r*c*4)) - for(var i=0; i 8192) { - throw new Error("vectorize-text: String too long (sorry, this will get fixed later)") - } - var height = 3 * size - if(canvas.height < height) { - canvas.height = height - } - - context.fillStyle = "#000" - context.fillRect(0, 0, canvas.width, canvas.height) +var proto = AxisSpikes.prototype - context.fillStyle = "#fff" - context.fillText(str, size, 2*size) +var OUTER_FACE = [0,0,0] +var INNER_FACE = [0,0,0] - //Cut pixels from image - var pixelData = context.getImageData(0, 0, width, height) - var pixels = ndarray(pixelData.data, [height, width, 4]) +var SHAPE = [0,0] - return pixels.pick(-1,-1,0).transpose(1,0) +proto.isTransparent = function() { + return false } -function getContour(pixels, doSimplify) { - var contour = surfaceNets(pixels, 128) - if(doSimplify) { - return simplify(contour.cells, contour.positions, 0.25) - } - return { - edges: contour.cells, - positions: contour.positions +proto.drawTransparent = function(camera) {} + +proto.draw = function(camera) { + var gl = this.gl + var vao = this.vao + var shader = this.shader + + vao.bind() + shader.bind() + + var model = camera.model || identity + var view = camera.view || identity + var projection = camera.projection || identity + + var axis + if(this.axes) { + axis = this.axes.lastCubeProps.axis } -} -function processPixelsImpl(pixels, options, size, simplify) { - //Extract contour - var contour = getContour(pixels, simplify) + var outerFace = OUTER_FACE + var innerFace = INNER_FACE + for(var i=0; i<3; ++i) { + if(axis && axis[i] < 0) { + outerFace[i] = this.bounds[0][i] + innerFace[i] = this.bounds[1][i] + } else { + outerFace[i] = this.bounds[1][i] + innerFace[i] = this.bounds[0][i] + } + } - //Apply warp to positions - var positions = transformPositions(contour.positions, options, size) - var edges = contour.edges - var flip = "ccw" === options.orientation + SHAPE[0] = gl.drawingBufferWidth + SHAPE[1] = gl.drawingBufferHeight - //Clean up the PSLG, resolve self intersections, etc. - cleanPSLG(positions, edges) + shader.uniforms.model = model + shader.uniforms.view = view + shader.uniforms.projection = projection + shader.uniforms.coordinates = [this.position, outerFace, innerFace] + shader.uniforms.colors = this.colors + shader.uniforms.screenShape = SHAPE - //If triangulate flag passed, triangulate the result - if(options.polygons || options.polygon || options.polyline) { - var result = toPolygonCrappy(edges, positions) - var nresult = new Array(result.length) - for(var i=0; i 0) { + var base = Math.round(Math.pow(10, y)) + return Math.ceil(x/base) * base + } + return Math.ceil(x) +} -var inCircle = require('robust-in-sphere')[4] -var bsearch = require('binary-search-bounds') +function defaultBool(x) { + if(typeof x === 'boolean') { + return x + } + return true +} -module.exports = delaunayRefine +function createScene(options) { + options = options || {} -function testFlip(points, triangulation, stack, a, b, x) { - var y = triangulation.opposite(a, b) + var stopped = false - //Test boundary edge - if(y < 0) { - return - } + var pixelRatio = options.pixelRatio || parseFloat(window.devicePixelRatio) - //Swap edge if order flipped - if(b < a) { - var tmp = a - a = b - b = tmp - tmp = x - x = y - y = tmp + var canvas = options.canvas + if(!canvas) { + canvas = document.createElement('canvas') + if(options.container) { + var container = options.container + container.appendChild(canvas) + } else { + document.body.appendChild(canvas) + } } - //Test if edge is constrained - if(triangulation.isConstraint(a, b)) { - return + var gl = options.gl + if(!gl) { + gl = getContext(canvas, + options.glOptions || { + premultipliedAlpha: true, + antialias: true + }) } - - //Test if edge is delaunay - if(inCircle(points[a], points[b], points[x], points[y]) < 0) { - stack.push(a, b) + if(!gl) { + throw new Error('webgl not supported') } -} - -//Assume edges are sorted lexicographically -function delaunayRefine(points, triangulation) { - var stack = [] - var numPoints = points.length - var stars = triangulation.stars - for(var a=0; a 0) { - var b = stack.pop() - var a = stack.pop() + //Create axes + var axesOptions = options.axes || {} + var axes = createAxes(gl, axesOptions) + axes.enable = !axesOptions.disable - //Find opposite pairs - var x = -1, y = -1 - var star = stars[a] - for(var i=1; i= 0) { - continue - } + //Dirty flag, skip redraw if scene static + var dirty = true + var pickDirty = true - //Flip the edge - triangulation.flip(a, b) + var projection = new Array(16) + var model = new Array(16) - //Test flipping neighboring edges - testFlip(points, triangulation, stack, x, a, y) - testFlip(points, triangulation, stack, a, y, x) - testFlip(points, triangulation, stack, y, b, x) - testFlip(points, triangulation, stack, b, x, y) + var cameraParams = { + view: null, + projection: projection, + model: model } -} - -},{"binary-search-bounds":283,"robust-in-sphere":330}],327:[function(require,module,exports){ -'use strict' -var bsearch = require('binary-search-bounds') - -module.exports = classifyFaces + var pickDirty = true -function FaceIndex(cells, neighbor, constraint, flags, active, next, boundary) { - this.cells = cells - this.neighbor = neighbor - this.flags = flags - this.constraint = constraint - this.active = active - this.next = next - this.boundary = boundary -} + var viewShape = [ gl.drawingBufferWidth, gl.drawingBufferHeight ] -var proto = FaceIndex.prototype + //Create scene object + var scene = { + gl: gl, + contextLost: false, + pixelRatio: options.pixelRatio || parseFloat(window.devicePixelRatio), + canvas: canvas, + selection: selection, + camera: createCamera(canvas, cameraOptions), + axes: axes, + axesPixels: null, + spikes: spikes, + bounds: bounds, + objects: objects, + shape: viewShape, + aspect: options.aspectRatio || [1,1,1], + pickRadius: options.pickRadius || 10, + zNear: options.zNear || 0.01, + zFar: options.zFar || 1000, + fovy: options.fovy || Math.PI/4, + clearColor: options.clearColor || [0,0,0,0], + autoResize: defaultBool(options.autoResize), + autoBounds: defaultBool(options.autoBounds), + autoScale: !!options.autoScale, + autoCenter: defaultBool(options.autoCenter), + clipToBounds: defaultBool(options.clipToBounds), + snapToData: !!options.snapToData, + onselect: options.onselect || null, + onrender: options.onrender || null, + onclick: options.onclick || null, + cameraParams: cameraParams, + oncontextloss: null, + mouseListener: null + } -function compareCell(a, b) { - return a[0] - b[0] || - a[1] - b[1] || - a[2] - b[2] -} + var pickShape = [ (gl.drawingBufferWidth/scene.pixelRatio)|0, (gl.drawingBufferHeight/scene.pixelRatio)|0 ] -proto.locate = (function() { - var key = [0,0,0] - return function(a, b, c) { - var x = a, y = b, z = c - if(b < c) { - if(b < a) { - x = b - y = c - z = a - } - } else if(c < a) { - x = c - y = a - z = b + function resizeListener() { + if(stopped) { + return } - if(x < 0) { - return -1 + if(!scene.autoResize) { + return } - key[0] = x - key[1] = y - key[2] = z - return bsearch.eq(this.cells, key, compareCell) - } -})() - -function indexCells(triangulation, infinity) { - //First get cells and canonicalize - var cells = triangulation.cells() - var nc = cells.length - for(var i=0; i 0 && pickBufferCount[numPick-1] === 0) { + pickBufferCount.pop() + pickBuffers.pop().dispose() } } - return index -} -function filterCells(cells, flags, target) { - var ptr = 0 - for(var i=0; i 0 || next.length > 0) { - while(active.length > 0) { - var t = active.pop() - if(flags[t] === -side) { - continue - } - flags[t] = side - var c = cells[t] - for(var j=0; j<3; ++j) { - var f = neighbor[3*t+j] - if(f >= 0 && flags[f] === 0) { - if(constraint[3*t+j]) { - next.push(f) - } else { - active.push(f) - flags[f] = side - } - } - } + scene.remove = function(obj) { + if(stopped) { + return } - - //Swap arrays and loop - var tmp = next - next = active - active = tmp - next.length = 0 - side = -side + var idx = objects.indexOf(obj) + if(idx < 0) { + return + } + objects.splice(idx, 1) + pickBufferIds.pop() + dirty = true + pickDirty = true + reallocPickIds() } - var result = filterCells(cells, flags, target) - if(infinity) { - return result.concat(index.boundary) - } - return result -} + scene.dispose = function() { + if(stopped) { + return + } -},{"binary-search-bounds":283}],328:[function(require,module,exports){ -'use strict' + stopped = true -var bsearch = require('binary-search-bounds') -var orient = require('robust-orientation')[3] + window.removeEventListener('resize', resizeListener) + canvas.removeEventListener('webglcontextlost', checkContextLoss) + scene.mouseListener.enabled = false -var EVENT_POINT = 0 -var EVENT_END = 1 -var EVENT_START = 2 + if(scene.contextLost) { + return + } -module.exports = monotoneTriangulate + //Destroy objects + axes.dispose() + spikes.dispose() + for(var i=0; i 1 && orient( - points[lowerIds[m-2]], - points[lowerIds[m-1]], - p) > 0) { - cells.push( - [lowerIds[m-1], - lowerIds[m-2], - idx]) - m -= 1 + scene.mouseListener = mouseChange(canvas, function(buttons, x, y) { + if(stopped) { + return } - lowerIds.length = m - lowerIds.push(idx) - //Insert p into upper hull - var upperIds = hull.upperIds - var m = upperIds.length - while(m > 1 && orient( - points[upperIds[m-2]], - points[upperIds[m-1]], - p) < 0) { - cells.push( - [upperIds[m-2], - upperIds[m-1], - idx]) - m -= 1 - } - upperIds.length = m - upperIds.push(idx) - } -} + var numPick = pickBuffers.length + var numObjs = objects.length + var prevObj = selection.object + selection.distance = Infinity + selection.mouse[0] = x + selection.mouse[1] = y + selection.object = null + selection.screen = null + selection.dataCoordinate = selection.dataPosition = null -function findSplit(hull, edge) { - var d - if(hull.a[0] < edge.a[0]) { - d = orient(hull.a, hull.b, edge.a) - } else { - d = orient(edge.b, edge.a, hull.a) - } - if(d) { return d } - if(edge.b[0] < hull.b[0]) { - d = orient(hull.a, hull.b, edge.b) - } else { - d = orient(edge.b, edge.a, hull.b) - } - return d || hull.idx - edge.idx -} + var change = false -function splitHulls(hulls, points, event) { - var splitIdx = bsearch.le(hulls, event, findSplit) - var hull = hulls[splitIdx] - var upperIds = hull.upperIds - var x = upperIds[upperIds.length-1] - hull.upperIds = [x] - hulls.splice(splitIdx+1, 0, - new PartialHull(event.a, event.b, event.idx, [x], upperIds)) -} + if(buttons) { + mouseRotating = true + } else { + if(mouseRotating) { + pickDirty = true + } + mouseRotating = false + for(var i=0; i selection.distance) { + continue + } + for(var j=0; j b[0]) { - events.push( - new Event(b, a, EVENT_START, i), - new Event(a, b, EVENT_END, i)) + var numObjs = objects.length + var numPick = pickBuffers.length + for(var j=0; j= 0 - } -})() + var boundsChanged = false + for(var j=0; j<3; ++j) { + boundsChanged = boundsChanged || + (prevBounds[0][j] !== bounds[0][j]) || + (prevBounds[1][j] !== bounds[1][j]) + prevBounds[0][j] = bounds[0][j] + prevBounds[1][j] = bounds[1][j] + } + + if(boundsChanged) { + var tickSpacing = [0,0,0] + for(var i=0; i<3; ++i) { + tickSpacing[i] = roundUpPow10((bounds[1][i]-bounds[0][i]) / 10.0) + } + if(axes.autoTicks) { + axes.update({ + bounds: bounds, + tickSpacing: tickSpacing + }) + } else { + axes.update({ + bounds: bounds + }) + } + } -proto.removeTriangle = function(i, j, k) { - var stars = this.stars - removePair(stars[i], j, k) - removePair(stars[j], k, i) - removePair(stars[k], i, j) -} + //Recalculate bounds + pickDirty = pickDirty || boundsChanged + dirty = dirty || boundsChanged -proto.addTriangle = function(i, j, k) { - var stars = this.stars - stars[i].push(j, k) - stars[j].push(k, i) - stars[k].push(i, j) -} + //Get scene + var width = gl.drawingBufferWidth + var height = gl.drawingBufferHeight + viewShape[0] = width + viewShape[1] = height + pickShape[0] = Math.max(width/scene.pixelRatio, 1)|0 + pickShape[1] = Math.max(height/scene.pixelRatio, 1)|0 -proto.opposite = function(j, i) { - var list = this.stars[i] - for(var k=1, n=list.length; k>1 - return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") - } -} -function makeProduct(a, b) { - if(a.charAt(0) === "m") { - if(b.charAt(0) === "w") { - var toks = a.split("[") - return ["w", b.substr(1), "m", toks[0].substr(1)].join("") - } else { - return ["prod(", a, ",", b, ")"].join("") + //If state changed, then redraw pick buffers + if(pickDirty) { + pickDirty = false + renderPick() } - } else { - return makeProduct(b, a) - } -} - -function sign(s) { - if(s & 1 !== 0) { - return "-" - } - return "" -} -function determinant(m) { - if(m.length === 2) { - return [["diff(", makeProduct(m[0][0], m[1][1]), ",", makeProduct(m[1][0], m[0][1]), ")"].join("")] - } else { - var expr = [] - for(var i=0; i= nf)) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) - } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - fa = abs(fi) - } - } - var x = a + b - var bv = x - a - var y = b - bv - var q0 = y - var q1 = x - var _x, _bv, _av, _br, _ar - while(eptr < ne && fptr < nf) { - if(ea < fa) { - a = ei - eptr += 1 - if(eptr < ne) { - ei = e[eptr] - ea = abs(ei) + if(axes.isTransparent()) { + axes.drawTransparent(cameraParams) } - } else { - a = fi - fptr += 1 - if(fptr < nf) { - fi = -f[fptr] - fa = abs(fi) + + for(var i=0; i 0) { - return [nextafter(f, -Infinity), f] - } else { - return [f, f] + //Clear dirty flags + dirty = false + for(var i=0; i= floatPoints.length) { - return ratPoints[idx-floatPoints.length] - } - var p = floatPoints[idx] - return [ rat(p[0]), rat(p[1]) ] +var BOUNDARIES = {} + +function getBoundary(glyph) { + if(glyph in BOUNDARIES) { + return BOUNDARIES[glyph] } - junctions.sort(function(a, b) { - if(a[0] !== b[0]) { - return a[0] - b[0] - } - var u = getPoint(a[1]) - var v = getPoint(b[1]) - return ratCmp(u[0], v[0]) || ratCmp(u[1], v[1]) + + var polys = vectorizeText(glyph, { + polygons: true, + font: 'sans-serif', + textAlign: 'left', + textBaseline: 'alphabetic' }) - //Split edges along junctions - for(var i=junctions.length-1; i>=0; --i) { - var junction = junctions[i] - var e = junction[0] + var coords = [] + var normals = [] - var edge = edges[e] - var s = edge[0] - var t = edge[1] + polys.forEach(function(loops) { + loops.forEach(function(loop) { + for(var i=0; i 0 && junctions[i-1][0] === e) { - var junction = junctions[--i] - var next = junction[1] - if(useColor) { - edges.push([last, next, color]) - } else { - edges.push([last, next]) + var ex = d[0] - c[0] + var ey = d[1] - c[1] + var el = Math.sqrt(ex*ex + ey*ey) + ex /= el + ey /= el + + coords.push(b[0], b[1]+1.4) + normals.push(dy, -dx) + coords.push(b[0], b[1]+1.4) + normals.push(-dy, dx) + coords.push(c[0], c[1]+1.4) + normals.push(-ey, ex) + + coords.push(c[0], c[1]+1.4) + normals.push(-ey, ex) + coords.push(b[0], b[1]+1.4) + normals.push(ey, -ex) + coords.push(c[0], c[1]+1.4) + normals.push(ey, -ex) } - last = next - } + }) + }) - //Add final edge - if(useColor) { - edges.push([last, t, color]) - } else { - edges.push([last, t]) + var bounds = [Infinity, Infinity, -Infinity, -Infinity] + for(var i=0; i b[2]) { - return 1 - } - return 0 -} + var viewBox = plot.viewBox + var dataBox = plot.dataBox + var pixelRatio = plot.pixelRatio -//Remove duplicate edge labels -function dedupEdges(edges, labels, useColor) { - if(edges.length === 0) { - return - } - if(labels) { - for(var i=0; i>(i*8)) & 0xff) } - edges[ptr++] = next - } - edges.length = ptr -} -//Repeat until convergence -function snapRound(points, edges, useColor) { + calcScales.call(this) - // 1. find edge crossings - var edgeBounds = boundEdges(points, edges) - var crossings = getCrossings(points, edges, edgeBounds) + shader.bind() - // 2. find t-junctions - var vertBounds = boundPoints(points) - var tjunctions = getTJunctions(points, edges, edgeBounds, vertBounds) + shader.uniforms.pixelScale = PIXEL_SCALE + shader.uniforms.viewTransform = MATRIX + shader.uniforms.pickOffset = PICK_OFFSET - // 3. cut edges, construct rational points - var ratPoints = cutEdges(points, edges, crossings, tjunctions, useColor) + this.positionBuffer.bind() + shader.attributes.position.pointer() - // 4. dedupe verts - var labels = dedupPoints(points, ratPoints, vertBounds) + this.offsetBuffer.bind() + shader.attributes.offset.pointer() - // 6. dedupe edges - dedupEdges(edges, labels, useColor) + this.idBuffer.bind() + shader.attributes.id.pointer(gl.UNSIGNED_BYTE, false) - // 5. check termination - if(!labels) { - return (crossings.length > 0 || tjunctions.length > 0) + gl.drawArrays(gl.TRIANGLES, 0, numVertices) + + return offset + this.numPoints } +})() - // More iterations necessary - return true +proto.pick = function(x, y, value) { + var pickOffset = this.pickOffset + var pointCount = this.numPoints + if(value < pickOffset || value >= pickOffset + pointCount) { + return null + } + var pointId = value - pickOffset + var points = this.points + return { + object: this, + pointId: pointId, + dataCoord: [ points[2*pointId], points[2*pointId+1] ] + } } -//Main loop, runs PSLG clean up until completion -function cleanPSLG(points, edges, colors) { - var modified = false +proto.update = function(options) { + options = options || {} - //If using colors, augment edges with color data - var prevEdges - if(colors) { - prevEdges = edges - var augEdges = new Array(edges.length) - for(var i=0; i> 1 + for(var j=0; j<2; ++j) { + bounds[j] = Math.min(bounds[j], positions[2*i+j]) + bounds[2+j] = Math.max(bounds[2+j], positions[2*i+j]) } } - return modified -} - -},{"./lib/rat-seg-intersect":337,"big-rat":341,"big-rat/cmp":339,"big-rat/to-float":356,"box-intersect":357,"compare-cell":367,"nextafter":368,"rat-vec":371,"robust-segment-intersect":374,"union-find":375}],337:[function(require,module,exports){ -'use strict' + if(bounds[0] === bounds[2]) { + bounds[2] += 1 + } + if(bounds[3] === bounds[1]) { + bounds[3] += 1 + } -//TODO: Move this to a separate module + var sx = 1/(bounds[2] - bounds[0]) + var sy = 1/(bounds[3] - bounds[1]) + var tx = bounds[0] + var ty = bounds[1] -module.exports = solveIntersection + var v_position = pool.mallocFloat32(2 * numVertices) + var v_offset = pool.mallocFloat32(2 * numVertices) + var v_color = pool.mallocUint8(4 * numVertices) + var v_ids = pool.mallocUint32(numVertices) + var ptr = 0 -var ratMul = require('big-rat/mul') -var ratDiv = require('big-rat/div') -var ratSub = require('big-rat/sub') -var ratSign = require('big-rat/sign') -var rvSub = require('rat-vec/sub') -var rvAdd = require('rat-vec/add') -var rvMuls = require('rat-vec/muls') + for(var i=0; i left) { + var b_level = data_levels[j-1] + var b_x = data_points[2*(j-1)] + if(((b_level - a_level) || (a_x - b_x)) >= 0) { + break + } + data_levels[j] = b_level + data_points[2*j] = b_x + data_points[2*j+1] = data_points[2*j-1] + data_ids[j] = data_ids[j-1] + data_weights[j] = data_weights[j-1] + j -= 1 } - b = num2bn(denom) - } - if(shift > 0) { - a = a.shln(shift) - } else if(shift < 0) { - b = b.shln(-shift) + + data_levels[j] = a_level + data_points[2*j] = a_x + data_points[2*j+1] = a_y + data_ids[j] = a_id + data_weights[j] = a_weight } - return rationalize(a, b) } -},{"./div":340,"./is-rat":342,"./lib/is-bn":346,"./lib/num-to-bn":347,"./lib/rationalize":348,"./lib/str-to-bn":349}],342:[function(require,module,exports){ -'use strict' +function swap(i, j, data_levels, data_points, data_ids, data_weights) { + var a_level = data_levels[i] + var a_x = data_points[2*i] + var a_y = data_points[2*i+1] + var a_id = data_ids[i] + var a_weight = data_weights[i] -var isBN = require('./lib/is-bn') + data_levels[i] = data_levels[j] + data_points[2*i] = data_points[2*j] + data_points[2*i+1] = data_points[2*j+1] + data_ids[i] = data_ids[j] + data_weights[i] = data_weights[j] -module.exports = isRat + data_levels[j] = a_level + data_points[2*j] = a_x + data_points[2*j+1] = a_y + data_ids[j] = a_id + data_weights[j] = a_weight +} -function isRat(x) { - return Array.isArray(x) && x.length === 2 && isBN(x[0]) && isBN(x[1]) +function move(i, j, data_levels, data_points, data_ids, data_weights) { + data_levels[i] = data_levels[j] + data_points[2*i] = data_points[2*j] + data_points[2*i+1] = data_points[2*j+1] + data_ids[i] = data_ids[j] + data_weights[i] = data_weights[j] } -},{"./lib/is-bn":346}],343:[function(require,module,exports){ -'use strict' +function rotate(i, j, k, data_levels, data_points, data_ids, data_weights) { + var a_level = data_levels[i] + var a_x = data_points[2*i] + var a_y = data_points[2*i+1] + var a_id = data_ids[i] + var a_weight = data_weights[i] -var bn = require('bn.js') + data_levels[i] = data_levels[j] + data_points[2*i] = data_points[2*j] + data_points[2*i+1] = data_points[2*j+1] + data_ids[i] = data_ids[j] + data_weights[i] = data_weights[j] -module.exports = sign + data_levels[j] = data_levels[k] + data_points[2*j] = data_points[2*k] + data_points[2*j+1] = data_points[2*k+1] + data_ids[j] = data_ids[k] + data_weights[j] = data_weights[k] -function sign(x) { - return x.cmp(new bn(0)) + data_levels[k] = a_level + data_points[2*k] = a_x + data_points[2*k+1] = a_y + data_ids[k] = a_id + data_weights[k] = a_weight } -},{"bn.js":352}],344:[function(require,module,exports){ -'use strict' +function shufflePivot( + i, j, + a_level, a_x, a_y, a_id, a_weight, + data_levels, data_points, data_ids, data_weights) { -module.exports = bn2num + data_levels[i] = data_levels[j] + data_points[2*i] = data_points[2*j] + data_points[2*i+1] = data_points[2*j+1] + data_ids[i] = data_ids[j] + data_weights[i] = data_weights[j] -//TODO: Make this better -function bn2num(b) { - var l = b.length - var words = b.words - var out = 0 - if (l === 1) { - out = words[0] - } else if (l === 2) { - out = words[0] + (words[1] * 0x4000000) - } else { - var out = 0 - for (var i = 0; i < l; i++) { - var w = words[i] - out += w * Math.pow(0x4000000, i) - } - } - return b.sign ? -out : out + data_levels[j] = a_level + data_points[2*j] = a_x + data_points[2*j+1] = a_y + data_ids[j] = a_id + data_weights[j] = a_weight } -},{}],345:[function(require,module,exports){ -'use strict' - -var db = require('double-bits') -var ctz = require('bit-twiddle').countTrailingZeros +function compare(i, j, data_levels, data_points, data_ids) { + return ((data_levels[i] - data_levels[j]) || + (data_points[2*j] - data_points[2*i]) || + (data_ids[i] - data_ids[j])) < 0 +} -module.exports = ctzNumber +function comparePivot(i, level, x, y, id, data_levels, data_points, data_ids) { + return ((level - data_levels[i]) || + (data_points[2*i] - x) || + (id - data_ids[i])) < 0 +} -//Counts the number of trailing zeros -function ctzNumber(x) { - var l = ctz(db.lo(x)) - if(l < 32) { - return l +function quickSort(left, right, data_levels, data_points, data_ids, data_weights) { + var sixth = (right - left + 1) / 6 | 0, + index1 = left + sixth, + index5 = right - sixth, + index3 = left + right >> 1, + index2 = index3 - sixth, + index4 = index3 + sixth, + el1 = index1, + el2 = index2, + el3 = index3, + el4 = index4, + el5 = index5, + less = left + 1, + great = right - 1, + tmp = 0 + if(compare(el1, el2, data_levels, data_points, data_ids, data_weights)) { + tmp = el1 + el1 = el2 + el2 = tmp } - var h = ctz(db.hi(x)) - if(h > 20) { - return 52 + if(compare(el4, el5, data_levels, data_points, data_ids, data_weights)) { + tmp = el4 + el4 = el5 + el5 = tmp + } + if(compare(el1, el3, data_levels, data_points, data_ids, data_weights)) { + tmp = el1 + el1 = el3 + el3 = tmp + } + if(compare(el2, el3, data_levels, data_points, data_ids, data_weights)) { + tmp = el2 + el2 = el3 + el3 = tmp + } + if(compare(el1, el4, data_levels, data_points, data_ids, data_weights)) { + tmp = el1 + el1 = el4 + el4 = tmp + } + if(compare(el3, el4, data_levels, data_points, data_ids, data_weights)) { + tmp = el3 + el3 = el4 + el4 = tmp + } + if(compare(el2, el5, data_levels, data_points, data_ids, data_weights)) { + tmp = el2 + el2 = el5 + el5 = tmp + } + if(compare(el2, el3, data_levels, data_points, data_ids, data_weights)) { + tmp = el2 + el2 = el3 + el3 = tmp + } + if(compare(el4, el5, data_levels, data_points, data_ids, data_weights)) { + tmp = el4 + el4 = el5 + el5 = tmp } - return h + 32 -} - -},{"bit-twiddle":351,"double-bits":353}],346:[function(require,module,exports){ -'use strict' - -var BN = require('bn.js') - -module.exports = isBN -//Test if x is a bignumber -//FIXME: obviously this is the wrong way to do it -function isBN(x) { - return x && typeof x === 'object' && Boolean(x.words) -} + var pivot1_level = data_levels[el2] + var pivot1_x = data_points[2*el2] + var pivot1_y = data_points[2*el2+1] + var pivot1_id = data_ids[el2] + var pivot1_weight = data_weights[el2] -},{"bn.js":352}],347:[function(require,module,exports){ -'use strict' + var pivot2_level = data_levels[el4] + var pivot2_x = data_points[2*el4] + var pivot2_y = data_points[2*el4+1] + var pivot2_id = data_ids[el4] + var pivot2_weight = data_weights[el4] -var BN = require('bn.js') -var db = require('double-bits') + var ptr0 = el1 + var ptr2 = el3 + var ptr4 = el5 + var ptr5 = index1 + var ptr6 = index3 + var ptr7 = index5 -module.exports = num2bn + var level_x = data_levels[ptr0] + var level_y = data_levels[ptr2] + var level_z = data_levels[ptr4] + data_levels[ptr5] = level_x + data_levels[ptr6] = level_y + data_levels[ptr7] = level_z -function num2bn(x) { - var e = db.exponent(x) - if(e < 52) { - return new BN(x) - } else { - return (new BN(x * Math.pow(2, 52-e))).shln(e-52) + for (var i1 = 0; i1 < 2; ++i1) { + var x = data_points[2*ptr0+i1] + var y = data_points[2*ptr2+i1] + var z = data_points[2*ptr4+i1] + data_points[2*ptr5+i1] = x + data_points[2*ptr6+i1] = y + data_points[2*ptr7+i1] = z } -} - -},{"bn.js":352,"double-bits":353}],348:[function(require,module,exports){ -'use strict' -var num2bn = require('./num-to-bn') -var sign = require('./bn-sign') + var id_x = data_ids[ptr0] + var id_y = data_ids[ptr2] + var id_z = data_ids[ptr4] + data_ids[ptr5] = id_x + data_ids[ptr6] = id_y + data_ids[ptr7] = id_z -module.exports = rationalize + var weight_x = data_weights[ptr0] + var weight_y = data_weights[ptr2] + var weight_z = data_weights[ptr4] + data_weights[ptr5] = weight_x + data_weights[ptr6] = weight_y + data_weights[ptr7] = weight_z -function rationalize(numer, denom) { - var snumer = sign(numer) - var sdenom = sign(denom) - if(snumer === 0) { - return [num2bn(0), num2bn(1)] + move(index2, left, data_levels, data_points, data_ids, data_weights) + move(index4, right, data_levels, data_points, data_ids, data_weights) + for (var k = less; k <= great; ++k) { + if (comparePivot(k, + pivot1_level, pivot1_x, pivot1_y, pivot1_id, + data_levels, data_points, data_ids)) { + if (k !== less) { + swap(k, less, data_levels, data_points, data_ids, data_weights) + } + ++less; + } else { + if (!comparePivot(k, + pivot2_level, pivot2_x, pivot2_y, pivot2_id, + data_levels, data_points, data_ids)) { + while (true) { + if (!comparePivot(great, + pivot2_level, pivot2_x, pivot2_y, pivot2_id, + data_levels, data_points, data_ids)) { + if (--great < k) { + break; + } + continue; + } else { + if (comparePivot(great, + pivot1_level, pivot1_x, pivot1_y, pivot1_id, + data_levels, data_points, data_ids)) { + rotate(k, less, great, data_levels, data_points, data_ids, data_weights) + ++less; + --great; + } else { + swap(k, great, data_levels, data_points, data_ids, data_weights) + --great; + } + break; + } + } + } + } } - if(sdenom === 0) { - return [num2bn(0), num2bn(0)] + shufflePivot(left, less-1, pivot1_level, pivot1_x, pivot1_y, pivot1_id, pivot1_weight, data_levels, data_points, data_ids, data_weights) + shufflePivot(right, great+1, pivot2_level, pivot2_x, pivot2_y, pivot2_id, pivot2_weight, data_levels, data_points, data_ids, data_weights) + if (less - 2 - left <= INSERT_SORT_CUTOFF) { + insertionSort(left, less - 2, data_levels, data_points, data_ids, data_weights) + } else { + quickSort(left, less - 2, data_levels, data_points, data_ids, data_weights) } - if(sdenom < 0) { - numer = numer.neg() - denom = denom.neg() + if (right - (great + 2) <= INSERT_SORT_CUTOFF) { + insertionSort(great + 2, right, data_levels, data_points, data_ids, data_weights) + } else { + quickSort(great + 2, right, data_levels, data_points, data_ids, data_weights) } - var d = numer.gcd(denom) - if(d.cmpn(1)) { - return [ numer.div(d), denom.div(d) ] + if (great - less <= INSERT_SORT_CUTOFF) { + insertionSort(less, great, data_levels, data_points, data_ids, data_weights) + } else { + quickSort(less, great, data_levels, data_points, data_ids, data_weights) } - return [ numer, denom ] -} - -},{"./bn-sign":343,"./num-to-bn":347}],349:[function(require,module,exports){ -'use strict' - -var BN = require('bn.js') - -module.exports = str2BN - -function str2BN(x) { - return new BN(x) } -},{"bn.js":352}],350:[function(require,module,exports){ +},{}],146:[function(require,module,exports){ 'use strict' -var rationalize = require('./lib/rationalize') - -module.exports = mul - -function mul(a, b) { - return rationalize(a[0].mul(b[0]), a[1].mul(b[1])) -} - -},{"./lib/rationalize":348}],351:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],352:[function(require,module,exports){ -(function (module, exports) { +var pool = require('typedarray-pool') -'use strict'; +var sortLevels = require('./lib/sort') -// Utils +module.exports = snapPoints -function assert(val, msg) { - if (!val) - throw new Error(msg || 'Assertion failed'); +function partition(points, ids, start, end, lox, loy, hix, hiy) { + var mid = start + for(var i=start; i>> 1 + if(n < 1) { + return [] } - this.sign = false; - this.words = null; - this.length = 0; - - // Reduction context - this.red = null; - - if (base === 'le' || base === 'be') { - endian = base; - base = 10; + var lox = Infinity, loy = Infinity + var hix = -Infinity, hiy = -Infinity + for(var i=0; i= 2 && base <= 36); + bounds = bounds || [0,0,0,0] - number = number.toString().replace(/\s+/g, ''); - var start = 0; - if (number[0] === '-') - start++; + bounds[0] = lox + bounds[1] = loy + bounds[2] = hix + bounds[3] = hiy - if (base === 16) - this._parseHex(number, start); - else - this._parseBase(number, base, start); + var levels = pool.mallocInt32(n) + var ptr = 0 - if (number[0] === '-') - this.sign = true; + function snapRec(x, y, diam, start, end, level) { + var diam_2 = diam * 0.5 + var offset = start + 1 + var count = end - start + weights[ptr] = count + levels[ptr++] = level + for(var i=0; i<2; ++i) { + for(var j=0; j<2; ++j) { + var nx = x+i*diam_2 + var ny = y+j*diam_2 + var nextOffset = partition( + points + , ids + , offset + , end + , nx, ny + , nx+diam_2, ny+diam_2) + if(nextOffset === offset) { + continue + } + if(nextOffset - offset >= Math.max(0.9 * count, 32)) { + var mid = (end + start)>>>1 + snapRec(nx, ny, diam_2, offset, mid, level+1) + offset = mid + } + snapRec(nx, ny, diam_2, offset, nextOffset, level+1) + offset = nextOffset + } + } + } + snapRec(lox, loy, diam, 0, n, 0) + sortLevels(levels, points, ids, weights, n) - this.strip(); + var lod = [] + var lastLevel = 0 + var prevOffset = n + for(var ptr=n-1; ptr>=0; --ptr) { + points[2*ptr] = (points[2*ptr] - lox) * scaleX + points[2*ptr+1] = (points[2*ptr+1] - loy) * scaleY - if (endian !== 'le') - return; + var level = levels[ptr] + if(level === lastLevel) { + continue + } - this._initArray(this.toArray(), base, endian); -}; + lod.push(new SnapInterval( + diam * Math.pow(0.5, level), + ptr+1, + prevOffset - (ptr+1) + )) + prevOffset = ptr+1 -BN.prototype._initNumber = function _initNumber(number, base, endian) { - if (number < 0) { - this.sign = true; - number = -number; - } - if (number < 0x4000000) { - this.words = [ number & 0x3ffffff ]; - this.length = 1; - } else if (number < 0x10000000000000) { - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff - ]; - this.length = 2; - } else { - assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) - this.words = [ - number & 0x3ffffff, - (number / 0x4000000) & 0x3ffffff, - 1 - ]; - this.length = 3; + lastLevel = level } - if (endian !== 'le') - return; + lod.push(new SnapInterval(diam * Math.pow(0.5, level+1), 0, prevOffset)) + pool.free(levels) - // Reverse the bytes - this._initArray(this.toArray(), base, endian); -}; + return lod +} -BN.prototype._initArray = function _initArray(number, base, endian) { - // Perhaps a Uint8Array - assert(typeof number.length === 'number'); - if (number.length <= 0) { - this.words = [ 0 ]; - this.length = 1; - return this; - } +},{"./lib/sort":145,"typedarray-pool":233}],147:[function(require,module,exports){ +'use strict' - this.length = Math.ceil(number.length / 3); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) - this.words[i] = 0; +var createShader = require('gl-shader') +var createBuffer = require('gl-buffer') +var bsearch = require('binary-search-bounds') +var snapPoints = require('snap-points-2d') - var off = 0; - if (endian === 'be') { - for (var i = number.length - 1, j = 0; i >= 0; i -= 3) { - var w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } else if (endian === 'le') { - for (var i = 0, j = 0; i < number.length; i += 3) { - var w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; - } - } - } - return this.strip(); -}; +var pool = require('typedarray-pool') -function parseHex(str, start, end) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; +var SHADERS = require('./lib/shader') - r <<= 4; +module.exports = createScatter2D - // 'a' - 'f' - if (c >= 49 && c <= 54) - r |= c - 49 + 0xa; +function Scatter2D(plot, offsetBuffer, pickBuffer, weightBuffer, shader, pickShader) { + this.plot = plot + this.offsetBuffer = offsetBuffer + this.pickBuffer = pickBuffer + this.weightBuffer = weightBuffer + this.shader = shader + this.pickShader = pickShader + this.scales = [] + this.size = 12.0 + this.borderSize = 1.0 + this.pointCount = 0 + this.color = [1,0,0,1] + this.borderColor = [0,0,0,1] + this.bounds = [Infinity,Infinity,-Infinity,-Infinity] + this.pickOffset = 0 + this.points = null + this.xCoords = null +} - // 'A' - 'F' - else if (c >= 17 && c <= 22) - r |= c - 17 + 0xa; +var proto = Scatter2D.prototype - // '0' - '9' - else - r |= c & 0xf; +proto.dispose = function() { + this.shader.dispose() + this.pickShader.dispose() + this.offsetBuffer.dispose() + this.pickBuffer.dispose() + if(this.xCoords) { + pool.free(this.xCoords) } - return r; + this.plot.removeObject(this) } -BN.prototype._parseHex = function _parseHex(number, start) { - // Create possibly bigger array to ensure that it fits the number - this.length = Math.ceil((number.length - start) / 6); - this.words = new Array(this.length); - for (var i = 0; i < this.length; i++) - this.words[i] = 0; +proto.update = function(options) { + options = options || {} - // Scan 24-bit chunks and add them to the number - var off = 0; - for (var i = number.length - 6, j = 0; i >= start; i -= 6) { - var w = parseHex(number, i, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - off += 24; - if (off >= 26) { - off -= 26; - j++; + function dflt(opt, value) { + if(opt in options) { + return options[opt] } + return value } - if (i + 6 !== start) { - var w = parseHex(number, start, i + 6); - this.words[j] |= (w << off) & 0x3ffffff; - this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; - } - this.strip(); -}; - -function parseBase(str, start, end, mul) { - var r = 0; - var len = Math.min(str.length, end); - for (var i = start; i < len; i++) { - var c = str.charCodeAt(i) - 48; - r *= mul; + this.size = dflt('size', 12.0) + this.color = dflt('color', [1,0,0,1]).slice() + this.borderSize = dflt('borderSize', 1) + this.borderColor = dflt('borderColor', [0,0,0,1]).slice() - // 'a' - if (c >= 49) - r += c - 49 + 0xa; + //Update point data + if(this.xCoords) { + pool.free(this.xCoords) + } + var data = options.positions + var packed = pool.mallocFloat32(data.length) + var packedId = pool.mallocInt32(data.length>>>1) + packed.set(data) + var packedW = pool.mallocFloat32(data.length) + this.points = data + this.scales = snapPoints(packed, packedId, packedW, this.bounds) + this.offsetBuffer.update(packed) + this.pickBuffer.update(packedId) + this.weightBuffer.update(packedW) + var xCoords = pool.mallocFloat32(data.length>>>1) + for(var i=0,j=0; i= 17) - r += c - 17 + 0xa; + this.xCoords = xCoords - // '0' - '9' - else - r += c; - } - return r; + this.pointCount = data.length >>> 1 + this.pickOffset = 0 } -BN.prototype._parseBase = function _parseBase(number, base, start) { - // Initialize as zero - this.words = [ 0 ]; - this.length = 1; +proto.drawPick = (function() { + var MATRIX = [1,0,0, + 0,1,0, + 0,0,1] + var PICK_VEC4 = [0,0,0,0] +return function(pickOffset) { + var plot = this.plot + var shader = this.pickShader + var scales = this.scales + var offsetBuffer = this.offsetBuffer + var pickBuffer = this.pickBuffer + var bounds = this.bounds + var size = this.size + var borderSize = this.borderSize + var gl = plot.gl + var pixelRatio = plot.pickPixelRatio + var viewBox = plot.viewBox + var dataBox = plot.dataBox - // Find length of limb in base - for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) - limbLen++; - limbLen--; - limbPow = (limbPow / base) | 0; + if(this.pointCount === 0) { + return pickOffset + } - var total = number.length - start; - var mod = total % limbLen; - var end = Math.min(total, total - mod) + start; + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + var screenX = (viewBox[2] - viewBox[0]) * pixelRatio / plot.pixelRatio + var screenY = (viewBox[3] - viewBox[1]) * pixelRatio / plot.pixelRatio - var word = 0; - for (var i = start; i < end; i += limbLen) { - word = parseBase(number, i, i + limbLen, base); + var pixelSize = Math.min(dataX / screenX, dataY / screenY) + var targetScale = pixelSize - this.imuln(limbPow); - if (this.words[0] + word < 0x4000000) - this.words[0] += word; - else - this._iaddn(word); - } - if (mod !== 0) { - var pow = 1; - var word = parseBase(number, i, number.length, base); + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 - for (var i = 0; i < mod; i++) - pow *= base; - this.imuln(pow); - if (this.words[0] + word < 0x4000000) - this.words[0] += word; - else - this._iaddn(word); - } -}; + this.pickOffset = pickOffset + PICK_VEC4[0] = ( pickOffset & 0xff) + PICK_VEC4[1] = ((pickOffset>>8) & 0xff) + PICK_VEC4[2] = ((pickOffset>>16) & 0xff) + PICK_VEC4[3] = ((pickOffset>>24) & 0xff) -BN.prototype.copy = function copy(dest) { - dest.words = new Array(this.length); - for (var i = 0; i < this.length; i++) - dest.words[i] = this.words[i]; - dest.length = this.length; - dest.sign = this.sign; - dest.red = this.red; -}; + shader.bind() + shader.uniforms.matrix = MATRIX + shader.uniforms.color = this.color + shader.uniforms.borderColor = this.borderColor + shader.uniforms.pointSize = pixelRatio * (size + borderSize) + shader.uniforms.pickOffset = PICK_VEC4 -BN.prototype.clone = function clone() { - var r = new BN(null); - this.copy(r); - return r; -}; + if(this.borderSize === 0) { + shader.uniforms.centerFraction = 2.0; + } else { + shader.uniforms.centerFraction = size / (size + borderSize + 1.25) + } -// Remove leading `0` from `this` -BN.prototype.strip = function strip() { - while (this.length > 1 && this.words[this.length - 1] === 0) - this.length--; - return this._normSign(); -}; + offsetBuffer.bind() + shader.attributes.position.pointer() + pickBuffer.bind() + shader.attributes.pickId.pointer(gl.UNSIGNED_BYTE) -BN.prototype._normSign = function _normSign() { - // -0 = 0 - if (this.length === 1 && this.words[0] === 0) - this.sign = false; - return this; -}; + var xCoords = this.xCoords + var xStart = (dataBox[0] - bounds[0] - pixelSize * size * pixelRatio) / boundX + var xEnd = (dataBox[2] - bounds[0] + pixelSize * size * pixelRatio) / boundX -BN.prototype.inspect = function inspect() { - return (this.red ? ''; -}; + for(var scaleNum = scales.length-1; scaleNum >= 0; --scaleNum) { + var lod = scales[scaleNum] + if(lod.pixelSize < pixelSize && scaleNum > 1) { + continue + } -/* + var intervalStart = lod.offset + var intervalEnd = lod.count + intervalStart -var zeros = []; -var groupSizes = []; -var groupBases = []; + var startOffset = bsearch.ge(xCoords, xStart, intervalStart, intervalEnd-1) + var endOffset = bsearch.lt(xCoords, xEnd, startOffset, intervalEnd-1)+1 -var s = ''; -var i = -1; -while (++i < BN.wordSize) { - zeros[i] = s; - s += '0'; -} -groupSizes[0] = 0; -groupSizes[1] = 0; -groupBases[0] = 0; -groupBases[1] = 0; -var base = 2 - 1; -while (++base < 36 + 1) { - var groupSize = 0; - var groupBase = 1; - while (groupBase < (1 << BN.wordSize) / base) { - groupBase *= base; - groupSize += 1; + gl.drawArrays(gl.POINTS, startOffset, endOffset - startOffset) } - groupSizes[base] = groupSize; - groupBases[base] = groupBase; + + return pickOffset + this.pointCount } +})() -*/ +proto.draw = (function() { + var MATRIX = [1, 0, 0, + 0, 1, 0, + 0, 0, 1] -var zeros = [ - '', - '0', - '00', - '000', - '0000', - '00000', - '000000', - '0000000', - '00000000', - '000000000', - '0000000000', - '00000000000', - '000000000000', - '0000000000000', - '00000000000000', - '000000000000000', - '0000000000000000', - '00000000000000000', - '000000000000000000', - '0000000000000000000', - '00000000000000000000', - '000000000000000000000', - '0000000000000000000000', - '00000000000000000000000', - '000000000000000000000000', - '0000000000000000000000000' -]; + return function() { + var plot = this.plot + var shader = this.shader + var scales = this.scales + var offsetBuffer = this.offsetBuffer + var bounds = this.bounds + var size = this.size + var borderSize = this.borderSize + var gl = plot.gl + var pixelRatio = plot.pixelRatio + var viewBox = plot.viewBox + var dataBox = plot.dataBox -var groupSizes = [ - 0, 0, - 25, 16, 12, 11, 10, 9, 8, - 8, 7, 7, 7, 7, 6, 6, - 6, 6, 6, 6, 6, 5, 5, - 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5 -]; + if(this.pointCount === 0) { + return + } -var groupBases = [ - 0, 0, - 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, - 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, - 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, - 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, - 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 -]; + var boundX = bounds[2] - bounds[0] + var boundY = bounds[3] - bounds[1] + var dataX = dataBox[2] - dataBox[0] + var dataY = dataBox[3] - dataBox[1] + var screenX = viewBox[2] - viewBox[0] + var screenY = viewBox[3] - viewBox[1] -BN.prototype.toString = function toString(base, padding) { - base = base || 10; - if (base === 16 || base === 'hex') { - var out = ''; - var off = 0; - var padding = padding | 0 || 1; - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i]; - var word = (((w << off) | carry) & 0xffffff).toString(16); - carry = (w >>> (24 - off)) & 0xffffff; - if (carry !== 0 || i !== this.length - 1) - out = zeros[6 - word.length] + word + out; - else - out = word + out; - off += 2; - if (off >= 26) { - off -= 26; - i--; - } - } - if (carry !== 0) - out = carry.toString(16) + out; - while (out.length % padding !== 0) - out = '0' + out; - if (this.sign) - out = '-' + out; - return out; - } else if (base === (base | 0) && base >= 2 && base <= 36) { - // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); - var groupSize = groupSizes[base]; - // var groupBase = Math.pow(base, groupSize); - var groupBase = groupBases[base]; - var out = ''; - var c = this.clone(); - c.sign = false; - while (c.cmpn(0) !== 0) { - var r = c.modn(groupBase).toString(base); - c = c.idivn(groupBase); + var pixelSize = Math.min(dataX / screenX, dataY / screenY) + var targetScale = pixelSize - if (c.cmpn(0) !== 0) - out = zeros[groupSize - r.length] + r + out; - else - out = r + out; + MATRIX[0] = 2.0 * boundX / dataX + MATRIX[4] = 2.0 * boundY / dataY + MATRIX[6] = 2.0 * (bounds[0] - dataBox[0]) / dataX - 1.0 + MATRIX[7] = 2.0 * (bounds[1] - dataBox[1]) / dataY - 1.0 + + shader.bind() + shader.uniforms.matrix = MATRIX + shader.uniforms.color = this.color + shader.uniforms.borderColor = this.borderColor + shader.uniforms.pointSize = pixelRatio * (size + borderSize) + shader.uniforms.useWeight = 1 + + if(this.borderSize === 0) { + shader.uniforms.centerFraction = 2.0; + } else { + shader.uniforms.centerFraction = size / (size + borderSize + 1.25) } - if (this.cmpn(0) === 0) - out = '0' + out; - if (this.sign) - out = '-' + out; - return out; - } else { - assert(false, 'Base should be between 2 and 36'); - } -}; -BN.prototype.toJSON = function toJSON() { - return this.toString(16); -}; + offsetBuffer.bind() + shader.attributes.position.pointer() -BN.prototype.toArray = function toArray(endian) { - this.strip(); - var res = new Array(this.byteLength()); - res[0] = 0; + this.weightBuffer.bind() + shader.attributes.weight.pointer() - var q = this.clone(); - if (endian !== 'le') { - // Assume big-endian - for (var i = 0; q.cmpn(0) !== 0; i++) { - var b = q.andln(0xff); - q.ishrn(8); + var xCoords = this.xCoords + var xStart = (dataBox[0] - bounds[0] - pixelSize * size * pixelRatio) / boundX + var xEnd = (dataBox[2] - bounds[0] + pixelSize * size * pixelRatio) / boundX - res[res.length - i - 1] = b; - } - } else { - // Assume little-endian - for (var i = 0; q.cmpn(0) !== 0; i++) { - var b = q.andln(0xff); - q.ishrn(8); + var firstLevel = true - res[i] = b; - } - } + for(var scaleNum = scales.length-1; scaleNum >= 0; --scaleNum) { + var lod = scales[scaleNum] + if(lod.pixelSize < pixelSize && scaleNum > 1) { + continue + } - return res; -}; + var intervalStart = lod.offset + var intervalEnd = lod.count + intervalStart -if (Math.clz32) { - BN.prototype._countBits = function _countBits(w) { - return 32 - Math.clz32(w); - }; -} else { - BN.prototype._countBits = function _countBits(w) { - var t = w; - var r = 0; - if (t >= 0x1000) { - r += 13; - t >>>= 13; - } - if (t >= 0x40) { - r += 7; - t >>>= 7; - } - if (t >= 0x8) { - r += 4; - t >>>= 4; - } - if (t >= 0x02) { - r += 2; - t >>>= 2; - } - return r + t; - }; -} + var startOffset = bsearch.ge(xCoords, xStart, intervalStart, intervalEnd-1) + var endOffset = bsearch.lt(xCoords, xEnd, startOffset, intervalEnd-1)+1 -BN.prototype._zeroBits = function _zeroBits(w) { - // Short-cut - if (w === 0) - return 26; + gl.drawArrays(gl.POINTS, startOffset, endOffset - startOffset) - var t = w; - var r = 0; - if ((t & 0x1fff) === 0) { - r += 13; - t >>>= 13; - } - if ((t & 0x7f) === 0) { - r += 7; - t >>>= 7; + if(firstLevel) { + firstLevel = false + shader.uniforms.useWeight = 0 + } + } } - if ((t & 0xf) === 0) { - r += 4; - t >>>= 4; +})() + +proto.pick = function(x, y, value) { + var pickOffset = this.pickOffset + var pointCount = this.pointCount + if(value < pickOffset || value >= pickOffset + pointCount) { + return null } - if ((t & 0x3) === 0) { - r += 2; - t >>>= 2; + var pointId = value - pickOffset + var points = this.points + return { + object: this, + pointId: pointId, + dataCoord: [ points[2*pointId], points[2*pointId+1] ] } - if ((t & 0x1) === 0) - r++; - return r; -}; +} -// Return number of used bits in a BN -BN.prototype.bitLength = function bitLength() { - var hi = 0; - var w = this.words[this.length - 1]; - var hi = this._countBits(w); - return (this.length - 1) * 26 + hi; -}; +function createScatter2D(plot, options) { + var gl = plot.gl + var buffer = createBuffer(gl) + var pickBuffer = createBuffer(gl) + var weightBuffer = createBuffer(gl) + var shader = createShader(gl, SHADERS.pointVertex, SHADERS.pointFragment) + var pickShader = createShader(gl, SHADERS.pickVertex, SHADERS.pickFragment) -// Number of trailing zero bits -BN.prototype.zeroBits = function zeroBits() { - if (this.cmpn(0) === 0) - return 0; + var result = new Scatter2D( + plot, buffer, pickBuffer, weightBuffer, shader, pickShader) + result.update(options) - var r = 0; - for (var i = 0; i < this.length; i++) { - var b = this._zeroBits(this.words[i]); - r += b; - if (b !== 26) - break; - } - return r; -}; + //Register with plot + plot.addObject(result) -BN.prototype.byteLength = function byteLength() { - return Math.ceil(this.bitLength() / 8); -}; + return result +} -// Return negative clone of `this` -BN.prototype.neg = function neg() { - if (this.cmpn(0) === 0) - return this.clone(); +},{"./lib/shader":143,"binary-search-bounds":144,"gl-buffer":75,"gl-shader":154,"snap-points-2d":146,"typedarray-pool":233}],148:[function(require,module,exports){ +"use strict" - var r = this.clone(); - r.sign = !this.sign; - return r; -}; +var vectorizeText = require("vectorize-text") +module.exports = getGlyph -// Or `num` with `this` in-place -BN.prototype.ior = function ior(num) { - this.sign = this.sign || num.sign; +var GLYPH_CACHE = {} - while (this.length < num.length) - this.words[this.length++] = 0; +function getGlyph(symbol, font) { + var fontCache = GLYPH_CACHE[font] + if(!fontCache) { + fontCache = GLYPH_CACHE[font] = {} + } + if(symbol in fontCache) { + return fontCache[symbol] + } - for (var i = 0; i < num.length; i++) - this.words[i] = this.words[i] | num.words[i]; + //Get line and triangle meshes for glyph + var lineSymbol = vectorizeText(symbol, { + textAlign: "center", + textBaseline: "middle", + lineHeight: 1.0, + font: font + }) + var triSymbol = vectorizeText(symbol, { + triangles: true, + textAlign: "center", + textBaseline: "middle", + lineHeight: 1.0, + font: font + }) - return this.strip(); -}; + //Calculate bounding box + var bounds = [[Infinity,Infinity], [-Infinity,-Infinity]] + for(var i=0; i num.length) - return this.clone().ior(num); - else - return num.clone().ior(this); -}; +var perspectiveVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\n\nuniform vec4 highlightId;\nuniform float highlightScale;\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || \n any(greaterThan(position, clipBounds[1])) ) {\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = 1.0;\n if(distance(highlightId, id) < 0.0001) {\n scale = highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1);\n vec4 viewPosition = view * worldPosition;\n viewPosition = viewPosition / viewPosition.w;\n vec4 clipPosition = projection * (viewPosition + scale * vec4(glyph.x, -glyph.y, 0, 0));\n \n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}" +var orthographicVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float highlightScale, pixelRatio;\nuniform vec4 highlightId;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) || any(greaterThan(position, clipBounds[1]))) {\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = pixelRatio;\n if(distance(highlightId.bgr, id.bgr) < 0.001) {\n scale *= highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1.0);\n vec4 viewPosition = view * worldPosition;\n vec4 clipPosition = projection * viewPosition;\n clipPosition /= clipPosition.w;\n \n gl_Position = clipPosition + vec4(screenSize * scale * vec2(glyph.x, -glyph.y), 0.0, 0.0);\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}" +var projectionVertSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform float highlightScale;\nuniform vec4 highlightId;\nuniform vec3 axes[2];\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float scale, pixelRatio;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if(any(lessThan(position, clipBounds[0])) ||\n any(greaterThan(position, clipBounds[1])) ) {\n gl_Position = vec4(0,0,0,0);\n } else {\n float lscale = pixelRatio * scale;\n if(distance(highlightId, id) < 0.0001) {\n lscale *= highlightScale;\n }\n\n vec4 clipCenter = projection * view * model * vec4(position, 1);\n vec3 dataPosition = position + 0.5*lscale*(axes[0] * glyph.x + axes[1] * glyph.y) * clipCenter.w * screenSize.y;\n vec4 clipPosition = projection * view * model * vec4(dataPosition, 1);\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = dataPosition;\n }\n}\n" +var drawFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 fragClipBounds[2];\nuniform float opacity;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if(any(lessThan(dataCoordinate, fragClipBounds[0])) ||\n any(greaterThan(dataCoordinate, fragClipBounds[1])) ) {\n discard;\n } else {\n gl_FragColor = interpColor * opacity;\n }\n}\n" +var pickFragSrc = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec3 fragClipBounds[2];\nuniform float pickGroup;\n\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if(any(lessThan(dataCoordinate, fragClipBounds[0])) || \n any(greaterThan(dataCoordinate, fragClipBounds[1])) ) {\n discard;\n } else {\n gl_FragColor = vec4(pickGroup, pickId.bgr);\n }\n}" -// And `num` with `this` in-place -BN.prototype.iand = function iand(num) { - this.sign = this.sign && num.sign; +var ATTRIBUTES = [ + {name: 'position', type: 'vec3'}, + {name: 'color', type: 'vec4'}, + {name: 'glyph', type: 'vec2'}, + {name: 'id', type: 'vec4'} +] - // b = min-length(num, this) - var b; - if (this.length > num.length) - b = num; - else - b = this; +var perspective = { + vertex: perspectiveVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + ortho = { + vertex: orthographicVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + project = { + vertex: projectionVertSrc, + fragment: drawFragSrc, + attributes: ATTRIBUTES + }, + pickPerspective = { + vertex: perspectiveVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + }, + pickOrtho = { + vertex: orthographicVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + }, + pickProject = { + vertex: projectionVertSrc, + fragment: pickFragSrc, + attributes: ATTRIBUTES + } - for (var i = 0; i < b.length; i++) - this.words[i] = this.words[i] & num.words[i]; +function createShader(gl, src) { + var shader = createShaderWrapper(gl, src) + var attr = shader.attributes + attr.position.location = 0 + attr.color.location = 1 + attr.glyph.location = 2 + attr.id.location = 3 + return shader +} + +exports.createPerspective = function(gl) { + return createShader(gl, perspective) +} +exports.createOrtho = function(gl) { + return createShader(gl, ortho) +} +exports.createProject = function(gl) { + return createShader(gl, project) +} +exports.createPickPerspective = function(gl) { + return createShader(gl, pickPerspective) +} +exports.createPickOrtho = function(gl) { + return createShader(gl, pickOrtho) +} +exports.createPickProject = function(gl) { + return createShader(gl, pickProject) +} - this.length = b.length; +},{"gl-shader":154}],150:[function(require,module,exports){ +'use strict' - return this.strip(); -}; +var createBuffer = require('gl-buffer') +var createVAO = require('gl-vao') +var pool = require('typedarray-pool') +var mat4mult = require('gl-mat4/multiply') +var shaders = require('./lib/shaders') +var getGlyph = require('./lib/glyphs') +var IDENTITY = [1,0,0,0, + 0,1,0,0, + 0,0,1,0, + 0,0,0,1] -// And `num` with `this` -BN.prototype.and = function and(num) { - if (this.length > num.length) - return this.clone().iand(num); - else - return num.clone().iand(this); -}; +module.exports = createPointCloud +function transformMat4(x, m) { + var x0 = x[0] + var x1 = x[1] + var x2 = x[2] + var x3 = x[3] + x[0] = m[0] * x0 + m[4] * x1 + m[8] * x2 + m[12] * x3 + x[1] = m[1] * x0 + m[5] * x1 + m[9] * x2 + m[13] * x3 + x[2] = m[2] * x0 + m[6] * x1 + m[10] * x2 + m[14] * x3 + x[3] = m[3] * x0 + m[7] * x1 + m[11] * x2 + m[15] * x3 + return x +} -// Xor `num` with `this` in-place -BN.prototype.ixor = function ixor(num) { - this.sign = this.sign || num.sign; +function project(p, v, m, x) { + transformMat4(x, x, m) + transformMat4(x, x, v) + return transformMat4(x, x, p) +} - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; +function clampVec(v) { + var result = new Array(3) + for(var i=0; i<3; ++i) { + result[i] = Math.min(Math.max(v[i], -1e8), 1e8) } + return result +} - for (var i = 0; i < b.length; i++) - this.words[i] = a.words[i] ^ b.words[i]; +function ScatterPlotPickResult(index, position) { + this.index = index + this.dataCoordinate = this.position = position +} - if (this !== a) - for (; i < a.length; i++) - this.words[i] = a.words[i]; +function PointCloud( + gl, + shader, + orthoShader, + projectShader, + pointBuffer, + colorBuffer, + glyphBuffer, + idBuffer, + vao, + pickPerspectiveShader, + pickOrthoShader, + pickProjectShader) { - this.length = a.length; + this.gl = gl - return this.strip(); -}; + this.pixelRatio = 1 + this.shader = shader + this.orthoShader = orthoShader + this.projectShader = projectShader -// Xor `num` with `this` -BN.prototype.xor = function xor(num) { - if (this.length > num.length) - return this.clone().ixor(num); - else - return num.clone().ixor(this); -}; + this.pointBuffer = pointBuffer + this.colorBuffer = colorBuffer + this.glyphBuffer = glyphBuffer + this.idBuffer = idBuffer + this.vao = vao + this.vertexCount = 0 + this.lineVertexCount = 0 + this.opacity = 1.0 -// Set `bit` of `this` -BN.prototype.setn = function setn(bit, val) { - assert(typeof bit === 'number' && bit >= 0); + this.lineWidth = 0 + this.projectScale = [2.0/3.0, 2.0/3.0, 2.0/3.0] + this.projectOpacity = [1,1,1] - var off = (bit / 26) | 0; - var wbit = bit % 26; + this.pickId = 0 + this.pickPerspectiveShader = pickPerspectiveShader + this.pickOrthoShader = pickOrthoShader + this.pickProjectShader = pickProjectShader + this.points = [] - while (this.length <= off) - this.words[this.length++] = 0; + this._selectResult = new ScatterPlotPickResult(0, [0,0,0]) - if (val) - this.words[off] = this.words[off] | (1 << wbit); - else - this.words[off] = this.words[off] & ~(1 << wbit); + this.useOrtho = true + this.bounds = [[ Infinity,Infinity,Infinity], + [-Infinity,-Infinity,-Infinity]] - return this.strip(); -}; + //Axes projections + this.axesProject = [ true, true, true ] + this.axesBounds = [[-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity]] + this.highlightId = [1,1,1,1] + this.highlightScale = 2 -// Add `num` to `this` in-place -BN.prototype.iadd = function iadd(num) { - // negative + positive - if (this.sign && !num.sign) { - this.sign = false; - var r = this.isub(num); - this.sign = !this.sign; - return this._normSign(); + this.clipBounds = [[-Infinity,-Infinity,-Infinity], + [ Infinity, Infinity, Infinity]] - // positive + negative - } else if (!this.sign && num.sign) { - num.sign = false; - var r = this.isub(num); - num.sign = true; - return r._normSign(); - } + this.dirty = true +} - // a.length > b.length - var a; - var b; - if (this.length > num.length) { - a = this; - b = num; - } else { - a = num; - b = this; - } +var proto = PointCloud.prototype - var carry = 0; - for (var i = 0; i < b.length; i++) { - var r = a.words[i] + b.words[i] + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; +proto.pickSlots = 1 + +proto.setPickBase = function(pickBase) { + this.pickId = pickBase +} + +proto.isTransparent = function() { + if(this.opacity < 1) { + return true } - for (; carry !== 0 && i < a.length; i++) { - var r = a.words[i] + carry; - this.words[i] = r & 0x3ffffff; - carry = r >>> 26; + for(var i=0; i<3; ++i) { + if(this.axesProject[i] && this.projectOpacity[i] < 1) { + return true + } } + return false +} - this.length = a.length; - if (carry !== 0) { - this.words[this.length] = carry; - this.length++; - // Copy the rest of the words - } else if (a !== this) { - for (; i < a.length; i++) - this.words[i] = a.words[i]; +proto.isOpaque = function() { + if(this.opacity >= 1) { + return true + } + for(var i=0; i<3; ++i) { + if(this.axesProject[i] && this.projectOpacity[i] >= 1) { + return true + } } + return false +} - return this; -}; +var VIEW_SHAPE = [0,0] +var U_VEC = [0,0,0] +var V_VEC = [0,0,0] +var MU_VEC = [0,0,0,1] +var MV_VEC = [0,0,0,1] +var SCRATCH_MATRIX = IDENTITY.slice() +var SCRATCH_VEC = [0,0,0] +var CLIP_BOUNDS = [[0,0,0], [0,0,0]] -// Add `num` to `this` -BN.prototype.add = function add(num) { - if (num.sign && !this.sign) { - num.sign = false; - var res = this.sub(num); - num.sign = true; - return res; - } else if (!num.sign && this.sign) { - this.sign = false; - var res = num.sub(this); - this.sign = true; - return res; - } +function zeroVec(a) { + a[0] = a[1] = a[2] = 0 + return a +} - if (this.length > num.length) - return this.clone().iadd(num); - else - return num.clone().iadd(this); -}; +function augment(hg, af) { + hg[0] = af[0] + hg[1] = af[1] + hg[2] = af[2] + hg[3] = 1 + return hg +} -// Subtract `num` from `this` in-place -BN.prototype.isub = function isub(num) { - // this - (-num) = this + num - if (num.sign) { - num.sign = false; - var r = this.iadd(num); - num.sign = true; - return r._normSign(); +function setComponent(out, v, i, x) { + out[0] = v[0] + out[1] = v[1] + out[2] = v[2] + out[i] = x + return out +} - // -this - num = -(this + num) - } else if (this.sign) { - this.sign = false; - this.iadd(num); - this.sign = true; - return this._normSign(); +function getClipBounds(bounds) { + var result = CLIP_BOUNDS + for(var i=0; i<2; ++i) { + for(var j=0; j<3; ++j) { + result[i][j] = Math.max(Math.min(bounds[i][j], 1e8), -1e8) + } } + return result +} - // At this point both numbers are positive - var cmp = this.cmp(num); +function drawProject(shader, points, camera, transparent, forceDraw) { + var axesProject = points.axesProject - // Optimization - zeroify - if (cmp === 0) { - this.sign = false; - this.length = 1; - this.words[0] = 0; - return this; - } + var gl = points.gl + var uniforms = shader.uniforms + var model = camera.model || IDENTITY + var view = camera.view || IDENTITY + var projection = camera.projection || IDENTITY + var bounds = points.axesBounds + var clipBounds = getClipBounds(points.clipBounds) - // a > b - var a; - var b; - if (cmp > 0) { - a = this; - b = num; + var cubeAxis + if(points.axes) { + cubeAxis = points.axes.lastCubeProps.axis } else { - a = num; - b = this; + cubeAxis = [1,1,1] } - var carry = 0; - for (var i = 0; i < b.length; i++) { - var r = a.words[i] - b.words[i] + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } - for (; carry !== 0 && i < a.length; i++) { - var r = a.words[i] + carry; - carry = r >> 26; - this.words[i] = r & 0x3ffffff; - } + VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth + VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight - // Copy rest of the words - if (carry === 0 && i < a.length && a !== this) - for (; i < a.length; i++) - this.words[i] = a.words[i]; - this.length = Math.max(this.length, i); + shader.bind() + uniforms.view = view + uniforms.projection = projection + uniforms.screenSize = VIEW_SHAPE + uniforms.highlightId = points.highlightId + uniforms.highlightScale = points.highlightScale + uniforms.clipBounds = clipBounds + uniforms.pickGroup = points.pickId / 255.0 + uniforms.pixelRatio = points.pixelRatio - if (a !== this) - this.sign = true; + for(var i=0; i<3; ++i) { + if(!axesProject[i]) { + continue + } + if((points.projectOpacity[i] < 1) !== transparent) { + continue + } - return this.strip(); -}; + uniforms.scale = points.projectScale[i] + uniforms.opacity = points.projectOpacity[i] -// Subtract `num` from `this` -BN.prototype.sub = function sub(num) { - return this.clone().isub(num); -}; + //Project model matrix + var pmodel = SCRATCH_MATRIX + for(var j=0; j<16; ++j) { + pmodel[j] = 0 + } + for(var j=0; j<4; ++j) { + pmodel[5*j] = 1 + } + pmodel[5*i] = 0 + if(cubeAxis[i] < 0) { + pmodel[12+i] = bounds[0][i] + } else { + pmodel[12+i] = bounds[1][i] + } + mat4mult(pmodel, model, pmodel) + uniforms.model = pmodel -/* -// NOTE: This could be potentionally used to generate loop-less multiplications -function _genCombMulTo(alen, blen) { - var len = alen + blen - 1; - var src = [ - 'var a = this.words, b = num.words, o = out.words, c = 0, w, ' + - 'mask = 0x3ffffff, shift = 0x4000000;', - 'out.length = ' + len + ';' - ]; - for (var k = 0; k < len; k++) { - var minJ = Math.max(0, k - alen + 1); - var maxJ = Math.min(k, blen - 1); + //Compute initial axes + var u = (i+1)%3 + var v = (i+2)%3 + var du = zeroVec(U_VEC) + var dv = zeroVec(V_VEC) + du[u] = 1 + dv[v] = 1 - for (var j = minJ; j <= maxJ; j++) { - var i = k - j; - var mul = 'a[' + i + '] * b[' + j + ']'; + //Align orientation relative to viewer + var mdu = project(projection, view, model, augment(MU_VEC, du)) + var mdv = project(projection, view, model, augment(MV_VEC, dv)) + if(Math.abs(mdu[1]) > Math.abs(mdv[1])) { + var tmp = mdu + mdu = mdv + mdv = tmp + tmp = du + du = dv + dv = tmp + var t = u + u = v + v = t + } + if(mdu[0] < 0) { + du[u] = -1 + } + if(mdv[1] > 0) { + dv[v] = -1 + } + var su = 0.0 + var sv = 0.0 + for(var j=0; j<4; ++j) { + su += Math.pow(model[4*u+j], 2) + sv += Math.pow(model[4*v+j], 2) + } + du[u] /= Math.sqrt(su) + dv[v] /= Math.sqrt(sv) + uniforms.axes[0] = du + uniforms.axes[1] = dv - if (j === minJ) { - src.push('w = ' + mul + ' + c;'); - src.push('c = (w / shift) | 0;'); - } else { - src.push('w += ' + mul + ';'); - src.push('c += (w / shift) | 0;'); - } - src.push('w &= mask;'); + //Update fragment clip bounds + uniforms.fragClipBounds[0] = setComponent(SCRATCH_VEC, clipBounds[0], i, -1e8) + uniforms.fragClipBounds[1] = setComponent(SCRATCH_VEC, clipBounds[1], i, 1e8) + + //Draw interior + points.vao.draw(gl.TRIANGLES, points.vertexCount) + + //Draw edges + if(points.lineWidth > 0) { + gl.lineWidth(points.lineWidth) + points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) } - src.push('o[' + k + '] = w;'); } - src.push('if (c !== 0) {', - ' o[' + k + '] = c;', - ' out.length++;', - '}', - 'return out;'); - - return src.join('\n'); } -*/ -BN.prototype._smallMulTo = function _smallMulTo(num, out) { - out.sign = num.sign !== this.sign; - out.length = this.length + num.length; - var carry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = carry >>> 26; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = this.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; +var NEG_INFINITY3 = [-1e8, -1e8, -1e8] +var POS_INFINITY3 = [1e8, 1e8, 1e8] +var CLIP_GROUP = [NEG_INFINITY3, POS_INFINITY3] - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; - } - out.words[k] = rword; - carry = ncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } +function drawFull(shader, pshader, points, camera, transparent, forceDraw) { + var gl = points.gl - return out.strip(); -}; + points.vao.bind() -BN.prototype._bigMulTo = function _bigMulTo(num, out) { - out.sign = num.sign !== this.sign; - out.length = this.length + num.length; + if(transparent === (points.opacity < 1) || forceDraw) { + shader.bind() + var uniforms = shader.uniforms - var carry = 0; - var hncarry = 0; - for (var k = 0; k < out.length - 1; k++) { - // Sum all words with the same `i + j = k` and accumulate `ncarry`, - // note that ncarry could be >= 0x3ffffff - var ncarry = hncarry; - hncarry = 0; - var rword = carry & 0x3ffffff; - var maxJ = Math.min(k, num.length - 1); - for (var j = Math.max(0, k - this.length + 1); j <= maxJ; j++) { - var i = k - j; - var a = this.words[i] | 0; - var b = num.words[j] | 0; - var r = a * b; + uniforms.model = camera.model || IDENTITY + uniforms.view = camera.view || IDENTITY + uniforms.projection = camera.projection || IDENTITY + + VIEW_SHAPE[0] = 2.0/gl.drawingBufferWidth + VIEW_SHAPE[1] = 2.0/gl.drawingBufferHeight + uniforms.screenSize = VIEW_SHAPE - var lo = r & 0x3ffffff; - ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; - lo = (lo + rword) | 0; - rword = lo & 0x3ffffff; - ncarry = (ncarry + (lo >>> 26)) | 0; + uniforms.highlightId = points.highlightId + uniforms.highlightScale = points.highlightScale - hncarry += ncarry >>> 26; - ncarry &= 0x3ffffff; - } - out.words[k] = rword; - carry = ncarry; - ncarry = hncarry; - } - if (carry !== 0) { - out.words[k] = carry; - } else { - out.length--; - } + uniforms.fragClipBounds = CLIP_GROUP + uniforms.clipBounds = points.axes.bounds - return out.strip(); -}; + uniforms.opacity = points.opacity + uniforms.pickGroup = points.pickId / 255.0 -BN.prototype.mulTo = function mulTo(num, out) { - var res; - if (this.length + num.length < 63) - res = this._smallMulTo(num, out); - else - res = this._bigMulTo(num, out); - return res; -}; + uniforms.pixelRatio = points.pixelRatio -// Multiply `this` by `num` -BN.prototype.mul = function mul(num) { - var out = new BN(null); - out.words = new Array(this.length + num.length); - return this.mulTo(num, out); -}; + //Draw interior + points.vao.draw(gl.TRIANGLES, points.vertexCount) -// In-place Multiplication -BN.prototype.imul = function imul(num) { - if (this.cmpn(0) === 0 || num.cmpn(0) === 0) { - this.words[0] = 0; - this.length = 1; - return this; + //Draw edges + if(points.lineWidth > 0) { + gl.lineWidth(points.lineWidth) + points.vao.draw(gl.LINES, points.lineVertexCount, points.vertexCount) + } } - var tlen = this.length; - var nlen = num.length; + drawProject(pshader, points, camera, transparent, forceDraw) - this.sign = num.sign !== this.sign; - this.length = this.length + num.length; - this.words[this.length - 1] = 0; + points.vao.unbind() +} - for (var k = this.length - 2; k >= 0; k--) { - // Sum all words with the same `i + j = k` and accumulate `carry`, - // note that carry could be >= 0x3ffffff - var carry = 0; - var rword = 0; - var maxJ = Math.min(k, nlen - 1); - for (var j = Math.max(0, k - tlen + 1); j <= maxJ; j++) { - var i = k - j; - var a = this.words[i]; - var b = num.words[j]; - var r = a * b; +proto.draw = function(camera) { + var shader = this.useOrtho ? this.orthoShader : this.shader + drawFull(shader, this.projectShader, this, camera, false, false) +} - var lo = r & 0x3ffffff; - carry += (r / 0x4000000) | 0; - lo += rword; - rword = lo & 0x3ffffff; - carry += lo >>> 26; - } - this.words[k] = rword; - this.words[k + 1] += carry; - carry = 0; +proto.drawTransparent = function(camera) { + var shader = this.useOrtho ? this.orthoShader : this.shader + drawFull(shader, this.projectShader, this, camera, true, false) +} + +proto.drawPick = function(camera) { + var shader = this.useOrtho ? this.pickOrthoShader : this.pickPerspectiveShader + drawFull(shader, this.pickProjectShader, this, camera, false, true) +} + +proto.pick = function(selected) { + if(!selected) { + return null + } + if(selected.id !== this.pickId) { + return null + } + var x = selected.value[2] + (selected.value[1]<<8) + (selected.value[0]<<16) + if(x >= this.pointCount || x < 0) { + return null } - // Propagate overflows - var carry = 0; - for (var i = 1; i < this.length; i++) { - var w = this.words[i] + carry; - this.words[i] = w & 0x3ffffff; - carry = w >>> 26; + //Unpack result + var coord = this.points[x] + var result = this._selectResult + result.index = x + for(var i=0; i<3; ++i) { + result.position[i] = result.dataCoordinate[i] = coord[i] } + return result +} - return this.strip(); -}; +proto.highlight = function(selection) { + if(!selection) { + this.highlightId = [1,1,1,1] + } else { + var pointId = selection.index + var a0 = pointId &0xff + var a1 = (pointId>>8) &0xff + var a2 = (pointId>>16)&0xff + this.highlightId = [a0/255.0, a1/255.0, a2/255.0, 0] + } +} -BN.prototype.imuln = function imuln(num) { - assert(typeof num === 'number'); +proto.update = function(options) { - // Carry - var carry = 0; - for (var i = 0; i < this.length; i++) { - var w = this.words[i] * num; - var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); - carry >>= 26; - carry += (w / 0x4000000) | 0; - // NOTE: lo is 27bit maximum - carry += lo >>> 26; - this.words[i] = lo & 0x3ffffff; + options = options || {} + + if('perspective' in options) { + this.useOrtho = !options.perspective + } + if('orthographic' in options) { + this.useOrtho = !!options.orthographic + } + if('lineWidth' in options) { + this.lineWidth = options.lineWidth + } + if('project' in options) { + if(Array.isArray(options.project)) { + this.axesProject = options.project + } else { + var v = !!options.project + this.axesProject = [v,v,v] + } + } + if('projectScale' in options) { + if(Array.isArray(options.projectScale)) { + this.projectScale = options.projectScale.slice() + } else { + var s = +options.projectScale + this.projectScale = [s,s,s] + } + } + if('projectOpacity' in options) { + if(Array.isArray(options.projectOpacity)) { + this.projectOpacity = options.projectOpacity.slice() + } else { + var s = +options.projectOpacity + this.projectOpacity = [s,s,s] + } + } + if('opacity' in options) { + this.opacity = options.opacity } - if (carry !== 0) { - this.words[i] = carry; - this.length++; + //Set dirty flag + this.dirty = true + + //Create new buffers + var points = options.position + if(!points) { + return } - return this; -}; + //Text font + var font = options.font || 'normal' + var alignment = options.alignment || [0,0] -BN.prototype.muln = function muln(num) { - return this.clone().imuln(num); -}; + //Bounds + var lowerBound = [ Infinity, Infinity, Infinity] + var upperBound = [-Infinity,-Infinity,-Infinity] -// `this` * `this` -BN.prototype.sqr = function sqr() { - return this.mul(this); -}; + //Unpack options + var glyphs = options.glyph + var colors = options.color + var sizes = options.size + var angles = options.angle + var lineColors = options.lineColor -// `this` * `this` in-place -BN.prototype.isqr = function isqr() { - return this.mul(this); -}; + //Picking geometry + var pickCounter = 0 -// Shift-left in-place -BN.prototype.ishln = function ishln(bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; - var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + //First do pass to compute buffer sizes + var triVertexCount = 0 + var lineVertexCount = 0 - if (r !== 0) { - var carry = 0; - for (var i = 0; i < this.length; i++) { - var newCarry = this.words[i] & carryMask; - var c = (this.words[i] - newCarry) << r; - this.words[i] = c | carry; - carry = newCarry >>> (26 - r); + //Count number of points and buffer size + var numPoints = points.length + +count_loop: + for(var i=0; i= 0; i--) - this.words[i + s] = this.words[i]; - for (var i = 0; i < s; i++) - this.words[i] = 0; - this.length += s; + triVertexCount += glyphMesh.cells.length * 3 + lineVertexCount += glyphLines.edges.length * 2 } - return this.strip(); -}; -// Shift-right in-place -// NOTE: `hint` is a lowest bit before trailing zeroes -// NOTE: if `extended` is present - it will be filled with destroyed bits -BN.prototype.ishrn = function ishrn(bits, hint, extended) { - assert(typeof bits === 'number' && bits >= 0); - var h; - if (hint) - h = (hint - (hint % 26)) / 26; - else - h = 0; + //Preallocate data + var vertexCount = triVertexCount + lineVertexCount + var positionArray = pool.mallocFloat(3*vertexCount) + var colorArray = pool.mallocFloat(4*vertexCount) + var glyphArray = pool.mallocFloat(2*vertexCount) + var idArray = pool.mallocUint32(vertexCount) - var r = bits % 26; - var s = Math.min((bits - r) / 26, this.length); - var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); - var maskedWords = extended; + var textOffset = [0,alignment[1]] - h -= s; - h = Math.max(0, h); + var triOffset = 0 + var lineOffset = triVertexCount + var color = [0,0,0,1] + var lineColor = [0,0,0,1] - // Extended mode, copy masked part - if (maskedWords) { - for (var i = 0; i < s; i++) - maskedWords.words[i] = this.words[i]; - maskedWords.length = s; - } + var isColorArray = Array.isArray(colors) && Array.isArray(colors[0]) + var isLineColorArray = Array.isArray(lineColors) && Array.isArray(lineColors[0]) - if (s === 0) { - // No-op, we should not move anything at all - } else if (this.length > s) { - this.length -= s; - for (var i = 0; i < this.length; i++) - this.words[i] = this.words[i + s]; - } else { - this.words[0] = 0; - this.length = 1; - } +fill_loop: + for(var i=0; i= 0 && (carry !== 0 || i >= h); i--) { - var word = this.words[i]; - this.words[i] = (carry << (26 - r)) | (word >>> r); - carry = word & mask; - } + upperBound[j] = Math.max(upperBound[j], x[j]) + lowerBound[j] = Math.min(lowerBound[j], x[j]) + } - // Push carried bits as a mask - if (maskedWords && carry !== 0) - maskedWords.words[maskedWords.length++] = carry; + var glyphData + if(Array.isArray(glyphs)) { + glyphData = getGlyph(glyphs[i], font) + } else if(glyphs) { + glyphData = getGlyph(glyphs, font) + } else { + glyphData = getGlyph('●', font) + } + var glyphMesh = glyphData[0] + var glyphLines = glyphData[1] + var glyphBounds = glyphData[2] - if (this.length === 0) { - this.words[0] = 0; - this.length = 1; - } - this.strip(); + //Get color + if(Array.isArray(colors)) { + var c + if(isColorArray) { + c = colors[i] + } else { + c = colors + } + if(c.length === 3) { + for(var j=0; j<3; ++j) { + color[j] = c[j] + } + color[3] = 1 + } else if(c.length === 4) { + for(var j=0; j<4; ++j) { + color[j] = c[j] + } + } + } else { + color[0] = color[1] = color[2] = 0 + color[3] = 1 + } - return this; -}; + //Get lineColor + if(Array.isArray(lineColors)) { + var c + if(isLineColorArray) { + c = lineColors[i] + } else { + c = lineColors + } + if(c.length === 3) { + for(var j=0; j<3; ++j) { + lineColor[j] = c[j] + } + lineColor[j] = 1 + } else if(c.length === 4) { + for(var j=0; j<4; ++j) { + lineColor[j] = c[j] + } + } + } else { + lineColor[0] = lineColor[1] = lineColor[2] = 0 + lineColor[3] = 1 + } -// Shift-left -BN.prototype.shln = function shln(bits) { - return this.clone().ishln(bits); -}; + var size = 0.5 + if(Array.isArray(sizes)) { + size = +sizes[i] + } else if(sizes) { + size = +sizes + } else if(this.useOrtho) { + size = 12 + } -// Shift-right -BN.prototype.shrn = function shrn(bits) { - return this.clone().ishrn(bits); -}; + var angle = 0 + if(Array.isArray(angles)) { + angle = +angles[i] + } else if(angles) { + angle = +angles + } -// Test if n bit is set -BN.prototype.testn = function testn(bit) { - assert(typeof bit === 'number' && bit >= 0); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; + //Loop through markers and append to buffers + var cos = Math.cos(angle) + var sin = Math.sin(angle) - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - return false; - } + var x = points[i] + for(var j=0; j<3; ++j) { + upperBound[j] = Math.max(upperBound[j], x[j]) + lowerBound[j] = Math.min(lowerBound[j], x[j]) + } - // Check bit and return - var w = this.words[s]; + //Calculate text offset + if(alignment[0] < 0) { + textOffset[0] = alignment[0] * (1+glyphBounds[1][0]) + } else if(alignment[0] > 0) { + textOffset[0] = -alignment[0] * (1+glyphBounds[0][0]) + } - return !!(w & q); -}; + //Write out inner marker + var cells = glyphMesh.cells + var verts = glyphMesh.positions -// Return only lowers bits of number (in-place) -BN.prototype.imaskn = function imaskn(bits) { - assert(typeof bits === 'number' && bits >= 0); - var r = bits % 26; - var s = (bits - r) / 26; + for(var j=0; j>> r) << r); - this.words[this.length - 1] &= mask; + //Increment pickCounter + pickCounter += 1 } - return this.strip(); -}; -// Return only lowers bits of number -BN.prototype.maskn = function maskn(bits) { - return this.clone().imaskn(bits); -}; + //Update vertex counts + this.vertexCount = triVertexCount + this.lineVertexCount = lineVertexCount + + //Update buffers + this.pointBuffer.update(positionArray) + this.colorBuffer.update(colorArray) + this.glyphBuffer.update(glyphArray) + this.idBuffer.update(new Uint32Array(idArray)) -// Add plain number `num` to `this` -BN.prototype.iaddn = function iaddn(num) { - assert(typeof num === 'number'); - if (num < 0) - return this.isubn(-num); + pool.free(positionArray) + pool.free(colorArray) + pool.free(glyphArray) + pool.free(idArray) - // Possible sign change - if (this.sign) { - if (this.length === 1 && this.words[0] < num) { - this.words[0] = num - this.words[0]; - this.sign = false; - return this; - } + //Update bounds + this.bounds = [lowerBound, upperBound] - this.sign = false; - this.isubn(num); - this.sign = true; - return this; - } + //Save points + this.points = points - // Add without checks - return this._iaddn(num); -}; + //Save number of points + this.pointCount = points.length +} -BN.prototype._iaddn = function _iaddn(num) { - this.words[0] += num; +proto.dispose = function() { + //Shaders + this.shader.dispose() + this.orthoShader.dispose() + this.pickPerspectiveShader.dispose() + this.pickOrthoShader.dispose() - // Carry - for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { - this.words[i] -= 0x4000000; - if (i === this.length - 1) - this.words[i + 1] = 1; - else - this.words[i + 1]++; - } - this.length = Math.max(this.length, i + 1); + //Vertex array + this.vao.dispose() - return this; -}; + //Buffers + this.pointBuffer.dispose() + this.colorBuffer.dispose() + this.glyphBuffer.dispose() + this.idBuffer.dispose() +} -// Subtract plain number `num` from `this` -BN.prototype.isubn = function isubn(num) { - assert(typeof num === 'number'); - if (num < 0) - return this.iaddn(-num); +function createPointCloud(options) { + var gl = options.gl - if (this.sign) { - this.sign = false; - this.iaddn(num); - this.sign = true; - return this; - } + var shader = shaders.createPerspective(gl) + var orthoShader = shaders.createOrtho(gl) + var projectShader = shaders.createProject(gl) + var pickPerspectiveShader = shaders.createPickPerspective(gl) + var pickOrthoShader = shaders.createPickOrtho(gl) + var pickProjectShader = shaders.createPickProject(gl) - this.words[0] -= num; + var pointBuffer = createBuffer(gl) + var colorBuffer = createBuffer(gl) + var glyphBuffer = createBuffer(gl) + var idBuffer = createBuffer(gl) + var vao = createVAO(gl, [ + { + buffer: pointBuffer, + size: 3, + type: gl.FLOAT + }, + { + buffer: colorBuffer, + size: 4, + type: gl.FLOAT + }, + { + buffer: glyphBuffer, + size: 2, + type: gl.FLOAT + }, + { + buffer: idBuffer, + size: 4, + type: gl.UNSIGNED_BYTE, + normalized: true + } + ]) - // Carry - for (var i = 0; i < this.length && this.words[i] < 0; i++) { - this.words[i] += 0x4000000; - this.words[i + 1] -= 1; - } + var pointCloud = new PointCloud( + gl, + shader, + orthoShader, + projectShader, + pointBuffer, + colorBuffer, + glyphBuffer, + idBuffer, + vao, + pickPerspectiveShader, + pickOrthoShader, + pickProjectShader) - return this.strip(); -}; + pointCloud.update(options) -BN.prototype.addn = function addn(num) { - return this.clone().iaddn(num); -}; + return pointCloud +} -BN.prototype.subn = function subn(num) { - return this.clone().isubn(num); -}; +},{"./lib/glyphs":148,"./lib/shaders":149,"gl-buffer":75,"gl-mat4/multiply":96,"gl-vao":189,"typedarray-pool":233}],151:[function(require,module,exports){ +'use strict' -BN.prototype.iabs = function iabs() { - this.sign = false; - return this; -}; -BN.prototype.abs = function abs() { - return this.clone().iabs(); -}; +exports.boxVertex = "#define GLSLIFY 1\nprecision mediump float;\n\nattribute vec2 vertex;\n\nuniform vec2 cornerA, cornerB;\n\nvoid main() {\n gl_Position = vec4(mix(cornerA, cornerB, vertex), 0, 1);\n}\n" +exports.boxFragment = "#define GLSLIFY 1\nprecision mediump float;\n\nuniform vec4 color;\n\nvoid main() {\n gl_FragColor = color;\n}\n" -BN.prototype._ishlnsubmul = function _ishlnsubmul(num, mul, shift) { - // Bigger storage is needed - var len = num.length + shift; - var i; - if (this.words.length < len) { - var t = new Array(len); - for (var i = 0; i < this.length; i++) - t[i] = this.words[i]; - this.words = t; - } else { - i = this.length; - } +},{}],152:[function(require,module,exports){ +'use strict' - // Zeroify rest - this.length = Math.max(this.length, len); - for (; i < this.length; i++) - this.words[i] = 0; +var createShader = require('gl-shader') +var createBuffer = require('gl-buffer') - var carry = 0; - for (var i = 0; i < num.length; i++) { - var w = this.words[i + shift] + carry; - var right = num.words[i] * mul; - w -= right & 0x3ffffff; - carry = (w >> 26) - ((right / 0x4000000) | 0); - this.words[i + shift] = w & 0x3ffffff; - } - for (; i < this.length - shift; i++) { - var w = this.words[i + shift] + carry; - carry = w >> 26; - this.words[i + shift] = w & 0x3ffffff; - } +var SHADERS = require('./lib/shaders') - if (carry === 0) - return this.strip(); +module.exports = createSelectBox - // Subtraction overflow - assert(carry === -1); - carry = 0; - for (var i = 0; i < this.length; i++) { - var w = -this.words[i] + carry; - carry = w >> 26; - this.words[i] = w & 0x3ffffff; - } - this.sign = true; +function SelectBox(plot, boxBuffer, boxShader) { + this.plot = plot + this.boxBuffer = boxBuffer + this.boxShader = boxShader - return this.strip(); -}; + this.enabled = true -BN.prototype._wordDiv = function _wordDiv(num, mode) { - var shift = this.length - num.length; + this.selectBox = [Infinity,Infinity,-Infinity,-Infinity] - var a = this.clone(); - var b = num; + this.borderColor = [0,0,0,1] + this.innerFill = false + this.innerColor = [0,0,0,0.25] + this.outerFill = true + this.outerColor = [0,0,0,0.5] + this.borderWidth = 10 +} - // Normalize - var bhi = b.words[b.length - 1]; - var bhiBits = this._countBits(bhi); - shift = 26 - bhiBits; - if (shift !== 0) { - b = b.shln(shift); - a.ishln(shift); - bhi = b.words[b.length - 1]; +var proto = SelectBox.prototype + +proto.draw = function() { + if(!this.enabled) { + return } - // Initialize quotient - var m = a.length - b.length; - var q; + var plot = this.plot + var selectBox = this.selectBox + var lineWidth = this.borderWidth - if (mode !== 'mod') { - q = new BN(null); - q.length = m + 1; - q.words = new Array(q.length); - for (var i = 0; i < q.length; i++) - q.words[i] = 0; - } + var innerFill = this.innerFill + var innerColor = this.innerColor + var outerFill = this.outerFill + var outerColor = this.outerColor + var borderColor = this.borderColor - var diff = a.clone()._ishlnsubmul(b, 1, m); - if (!diff.sign) { - a = diff; - if (q) - q.words[m] = 1; - } + var boxes = plot.box + var screenBox = plot.screenBox + var dataBox = plot.dataBox + var viewBox = plot.viewBox + var pixelRatio = plot.pixelRatio - for (var j = m - 1; j >= 0; j--) { - var qj = a.words[b.length + j] * 0x4000000 + a.words[b.length + j - 1]; + //Map select box into pixel coordinates + var loX = (selectBox[0]-dataBox[0])*(viewBox[2]-viewBox[0])/(dataBox[2]-dataBox[0])+viewBox[0] + var loY = (selectBox[1]-dataBox[1])*(viewBox[3]-viewBox[1])/(dataBox[3]-dataBox[1])+viewBox[1] + var hiX = (selectBox[2]-dataBox[0])*(viewBox[2]-viewBox[0])/(dataBox[2]-dataBox[0])+viewBox[0] + var hiY = (selectBox[3]-dataBox[1])*(viewBox[3]-viewBox[1])/(dataBox[3]-dataBox[1])+viewBox[1] - // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max - // (0x7ffffff) - qj = Math.min((qj / bhi) | 0, 0x3ffffff); + loX = Math.max(loX, viewBox[0]) + loY = Math.max(loY, viewBox[1]) + hiX = Math.min(hiX, viewBox[2]) + hiY = Math.min(hiY, viewBox[3]) - a._ishlnsubmul(b, qj, j); - while (a.sign) { - qj--; - a.sign = false; - a._ishlnsubmul(b, 1, j); - if (a.cmpn(0) !== 0) - a.sign = !a.sign; - } - if (q) - q.words[j] = qj; + if(hiX < loX || hiY < loY) { + return } - if (q) - q.strip(); - a.strip(); - // Denormalize - if (mode !== 'div' && shift !== 0) - a.ishrn(shift); - return { div: q ? q : null, mod: a }; -}; + boxes.bind() -BN.prototype.divmod = function divmod(num, mode) { - assert(num.cmpn(0) !== 0); + //Draw box + var screenWidth = screenBox[2] - screenBox[0] + var screenHeight = screenBox[3] - screenBox[1] - if (this.sign && !num.sign) { - var res = this.neg().divmod(num, mode); - var div; - var mod; - if (mode !== 'mod') - div = res.div.neg(); - if (mode !== 'div') - mod = res.mod.cmpn(0) === 0 ? res.mod : num.sub(res.mod); - return { - div: div, - mod: mod - }; - } else if (!this.sign && num.sign) { - var res = this.divmod(num.neg(), mode); - var div; - if (mode !== 'mod') - div = res.div.neg(); - return { div: div, mod: res.mod }; - } else if (this.sign && num.sign) { - return this.neg().divmod(num.neg(), mode); + if(this.outerFill) { + boxes.drawBox(0, 0, screenWidth, loY, outerColor) + boxes.drawBox(0, loY, loX, hiY, outerColor) + boxes.drawBox(0, hiY, screenWidth, screenHeight, outerColor) + boxes.drawBox(hiX, loY, screenWidth, hiY, outerColor) } - // Both numbers are positive at this point + if(this.innerFill) { + boxes.drawBox(loX, loY, hiX, hiY, innerColor) + } - // Strip both numbers to approximate shift value - if (num.length > this.length || this.cmp(num) < 0) - return { div: new BN(0), mod: this }; + //Draw border + if(lineWidth > 0) { - // Very short reduction - if (num.length === 1) { - if (mode === 'div') - return { div: this.divn(num.words[0]), mod: null }; - else if (mode === 'mod') - return { div: null, mod: new BN(this.modn(num.words[0])) }; - return { - div: this.divn(num.words[0]), - mod: new BN(this.modn(num.words[0])) - }; + //Draw border + var w = lineWidth * pixelRatio + boxes.drawBox(loX-w, loY-w, hiX+w, loY+w, borderColor) + boxes.drawBox(loX-w, hiY-w, hiX+w, hiY+w, borderColor) + boxes.drawBox(loX-w, loY-w, loX+w, hiY+w, borderColor) + boxes.drawBox(hiX-w, loY-w, hiX+w, hiY+w, borderColor) } +} - return this._wordDiv(num, mode); -}; +proto.update = function(options) { + options = options || {} -// Find `this` / `num` -BN.prototype.div = function div(num) { - return this.divmod(num, 'div').div; -}; + this.innerFill = !!options.innerFill + this.outerFill = !!options.outerFill + this.innerColor = (options.innerColor || [0,0,0,0.5]).slice() + this.outerColor = (options.outerColor || [0,0,0,0.5]).slice() + this.borderColor = (options.borderColor || [0,0,0,1]).slice() + this.borderWidth = options.borderWidth || 0 + this.selectBox = (options.selectBox || this.selectBox).slice() +} -// Find `this` % `num` -BN.prototype.mod = function mod(num) { - return this.divmod(num, 'mod').mod; -}; +proto.dispose = function() { + this.boxBuffer.dispose() + this.boxShader.dispose() + this.plot.removeOverlay(this) +} -// Find Round(`this` / `num`) -BN.prototype.divRound = function divRound(num) { - var dm = this.divmod(num); +function createSelectBox(plot, options) { + var gl = plot.gl + var buffer = createBuffer(gl, [ + 0, 0, + 0, 1, + 1, 0, + 1, 1 ]) + var shader = createShader(gl, SHADERS.boxVertex, SHADERS.boxFragment) + var selectBox = new SelectBox(plot, buffer, shader) + selectBox.update(options) + plot.addOverlay(selectBox) + return selectBox +} - // Fast case - exact division - if (dm.mod.cmpn(0) === 0) - return dm.div; +},{"./lib/shaders":151,"gl-buffer":75,"gl-shader":154}],153:[function(require,module,exports){ +'use strict' - var mod = dm.div.sign ? dm.mod.isub(num) : dm.mod; +module.exports = createSelectBuffer - var half = num.shrn(1); - var r2 = num.andln(1); - var cmp = mod.cmp(half); +var createFBO = require('gl-fbo') +var pool = require('typedarray-pool') +var ndarray = require('ndarray') - // Round down - if (cmp < 0 || r2 === 1 && cmp === 0) - return dm.div; +var nextPow2 = require('bit-twiddle').nextPow2 - // Round up - return dm.div.sign ? dm.div.isubn(1) : dm.div.iaddn(1); -}; +var selectRange = require('cwise/lib/wrapper')({"args":["array",{"offset":[0,0,1],"array":0},{"offset":[0,0,2],"array":0},{"offset":[0,0,3],"array":0},"scalar","scalar","index"],"pre":{"body":"{this_closestD2=1e8,this_closestX=-1,this_closestY=-1}","args":[],"thisVars":["this_closestD2","this_closestX","this_closestY"],"localVars":[]},"body":{"body":"{if(255>_inline_34_arg0_||255>_inline_34_arg1_||255>_inline_34_arg2_||255>_inline_34_arg3_){var _inline_34_l=_inline_34_arg4_-_inline_34_arg6_[0],_inline_34_a=_inline_34_arg5_-_inline_34_arg6_[1],_inline_34_f=_inline_34_l*_inline_34_l+_inline_34_a*_inline_34_a;_inline_34_f= 0; i--) - acc = (p * acc + this.words[i]) % num; +function SelectBuffer(gl, fbo, buffer) { + this.gl = gl + this.fbo = fbo + this.buffer = buffer + this._readTimeout = null + var self = this - return acc; -}; + this._readCallback = function() { + if(!self.gl) { + return + } + fbo.bind() + gl.readPixels(0,0,fbo.shape[0],fbo.shape[1],gl.RGBA,gl.UNSIGNED_BYTE,self.buffer) + self._readTimeout = null + } +} -// In-place division by number -BN.prototype.idivn = function idivn(num) { - assert(num <= 0x3ffffff); +var proto = SelectBuffer.prototype - var carry = 0; - for (var i = this.length - 1; i >= 0; i--) { - var w = this.words[i] + carry * 0x4000000; - this.words[i] = (w / num) | 0; - carry = w % num; +Object.defineProperty(proto, 'shape', { + get: function() { + if(!this.gl) { + return [0,0] + } + return this.fbo.shape.slice() + }, + set: function(v) { + if(!this.gl) { + return + } + this.fbo.shape = v + var c = this.fbo.shape[0] + var r = this.fbo.shape[1] + if(r*c*4 > this.buffer.length) { + pool.free(this.buffer) + var buffer = this.buffer = pool.mallocUint8(nextPow2(r*c*4)) + for(var i=0; i= 0) { - x.isub(y); - A.isub(C); - B.isub(D); - } else { - y.isub(x); - C.isub(A); - D.isub(B); - } + return new SelectResult( + (dx + x0)|0, + (dy + y0)|0, + c0, + [c1, c2, c3], + Math.sqrt(closest[2])) +} + +proto.dispose = function() { + if(!this.gl) { + return + } + this.fbo.dispose() + pool.free(this.buffer) + this.gl = null + if(this._readTimeout) { + clearTimeout(this._readTimeout) } +} - return { - a: C, - b: D, - gcd: y.ishln(g) - }; -}; +function createSelectBuffer(gl, shape) { + var fbo = createFBO(gl, shape) + var buffer = pool.mallocUint8(shape[0]*shape[1]*4) + return new SelectBuffer(gl, fbo, buffer) +} -// This is reduced incarnation of the binary EEA -// above, designated to invert members of the -// _prime_ fields F(p) at a maximal speed -BN.prototype._invmp = function _invmp(p) { - assert(!p.sign); - assert(p.cmpn(0) !== 0); +},{"bit-twiddle":49,"cwise/lib/wrapper":69,"gl-fbo":80,"ndarray":208,"typedarray-pool":233}],154:[function(require,module,exports){ +'use strict' - var a = this; - var b = p.clone(); +var createUniformWrapper = require('./lib/create-uniforms') +var createAttributeWrapper = require('./lib/create-attributes') +var makeReflect = require('./lib/reflect') +var shaderCache = require('./lib/shader-cache') +var runtime = require('./lib/runtime-reflect') +var GLError = require("./lib/GLError") - if (a.sign) - a = a.mod(p); - else - a = a.clone(); +//Shader object +function Shader(gl) { + this.gl = gl - var x1 = new BN(1); - var x2 = new BN(0); + //Default initialize these to null + this._vref = + this._fref = + this._relink = + this.vertShader = + this.fragShader = + this.program = + this.attributes = + this.uniforms = + this.types = null +} - var delta = b.clone(); +var proto = Shader.prototype - while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { - while (a.isEven()) { - a.ishrn(1); - if (x1.isEven()) - x1.ishrn(1); - else - x1.iadd(delta).ishrn(1); - } - while (b.isEven()) { - b.ishrn(1); - if (x2.isEven()) - x2.ishrn(1); - else - x2.iadd(delta).ishrn(1); - } - if (a.cmp(b) >= 0) { - a.isub(b); - x1.isub(x2); - } else { - b.isub(a); - x2.isub(x1); - } +proto.bind = function() { + if(!this.program) { + this._relink() } - if (a.cmpn(1) === 0) - return x1; - else - return x2; -}; - -BN.prototype.gcd = function gcd(num) { - if (this.cmpn(0) === 0) - return num.clone(); - if (num.cmpn(0) === 0) - return this.clone(); + this.gl.useProgram(this.program) +} - var a = this.clone(); - var b = num.clone(); - a.sign = false; - b.sign = false; +proto.dispose = function() { + if(this._fref) { + this._fref.dispose() + } + if(this._vref) { + this._vref.dispose() + } + this.attributes = + this.types = + this.vertShader = + this.fragShader = + this.program = + this._relink = + this._fref = + this._vref = null +} - // Remove common factor of two - for (var shift = 0; a.isEven() && b.isEven(); shift++) { - a.ishrn(1); - b.ishrn(1); +function compareAttributes(a, b) { + if(a.name < b.name) { + return -1 } + return 1 +} - do { - while (a.isEven()) - a.ishrn(1); - while (b.isEven()) - b.ishrn(1); +//Update export hook for glslify-live +proto.update = function( + vertSource + , fragSource + , uniforms + , attributes) { - var r = a.cmp(b); - if (r < 0) { - // Swap `a` and `b` to make `a` always bigger than `b` - var t = a; - a = b; - b = t; - } else if (r === 0 || b.cmpn(1) === 0) { - break; - } + //If only one object passed, assume glslify style output + if(!fragSource || arguments.length === 1) { + var obj = vertSource + vertSource = obj.vertex + fragSource = obj.fragment + uniforms = obj.uniforms + attributes = obj.attributes + } - a.isub(b); - } while (true); + var wrapper = this + var gl = wrapper.gl - return b.ishln(shift); -}; + //Compile vertex and fragment shaders + var pvref = wrapper._vref + wrapper._vref = shaderCache.shader(gl, gl.VERTEX_SHADER, vertSource) + if(pvref) { + pvref.dispose() + } + wrapper.vertShader = wrapper._vref.shader + var pfref = this._fref + wrapper._fref = shaderCache.shader(gl, gl.FRAGMENT_SHADER, fragSource) + if(pfref) { + pfref.dispose() + } + wrapper.fragShader = wrapper._fref.shader -// Invert number in the field F(num) -BN.prototype.invm = function invm(num) { - return this.egcd(num).a.mod(num); -}; + //If uniforms/attributes is not specified, use RT reflection + if(!uniforms || !attributes) { -BN.prototype.isEven = function isEven() { - return (this.words[0] & 1) === 0; -}; + //Create initial test program + var testProgram = gl.createProgram() + gl.attachShader(testProgram, wrapper.fragShader) + gl.attachShader(testProgram, wrapper.vertShader) + gl.linkProgram(testProgram) + if(!gl.getProgramParameter(testProgram, gl.LINK_STATUS)) { + var errLog = gl.getProgramInfoLog(testProgram) + throw new GLError(errLog, 'Error linking program:' + errLog) + } -BN.prototype.isOdd = function isOdd() { - return (this.words[0] & 1) === 1; -}; + //Load data from runtime + uniforms = uniforms || runtime.uniforms(gl, testProgram) + attributes = attributes || runtime.attributes(gl, testProgram) -// And first word and num -BN.prototype.andln = function andln(num) { - return this.words[0] & num; -}; + //Release test program + gl.deleteProgram(testProgram) + } -// Increment at the bit position in-line -BN.prototype.bincn = function bincn(bit) { - assert(typeof bit === 'number'); - var r = bit % 26; - var s = (bit - r) / 26; - var q = 1 << r; + //Sort attributes lexicographically + // overrides undefined WebGL behavior for attribute locations + attributes = attributes.slice() + attributes.sort(compareAttributes) - // Fast case: bit is much higher than all existing words - if (this.length <= s) { - for (var i = this.length; i < s + 1; i++) - this.words[i] = 0; - this.words[s] |= q; - this.length = s + 1; - return this; + //Convert attribute types, read out locations + var attributeUnpacked = [] + var attributeNames = [] + var attributeLocations = [] + for(var i=0; i= 0) { + var size = attr.type.charAt(attr.type.length-1)|0 + var locVector = new Array(size) + for(var j=0; j>> 26; - w &= 0x3ffffff; - this.words[i] = w; - } - if (carry !== 0) { - this.words[i] = carry; - this.length++; + //For all unspecified attributes, assign them lexicographically min attribute + var curLocation = 0 + for(var i=0; i= 0) { + curLocation += 1 + } + attributeLocations[i] = curLocation + } } - return this; -}; -BN.prototype.cmpn = function cmpn(num) { - var sign = num < 0; - if (sign) - num = -num; + //Rebuild program and recompute all uniform locations + var uniformLocations = new Array(uniforms.length) + function relink() { + wrapper.program = shaderCache.program( + gl + , wrapper._vref + , wrapper._fref + , attributeNames + , attributeLocations) - if (this.sign && !sign) - return -1; - else if (!this.sign && sign) - return 1; + for(var i=0; i 1) { - res = 1; - } else { - var w = this.words[0]; - res = w === num ? 0 : w < num ? -1 : 1; + //Save relinking procedure, defer until runtime + wrapper._relink = relink + + //Generate type info + wrapper.types = { + uniforms: makeReflect(uniforms), + attributes: makeReflect(attributes) } - if (this.sign) - res = -res; - return res; -}; -// Compare two numbers and return: -// 1 - if `this` > `num` -// 0 - if `this` == `num` -// -1 - if `this` < `num` -BN.prototype.cmp = function cmp(num) { - if (this.sign && !num.sign) - return -1; - else if (!this.sign && num.sign) - return 1; + //Generate attribute wrappers + wrapper.attributes = createAttributeWrapper( + gl + , wrapper + , attributeUnpacked + , attributeLocations) - var res = this.ucmp(num); - if (this.sign) - return -res; - else - return res; -}; + //Generate uniform wrappers + Object.defineProperty(wrapper, 'uniforms', createUniformWrapper( + gl + , wrapper + , uniforms + , uniformLocations)) +} -// Unsigned comparison -BN.prototype.ucmp = function ucmp(num) { - // At this point both numbers have the same sign - if (this.length > num.length) - return 1; - else if (this.length < num.length) - return -1; +//Compiles and links a shader program with the given attribute and vertex list +function createShader( + gl + , vertSource + , fragSource + , uniforms + , attributes) { - var res = 0; - for (var i = this.length - 1; i >= 0; i--) { - var a = this.words[i]; - var b = num.words[i]; + var shader = new Shader(gl) - if (a === b) - continue; - if (a < b) - res = -1; - else if (a > b) - res = 1; - break; - } - return res; -}; + shader.update( + vertSource + , fragSource + , uniforms + , attributes) -// -// A reduce context, could be using montgomery or something better, depending -// on the `m` itself. -// -BN.red = function red(num) { - return new Red(num); -}; + return shader +} -BN.prototype.toRed = function toRed(ctx) { - assert(!this.red, 'Already a number in reduction context'); - assert(!this.sign, 'red works only with positives'); - return ctx.convertTo(this)._forceRed(ctx); -}; +module.exports = createShader -BN.prototype.fromRed = function fromRed() { - assert(this.red, 'fromRed works only with numbers in reduction context'); - return this.red.convertFrom(this); -}; +},{"./lib/GLError":155,"./lib/create-attributes":156,"./lib/create-uniforms":157,"./lib/reflect":158,"./lib/runtime-reflect":159,"./lib/shader-cache":160}],155:[function(require,module,exports){ +function GLError (rawError, shortMessage, longMessage) { + this.shortMessage = shortMessage || '' + this.longMessage = longMessage || '' + this.rawError = rawError || '' + this.message = + 'gl-shader: ' + (shortMessage || rawError || '') + + (longMessage ? '\n'+longMessage : '') + this.stack = (new Error()).stack +} +GLError.prototype = new Error +GLError.prototype.name = 'GLError' +GLError.prototype.constructor = GLError +module.exports = GLError -BN.prototype._forceRed = function _forceRed(ctx) { - this.red = ctx; - return this; -}; +},{}],156:[function(require,module,exports){ +'use strict' -BN.prototype.forceRed = function forceRed(ctx) { - assert(!this.red, 'Already a number in reduction context'); - return this._forceRed(ctx); -}; +module.exports = createAttributeWrapper + +var GLError = require("./GLError") + +function ShaderAttribute( + gl + , wrapper + , index + , locations + , dimension + , constFunc) { + this._gl = gl + this._wrapper = wrapper + this._index = index + this._locations = locations + this._dimension = dimension + this._constFunc = constFunc +} -BN.prototype.redAdd = function redAdd(num) { - assert(this.red, 'redAdd works only with red numbers'); - return this.red.add(this, num); -}; +var proto = ShaderAttribute.prototype -BN.prototype.redIAdd = function redIAdd(num) { - assert(this.red, 'redIAdd works only with red numbers'); - return this.red.iadd(this, num); -}; +proto.pointer = function setAttribPointer( + type + , normalized + , stride + , offset) { -BN.prototype.redSub = function redSub(num) { - assert(this.red, 'redSub works only with red numbers'); - return this.red.sub(this, num); -}; + var self = this + var gl = self._gl + var location = self._locations[self._index] -BN.prototype.redISub = function redISub(num) { - assert(this.red, 'redISub works only with red numbers'); - return this.red.isub(this, num); -}; + gl.vertexAttribPointer( + location + , self._dimension + , type || gl.FLOAT + , !!normalized + , stride || 0 + , offset || 0) + gl.enableVertexAttribArray(location) +} -BN.prototype.redShl = function redShl(num) { - assert(this.red, 'redShl works only with red numbers'); - return this.red.shl(this, num); -}; +proto.set = function(x0, x1, x2, x3) { + return this._constFunc(this._locations[this._index], x0, x1, x2, x3) +} -BN.prototype.redMul = function redMul(num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.mul(this, num); -}; +Object.defineProperty(proto, 'location', { + get: function() { + return this._locations[this._index] + } + , set: function(v) { + if(v !== this._locations[this._index]) { + this._locations[this._index] = v|0 + this._wrapper.program = null + } + return v|0 + } +}) -BN.prototype.redIMul = function redIMul(num) { - assert(this.red, 'redMul works only with red numbers'); - this.red._verify2(this, num); - return this.red.imul(this, num); -}; +//Adds a vector attribute to obj +function addVectorAttribute( + gl + , wrapper + , index + , locations + , dimension + , obj + , name) { -BN.prototype.redSqr = function redSqr() { - assert(this.red, 'redSqr works only with red numbers'); - this.red._verify1(this); - return this.red.sqr(this); -}; + //Construct constant function + var constFuncArgs = [ 'gl', 'v' ] + var varNames = [] + for(var i=0; i this.n); + var a = attributes[i] + var name = a.name + var type = a.type + var locs = a.locations - var cmp = rlen < this.n ? -1 : r.ucmp(this.p); - if (cmp === 0) { - r.words[0] = 0; - r.length = 1; - } else if (cmp > 0) { - r.isub(this.p); - } else { - r.strip(); + switch(type) { + case 'bool': + case 'int': + case 'float': + addVectorAttribute( + gl + , wrapper + , locs[0] + , locations + , 1 + , obj + , name) + break + + default: + if(type.indexOf('vec') >= 0) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) + } + addVectorAttribute( + gl + , wrapper + , locs[0] + , locations + , d + , obj + , name) + } else if(type.indexOf('mat') >= 0) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) + } + addMatrixAttribute( + gl + , wrapper + , locs + , locations + , d + , obj + , name) + } else { + throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type) + } + break + } } + return obj +} - return r; -}; +},{"./GLError":155}],157:[function(require,module,exports){ +'use strict' -MPrime.prototype.split = function split(input, out) { - input.ishrn(this.n, 0, out); -}; +var coallesceUniforms = require('./reflect') +var GLError = require("./GLError") -MPrime.prototype.imulK = function imulK(num) { - return num.imul(this.k); -}; +module.exports = createUniformWrapper -function K256() { - MPrime.call( - this, - 'k256', - 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); +//Binds a function and returns a value +function identity(x) { + var c = new Function('y', 'return function(){return y}') + return c(x) } -inherits(K256, MPrime); - -K256.prototype.split = function split(input, output) { - // 256 = 9 * 26 + 22 - var mask = 0x3fffff; - - var outLen = Math.min(input.length, 9); - for (var i = 0; i < outLen; i++) - output.words[i] = input.words[i]; - output.length = outLen; - if (input.length <= 9) { - input.words[0] = 0; - input.length = 1; - return; +function makeVector(length, fill) { + var result = new Array(length) + for(var i=0; i>> 22); - prev = next; + function makeGetter(index) { + var proc = new Function( + 'gl' + , 'wrapper' + , 'locations' + , 'return function(){return gl.getUniform(wrapper.program,locations[' + index + '])}') + return proc(gl, wrapper, locations) } - input.words[i - 10] = prev >>> 22; - input.length -= 9; -}; - -K256.prototype.imulK = function imulK(num) { - // K = 0x1000003d1 = [ 0x40, 0x3d1 ] - num.words[num.length] = 0; - num.words[num.length + 1] = 0; - num.length += 2; - // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 - var hi; - var lo = 0; - for (var i = 0; i < num.length; i++) { - var w = num.words[i]; - hi = w * 0x40; - lo += w * 0x3d1; - hi += (lo / 0x4000000) | 0; - lo &= 0x3ffffff; + function makePropSetter(path, index, type) { + switch(type) { + case 'bool': + case 'int': + case 'sampler2D': + case 'samplerCube': + return 'gl.uniform1i(locations[' + index + '],obj' + path + ')' + case 'float': + return 'gl.uniform1f(locations[' + index + '],obj' + path + ')' + default: + var vidx = type.indexOf('vec') + if(0 <= vidx && vidx <= 1 && type.length === 4 + vidx) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid data type') + } + switch(type.charAt(0)) { + case 'b': + case 'i': + return 'gl.uniform' + d + 'iv(locations[' + index + '],obj' + path + ')' + case 'v': + return 'gl.uniform' + d + 'fv(locations[' + index + '],obj' + path + ')' + default: + throw new GLError('', 'Unrecognized data type for vector ' + name + ': ' + type) + } + } else if(type.indexOf('mat') === 0 && type.length === 4) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) + } + return 'gl.uniformMatrix' + d + 'fv(locations[' + index + '],false,obj' + path + ')' + } else { + throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + } + break + } + } - num.words[i] = lo; + function enumerateIndices(prefix, type) { + if(typeof type !== 'object') { + return [ [prefix, type] ] + } + var indices = [] + for(var id in type) { + var prop = type[id] + var tprefix = prefix + if(parseInt(id) + '' === id) { + tprefix += '[' + id + ']' + } else { + tprefix += '.' + id + } + if(typeof prop === 'object') { + indices.push.apply(indices, enumerateIndices(tprefix, prop)) + } else { + indices.push([tprefix, prop]) + } + } + return indices + } - lo = hi; + function makeSetter(type) { + var code = [ 'return function updateProperty(obj){' ] + var indices = enumerateIndices('', type) + for(var i=0; i 4) { + throw new GLError('', 'Invalid data type') + } + if(type.charAt(0) === 'b') { + return makeVector(d, false) + } + return makeVector(d, 0) + } else if(type.indexOf('mat') === 0 && type.length === 4) { + var d = type.charCodeAt(type.length-1) - 48 + if(d < 2 || d > 4) { + throw new GLError('', 'Invalid uniform dimension type for matrix ' + name + ': ' + type) + } + return makeVector(d*d, 0) + } else { + throw new GLError('', 'Unknown uniform data type for ' + name + ': ' + type) + } + break + } } - return num; -}; - -function P224() { - MPrime.call( - this, - 'p224', - 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); -} -inherits(P224, MPrime); - -function P192() { - MPrime.call( - this, - 'p192', - 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); -} -inherits(P192, MPrime); - -function P25519() { - // 2 ^ 255 - 19 - MPrime.call( - this, - '25519', - '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); -} -inherits(P25519, MPrime); -P25519.prototype.imulK = function imulK(num) { - // K = 0x13 - var carry = 0; - for (var i = 0; i < num.length; i++) { - var hi = num.words[i] * 0x13 + carry; - var lo = hi & 0x3ffffff; - hi >>>= 26; + function storeProperty(obj, prop, type) { + if(typeof type === 'object') { + var child = processObject(type) + Object.defineProperty(obj, prop, { + get: identity(child), + set: makeSetter(type), + enumerable: true, + configurable: false + }) + } else { + if(locations[type]) { + Object.defineProperty(obj, prop, { + get: makeGetter(type), + set: makeSetter(type), + enumerable: true, + configurable: false + }) + } else { + obj[prop] = defaultValue(uniforms[type].type) + } + } + } - num.words[i] = lo; - carry = hi; + function processObject(obj) { + var result + if(Array.isArray(obj)) { + result = new Array(obj.length) + for(var i=0; i 1) { + if(!(x[0] in o)) { + o[x[0]] = [] + } + o = o[x[0]] + for(var k=1; k= 0) - res.isub(this.m); - return res._forceRed(this); -}; +function getType(gl, type) { + if(!GL_TABLE) { + var typeNames = Object.keys(GL_TO_GLSL_TYPES) + GL_TABLE = {} + for(var i=0; i 1) { + for(var j=0; j= 0) - res.isub(this.m); - return res; -}; +function runtimeAttributes(gl, program) { + var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES) + var result = [] + for(var i=0; i= 0) - res = u.isub(this.m); - else if (u.cmpn(0) < 0) - res = u.iadd(this.m); + var lines = string.split(/\r?\n/) + var totalDigits = String(lines.length + start - 1).length + return lines.map(function (line, i) { + var c = i + start + var digits = String(c).length + var prefix = padLeft(c, totalDigits - digits) + return prefix + delim + line + }).join('\n') +} - return res._forceRed(this); -}; +},{"pad-left":163}],163:[function(require,module,exports){ +/*! + * pad-left + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT license. + */ -Mont.prototype.mul = function mul(a, b) { - if (a.cmpn(0) === 0 || b.cmpn(0) === 0) - return new BN(0)._forceRed(this); +'use strict'; - var t = a.mul(b); - var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); - var u = t.isub(c).ishrn(this.shift); - var res = u; - if (u.cmp(this.m) >= 0) - res = u.isub(this.m); - else if (u.cmpn(0) < 0) - res = u.iadd(this.m); +var repeat = require('repeat-string'); - return res._forceRed(this); +module.exports = function padLeft(str, num, ch) { + ch = typeof ch !== 'undefined' ? (ch + '') : ' '; + return repeat(ch, num) + str; }; +},{"repeat-string":164}],164:[function(require,module,exports){ +/*! + * repeat-string + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ -Mont.prototype.invm = function invm(a) { - // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R - var res = this.imod(a._invmp(this.m).mul(this.r2)); - return res._forceRed(this); -}; +'use strict'; -})(typeof module === 'undefined' || module, this); +/** + * Expose `repeat` + */ -},{}],353:[function(require,module,exports){ -(function (Buffer){ -var hasTypedArrays = false -if(typeof Float64Array !== "undefined") { - var DOUBLE_VIEW = new Float64Array(1) - , UINT_VIEW = new Uint32Array(DOUBLE_VIEW.buffer) - DOUBLE_VIEW[0] = 1.0 - hasTypedArrays = true - if(UINT_VIEW[1] === 0x3ff00000) { - //Use little endian - module.exports = function doubleBitsLE(n) { - DOUBLE_VIEW[0] = n - return [ UINT_VIEW[0], UINT_VIEW[1] ] - } - function toDoubleLE(lo, hi) { - UINT_VIEW[0] = lo - UINT_VIEW[1] = hi - return DOUBLE_VIEW[0] - } - module.exports.pack = toDoubleLE - function lowUintLE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[0] - } - module.exports.lo = lowUintLE - function highUintLE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[1] - } - module.exports.hi = highUintLE - } else if(UINT_VIEW[0] === 0x3ff00000) { - //Use big endian - module.exports = function doubleBitsBE(n) { - DOUBLE_VIEW[0] = n - return [ UINT_VIEW[1], UINT_VIEW[0] ] - } - function toDoubleBE(lo, hi) { - UINT_VIEW[1] = lo - UINT_VIEW[0] = hi - return DOUBLE_VIEW[0] - } - module.exports.pack = toDoubleBE - function lowUintBE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[1] - } - module.exports.lo = lowUintBE - function highUintBE(n) { - DOUBLE_VIEW[0] = n - return UINT_VIEW[0] - } - module.exports.hi = highUintBE - } else { - hasTypedArrays = false - } -} -if(!hasTypedArrays) { - var buffer = new Buffer(8) - module.exports = function doubleBits(n) { - buffer.writeDoubleLE(n, 0, true) - return [ buffer.readUInt32LE(0, true), buffer.readUInt32LE(4, true) ] - } - function toDouble(lo, hi) { - buffer.writeUInt32LE(lo, 0, true) - buffer.writeUInt32LE(hi, 4, true) - return buffer.readDoubleLE(0, true) - } - module.exports.pack = toDouble - function lowUint(n) { - buffer.writeDoubleLE(n, 0, true) - return buffer.readUInt32LE(0, true) - } - module.exports.lo = lowUint - function highUint(n) { - buffer.writeDoubleLE(n, 0, true) - return buffer.readUInt32LE(4, true) +module.exports = repeat; + +/** + * Repeat the given `string` the specified `number` + * of times. + * + * **Example:** + * + * ```js + * var repeat = require('repeat-string'); + * repeat('A', 5); + * //=> AAAAA + * ``` + * + * @param {String} `string` The string to repeat + * @param {Number} `number` The number of times to repeat the string + * @return {String} Repeated string + * @api public + */ + +function repeat(str, num) { + if (typeof str !== 'string') { + throw new TypeError('repeat-string expects a string.'); } - module.exports.hi = highUint -} -module.exports.sign = function(n) { - return module.exports.hi(n) >>> 31 -} + if (num === 1) return str; + if (num === 2) return str + str; -module.exports.exponent = function(n) { - var b = module.exports.hi(n) - return ((b<<1) >>> 21) - 1023 -} + var max = str.length * num; + if (cache !== str || typeof cache === 'undefined') { + cache = str; + res = ''; + } -module.exports.fraction = function(n) { - var lo = module.exports.lo(n) - var hi = module.exports.hi(n) - var b = hi & ((1<<20) - 1) - if(hi & 0x7ff00000) { - b += (1<<20) + while (max > res.length && num > 0) { + if (num & 1) { + res += str; + } + + num >>= 1; + if (!num) break; + str += str; } - return [lo, b] -} -module.exports.denormalized = function(n) { - var hi = module.exports.hi(n) - return !(hi & 0x7ff00000) + return res.substr(0, max); } -}).call(this,require("buffer").Buffer) -},{"buffer":48}],354:[function(require,module,exports){ -'use strict' -var bnsign = require('./lib/bn-sign') +/** + * Results cache + */ -module.exports = sign +var res = ''; +var cache; -function sign(x) { - return bnsign(x[0]) * bnsign(x[1]) +},{}],165:[function(require,module,exports){ +module.exports = { + 0: 'NONE', + 1: 'ONE', + 2: 'LINE_LOOP', + 3: 'LINE_STRIP', + 4: 'TRIANGLES', + 5: 'TRIANGLE_STRIP', + 6: 'TRIANGLE_FAN', + 256: 'DEPTH_BUFFER_BIT', + 512: 'NEVER', + 513: 'LESS', + 514: 'EQUAL', + 515: 'LEQUAL', + 516: 'GREATER', + 517: 'NOTEQUAL', + 518: 'GEQUAL', + 519: 'ALWAYS', + 768: 'SRC_COLOR', + 769: 'ONE_MINUS_SRC_COLOR', + 770: 'SRC_ALPHA', + 771: 'ONE_MINUS_SRC_ALPHA', + 772: 'DST_ALPHA', + 773: 'ONE_MINUS_DST_ALPHA', + 774: 'DST_COLOR', + 775: 'ONE_MINUS_DST_COLOR', + 776: 'SRC_ALPHA_SATURATE', + 1024: 'STENCIL_BUFFER_BIT', + 1028: 'FRONT', + 1029: 'BACK', + 1032: 'FRONT_AND_BACK', + 1280: 'INVALID_ENUM', + 1281: 'INVALID_VALUE', + 1282: 'INVALID_OPERATION', + 1285: 'OUT_OF_MEMORY', + 1286: 'INVALID_FRAMEBUFFER_OPERATION', + 2304: 'CW', + 2305: 'CCW', + 2849: 'LINE_WIDTH', + 2884: 'CULL_FACE', + 2885: 'CULL_FACE_MODE', + 2886: 'FRONT_FACE', + 2928: 'DEPTH_RANGE', + 2929: 'DEPTH_TEST', + 2930: 'DEPTH_WRITEMASK', + 2931: 'DEPTH_CLEAR_VALUE', + 2932: 'DEPTH_FUNC', + 2960: 'STENCIL_TEST', + 2961: 'STENCIL_CLEAR_VALUE', + 2962: 'STENCIL_FUNC', + 2963: 'STENCIL_VALUE_MASK', + 2964: 'STENCIL_FAIL', + 2965: 'STENCIL_PASS_DEPTH_FAIL', + 2966: 'STENCIL_PASS_DEPTH_PASS', + 2967: 'STENCIL_REF', + 2968: 'STENCIL_WRITEMASK', + 2978: 'VIEWPORT', + 3024: 'DITHER', + 3042: 'BLEND', + 3088: 'SCISSOR_BOX', + 3089: 'SCISSOR_TEST', + 3106: 'COLOR_CLEAR_VALUE', + 3107: 'COLOR_WRITEMASK', + 3317: 'UNPACK_ALIGNMENT', + 3333: 'PACK_ALIGNMENT', + 3379: 'MAX_TEXTURE_SIZE', + 3386: 'MAX_VIEWPORT_DIMS', + 3408: 'SUBPIXEL_BITS', + 3410: 'RED_BITS', + 3411: 'GREEN_BITS', + 3412: 'BLUE_BITS', + 3413: 'ALPHA_BITS', + 3414: 'DEPTH_BITS', + 3415: 'STENCIL_BITS', + 3553: 'TEXTURE_2D', + 4352: 'DONT_CARE', + 4353: 'FASTEST', + 4354: 'NICEST', + 5120: 'BYTE', + 5121: 'UNSIGNED_BYTE', + 5122: 'SHORT', + 5123: 'UNSIGNED_SHORT', + 5124: 'INT', + 5125: 'UNSIGNED_INT', + 5126: 'FLOAT', + 5386: 'INVERT', + 5890: 'TEXTURE', + 6401: 'STENCIL_INDEX', + 6402: 'DEPTH_COMPONENT', + 6406: 'ALPHA', + 6407: 'RGB', + 6408: 'RGBA', + 6409: 'LUMINANCE', + 6410: 'LUMINANCE_ALPHA', + 7680: 'KEEP', + 7681: 'REPLACE', + 7682: 'INCR', + 7683: 'DECR', + 7936: 'VENDOR', + 7937: 'RENDERER', + 7938: 'VERSION', + 9728: 'NEAREST', + 9729: 'LINEAR', + 9984: 'NEAREST_MIPMAP_NEAREST', + 9985: 'LINEAR_MIPMAP_NEAREST', + 9986: 'NEAREST_MIPMAP_LINEAR', + 9987: 'LINEAR_MIPMAP_LINEAR', + 10240: 'TEXTURE_MAG_FILTER', + 10241: 'TEXTURE_MIN_FILTER', + 10242: 'TEXTURE_WRAP_S', + 10243: 'TEXTURE_WRAP_T', + 10497: 'REPEAT', + 10752: 'POLYGON_OFFSET_UNITS', + 16384: 'COLOR_BUFFER_BIT', + 32769: 'CONSTANT_COLOR', + 32770: 'ONE_MINUS_CONSTANT_COLOR', + 32771: 'CONSTANT_ALPHA', + 32772: 'ONE_MINUS_CONSTANT_ALPHA', + 32773: 'BLEND_COLOR', + 32774: 'FUNC_ADD', + 32777: 'BLEND_EQUATION_RGB', + 32778: 'FUNC_SUBTRACT', + 32779: 'FUNC_REVERSE_SUBTRACT', + 32819: 'UNSIGNED_SHORT_4_4_4_4', + 32820: 'UNSIGNED_SHORT_5_5_5_1', + 32823: 'POLYGON_OFFSET_FILL', + 32824: 'POLYGON_OFFSET_FACTOR', + 32854: 'RGBA4', + 32855: 'RGB5_A1', + 32873: 'TEXTURE_BINDING_2D', + 32926: 'SAMPLE_ALPHA_TO_COVERAGE', + 32928: 'SAMPLE_COVERAGE', + 32936: 'SAMPLE_BUFFERS', + 32937: 'SAMPLES', + 32938: 'SAMPLE_COVERAGE_VALUE', + 32939: 'SAMPLE_COVERAGE_INVERT', + 32968: 'BLEND_DST_RGB', + 32969: 'BLEND_SRC_RGB', + 32970: 'BLEND_DST_ALPHA', + 32971: 'BLEND_SRC_ALPHA', + 33071: 'CLAMP_TO_EDGE', + 33170: 'GENERATE_MIPMAP_HINT', + 33189: 'DEPTH_COMPONENT16', + 33306: 'DEPTH_STENCIL_ATTACHMENT', + 33635: 'UNSIGNED_SHORT_5_6_5', + 33648: 'MIRRORED_REPEAT', + 33901: 'ALIASED_POINT_SIZE_RANGE', + 33902: 'ALIASED_LINE_WIDTH_RANGE', + 33984: 'TEXTURE0', + 33985: 'TEXTURE1', + 33986: 'TEXTURE2', + 33987: 'TEXTURE3', + 33988: 'TEXTURE4', + 33989: 'TEXTURE5', + 33990: 'TEXTURE6', + 33991: 'TEXTURE7', + 33992: 'TEXTURE8', + 33993: 'TEXTURE9', + 33994: 'TEXTURE10', + 33995: 'TEXTURE11', + 33996: 'TEXTURE12', + 33997: 'TEXTURE13', + 33998: 'TEXTURE14', + 33999: 'TEXTURE15', + 34000: 'TEXTURE16', + 34001: 'TEXTURE17', + 34002: 'TEXTURE18', + 34003: 'TEXTURE19', + 34004: 'TEXTURE20', + 34005: 'TEXTURE21', + 34006: 'TEXTURE22', + 34007: 'TEXTURE23', + 34008: 'TEXTURE24', + 34009: 'TEXTURE25', + 34010: 'TEXTURE26', + 34011: 'TEXTURE27', + 34012: 'TEXTURE28', + 34013: 'TEXTURE29', + 34014: 'TEXTURE30', + 34015: 'TEXTURE31', + 34016: 'ACTIVE_TEXTURE', + 34024: 'MAX_RENDERBUFFER_SIZE', + 34041: 'DEPTH_STENCIL', + 34055: 'INCR_WRAP', + 34056: 'DECR_WRAP', + 34067: 'TEXTURE_CUBE_MAP', + 34068: 'TEXTURE_BINDING_CUBE_MAP', + 34069: 'TEXTURE_CUBE_MAP_POSITIVE_X', + 34070: 'TEXTURE_CUBE_MAP_NEGATIVE_X', + 34071: 'TEXTURE_CUBE_MAP_POSITIVE_Y', + 34072: 'TEXTURE_CUBE_MAP_NEGATIVE_Y', + 34073: 'TEXTURE_CUBE_MAP_POSITIVE_Z', + 34074: 'TEXTURE_CUBE_MAP_NEGATIVE_Z', + 34076: 'MAX_CUBE_MAP_TEXTURE_SIZE', + 34338: 'VERTEX_ATTRIB_ARRAY_ENABLED', + 34339: 'VERTEX_ATTRIB_ARRAY_SIZE', + 34340: 'VERTEX_ATTRIB_ARRAY_STRIDE', + 34341: 'VERTEX_ATTRIB_ARRAY_TYPE', + 34342: 'CURRENT_VERTEX_ATTRIB', + 34373: 'VERTEX_ATTRIB_ARRAY_POINTER', + 34466: 'NUM_COMPRESSED_TEXTURE_FORMATS', + 34467: 'COMPRESSED_TEXTURE_FORMATS', + 34660: 'BUFFER_SIZE', + 34661: 'BUFFER_USAGE', + 34816: 'STENCIL_BACK_FUNC', + 34817: 'STENCIL_BACK_FAIL', + 34818: 'STENCIL_BACK_PASS_DEPTH_FAIL', + 34819: 'STENCIL_BACK_PASS_DEPTH_PASS', + 34877: 'BLEND_EQUATION_ALPHA', + 34921: 'MAX_VERTEX_ATTRIBS', + 34922: 'VERTEX_ATTRIB_ARRAY_NORMALIZED', + 34930: 'MAX_TEXTURE_IMAGE_UNITS', + 34962: 'ARRAY_BUFFER', + 34963: 'ELEMENT_ARRAY_BUFFER', + 34964: 'ARRAY_BUFFER_BINDING', + 34965: 'ELEMENT_ARRAY_BUFFER_BINDING', + 34975: 'VERTEX_ATTRIB_ARRAY_BUFFER_BINDING', + 35040: 'STREAM_DRAW', + 35044: 'STATIC_DRAW', + 35048: 'DYNAMIC_DRAW', + 35632: 'FRAGMENT_SHADER', + 35633: 'VERTEX_SHADER', + 35660: 'MAX_VERTEX_TEXTURE_IMAGE_UNITS', + 35661: 'MAX_COMBINED_TEXTURE_IMAGE_UNITS', + 35663: 'SHADER_TYPE', + 35664: 'FLOAT_VEC2', + 35665: 'FLOAT_VEC3', + 35666: 'FLOAT_VEC4', + 35667: 'INT_VEC2', + 35668: 'INT_VEC3', + 35669: 'INT_VEC4', + 35670: 'BOOL', + 35671: 'BOOL_VEC2', + 35672: 'BOOL_VEC3', + 35673: 'BOOL_VEC4', + 35674: 'FLOAT_MAT2', + 35675: 'FLOAT_MAT3', + 35676: 'FLOAT_MAT4', + 35678: 'SAMPLER_2D', + 35680: 'SAMPLER_CUBE', + 35712: 'DELETE_STATUS', + 35713: 'COMPILE_STATUS', + 35714: 'LINK_STATUS', + 35715: 'VALIDATE_STATUS', + 35716: 'INFO_LOG_LENGTH', + 35717: 'ATTACHED_SHADERS', + 35718: 'ACTIVE_UNIFORMS', + 35719: 'ACTIVE_UNIFORM_MAX_LENGTH', + 35720: 'SHADER_SOURCE_LENGTH', + 35721: 'ACTIVE_ATTRIBUTES', + 35722: 'ACTIVE_ATTRIBUTE_MAX_LENGTH', + 35724: 'SHADING_LANGUAGE_VERSION', + 35725: 'CURRENT_PROGRAM', + 36003: 'STENCIL_BACK_REF', + 36004: 'STENCIL_BACK_VALUE_MASK', + 36005: 'STENCIL_BACK_WRITEMASK', + 36006: 'FRAMEBUFFER_BINDING', + 36007: 'RENDERBUFFER_BINDING', + 36048: 'FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE', + 36049: 'FRAMEBUFFER_ATTACHMENT_OBJECT_NAME', + 36050: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL', + 36051: 'FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE', + 36053: 'FRAMEBUFFER_COMPLETE', + 36054: 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT', + 36055: 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT', + 36057: 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS', + 36061: 'FRAMEBUFFER_UNSUPPORTED', + 36064: 'COLOR_ATTACHMENT0', + 36096: 'DEPTH_ATTACHMENT', + 36128: 'STENCIL_ATTACHMENT', + 36160: 'FRAMEBUFFER', + 36161: 'RENDERBUFFER', + 36162: 'RENDERBUFFER_WIDTH', + 36163: 'RENDERBUFFER_HEIGHT', + 36164: 'RENDERBUFFER_INTERNAL_FORMAT', + 36168: 'STENCIL_INDEX8', + 36176: 'RENDERBUFFER_RED_SIZE', + 36177: 'RENDERBUFFER_GREEN_SIZE', + 36178: 'RENDERBUFFER_BLUE_SIZE', + 36179: 'RENDERBUFFER_ALPHA_SIZE', + 36180: 'RENDERBUFFER_DEPTH_SIZE', + 36181: 'RENDERBUFFER_STENCIL_SIZE', + 36194: 'RGB565', + 36336: 'LOW_FLOAT', + 36337: 'MEDIUM_FLOAT', + 36338: 'HIGH_FLOAT', + 36339: 'LOW_INT', + 36340: 'MEDIUM_INT', + 36341: 'HIGH_INT', + 36346: 'SHADER_COMPILER', + 36347: 'MAX_VERTEX_UNIFORM_VECTORS', + 36348: 'MAX_VARYING_VECTORS', + 36349: 'MAX_FRAGMENT_UNIFORM_VECTORS', + 37440: 'UNPACK_FLIP_Y_WEBGL', + 37441: 'UNPACK_PREMULTIPLY_ALPHA_WEBGL', + 37442: 'CONTEXT_LOST_WEBGL', + 37443: 'UNPACK_COLORSPACE_CONVERSION_WEBGL', + 37444: 'BROWSER_DEFAULT_WEBGL' } -},{"./lib/bn-sign":343}],355:[function(require,module,exports){ -'use strict' - -var rationalize = require('./lib/rationalize') - -module.exports = sub +},{}],166:[function(require,module,exports){ +var gl10 = require('./1.0/numbers') -function sub(a, b) { - return rationalize(a[0].mul(b[1]).sub(a[1].mul(b[0])), a[1].mul(b[1])) +module.exports = function lookupConstant (number) { + return gl10[number] } -},{"./lib/rationalize":348}],356:[function(require,module,exports){ -'use strict' +},{"./1.0/numbers":165}],167:[function(require,module,exports){ +var tokenize = require('glsl-tokenizer') +var atob = require('atob-lite') -var bn2num = require('./lib/bn-to-num') -var ctz = require('./lib/ctz') +module.exports = getName -module.exports = roundRat +function getName(src) { + var tokens = Array.isArray(src) + ? src + : tokenize(src) -//Round a rational to the closest float -function roundRat(f) { - var a = f[0] - var b = f[1] - if(a.cmpn(0) === 0) { - return 0 - } - var h = a.divmod(b) - var iv = h.div - var x = bn2num(iv) - var ir = h.mod - if(ir.cmpn(0) === 0) { - return x - } - if(x) { - var s = ctz(x) + 4 - var y = bn2num(ir.shln(s).divRound(b)) + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i] + if (token.type !== 'preprocessor') continue + var match = token.data.match(/\#define\s+SHADER_NAME(_B64)?\s+(.+)$/) + if (!match) continue + if (!match[2]) continue - // flip the sign of y if x is negative - if (x<0) { - y = -y; - } + var b64 = match[1] + var name = match[2] - return x + y * Math.pow(2, -s) - } else { - var ybits = b.bitLength() - ir.bitLength() + 53 - var y = bn2num(ir.shln(ybits).divRound(b)) - if(ybits < 1023) { - return y * Math.pow(2, -ybits) - } - y *= Math.pow(2, -1023) - return y * Math.pow(2, 1023-ybits) + return (b64 ? atob(name) : name).trim() } } -},{"./lib/bn-to-num":344,"./lib/ctz":345}],357:[function(require,module,exports){ -'use strict' +},{"atob-lite":168,"glsl-tokenizer":173}],168:[function(require,module,exports){ +module.exports = function _atob(str) { + return atob(str) +} -module.exports = boxIntersectWrapper +},{}],169:[function(require,module,exports){ +module.exports = tokenize -var pool = require('typedarray-pool') -var sweep = require('./lib/sweep') -var boxIntersectIter = require('./lib/intersect') +var literals = require('./lib/literals') + , operators = require('./lib/operators') + , builtins = require('./lib/builtins') -function boxEmpty(d, box) { - for(var j=0; j>>1 - if(d <= 0) { - return + function token(data) { + if (data.length) { + tokens.push({ + type: map[mode] + , data: data + , position: start + , line: line + , column: col + }) + } } - var retval - - //Convert red boxes - var redList = pool.mallocDouble(2*d*n) - var redIds = pool.mallocInt32(n) - n = convertBoxes(red, d, redList, redIds) + function write(chunk) { + i = 0 + input += chunk + len = input.length - if(n > 0) { - if(d === 1 && full) { - //Special case: 1d complete - sweep.init(n) - retval = sweep.sweepComplete( - d, visit, - 0, n, redList, redIds, - 0, n, redList, redIds) - } else { + var last - //Convert blue boxes - var blueList = pool.mallocDouble(2*d*m) - var blueIds = pool.mallocInt32(m) - m = convertBoxes(blue, d, blueList, blueIds) + while(c = input[i], i < len) { + last = i - if(m > 0) { - sweep.init(n+m) + switch(mode) { + case BLOCK_COMMENT: i = block_comment(); break + case LINE_COMMENT: i = line_comment(); break + case PREPROCESSOR: i = preprocessor(); break + case OPERATOR: i = operator(); break + case INTEGER: i = integer(); break + case HEX: i = hex(); break + case FLOAT: i = decimal(); break + case TOKEN: i = readtoken(); break + case WHITESPACE: i = whitespace(); break + case NORMAL: i = normal(); break + } - if(d === 1) { - //Special case: 1d bipartite - retval = sweep.sweepBipartite( - d, visit, - 0, n, redList, redIds, - 0, m, blueList, blueIds) - } else { - //General case: d>1 - retval = boxIntersectIter( - d, visit, full, - n, redList, redIds, - m, blueList, blueIds) + if(last !== i) { + switch(input[last]) { + case '\n': col = 0; ++line; break + default: ++col; break } - - pool.free(blueList) - pool.free(blueIds) } } - pool.free(redList) - pool.free(redIds) - } - - return retval -} - - -var RESULT - -function appendItem(i,j) { - RESULT.push([i,j]) -} - -function intersectFullArray(x) { - RESULT = [] - boxIntersect(x, x, appendItem, true) - return RESULT -} - -function intersectBipartiteArray(x, y) { - RESULT = [] - boxIntersect(x, y, appendItem, false) - return RESULT -} - -//User-friendly wrapper, handle full input and no-visitor cases -function boxIntersectWrapper(arg0, arg1, arg2) { - var result - switch(arguments.length) { - case 1: - return intersectFullArray(arg0) - case 2: - if(typeof arg1 === 'function') { - return boxIntersect(arg0, arg0, arg1, true) - } else { - return intersectBipartiteArray(arg0, arg1) - } - case 3: - return boxIntersect(arg0, arg1, arg2, false) - default: - throw new Error('box-intersect: Invalid arguments') - } -} -},{"./lib/intersect":359,"./lib/sweep":363,"typedarray-pool":366}],358:[function(require,module,exports){ -'use strict' - -var DIMENSION = 'd' -var AXIS = 'ax' -var VISIT = 'vv' -var FLIP = 'fp' - -var ELEM_SIZE = 'es' - -var RED_START = 'rs' -var RED_END = 're' -var RED_BOXES = 'rb' -var RED_INDEX = 'ri' -var RED_PTR = 'rp' - -var BLUE_START = 'bs' -var BLUE_END = 'be' -var BLUE_BOXES = 'bb' -var BLUE_INDEX = 'bi' -var BLUE_PTR = 'bp' - -var RETVAL = 'rv' - -var INNER_LABEL = 'Q' - -var ARGS = [ - DIMENSION, - AXIS, - VISIT, - RED_START, - RED_END, - RED_BOXES, - RED_INDEX, - BLUE_START, - BLUE_END, - BLUE_BOXES, - BLUE_INDEX -] - -function generateBruteForce(redMajor, flip, full) { - var funcName = 'bruteForce' + - (redMajor ? 'Red' : 'Blue') + - (flip ? 'Flip' : '') + - (full ? 'Full' : '') - - var code = ['function ', funcName, '(', ARGS.join(), '){', - 'var ', ELEM_SIZE, '=2*', DIMENSION, ';'] - - var redLoop = - 'for(var i=' + RED_START + ',' + RED_PTR + '=' + ELEM_SIZE + '*' + RED_START + ';' + - 'i<' + RED_END +';' + - '++i,' + RED_PTR + '+=' + ELEM_SIZE + '){' + - 'var x0=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '],' + - 'x1=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '+' + DIMENSION + '],' + - 'xi=' + RED_INDEX + '[i];' - - var blueLoop = - 'for(var j=' + BLUE_START + ',' + BLUE_PTR + '=' + ELEM_SIZE + '*' + BLUE_START + ';' + - 'j<' + BLUE_END + ';' + - '++j,' + BLUE_PTR + '+=' + ELEM_SIZE + '){' + - 'var y0=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '],' + - (full ? 'y1=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '+' + DIMENSION + '],' : '') + - 'yi=' + BLUE_INDEX + '[j];' - - if(redMajor) { - code.push(redLoop, INNER_LABEL, ':', blueLoop) - } else { - code.push(blueLoop, INNER_LABEL, ':', redLoop) - } - - if(full) { - code.push('if(y1' + - BLUE_END + '-' + BLUE_START + '){') + isnum = /\d/.test(c) + isoperator = /[^\w_]/.test(c) - if(full) { - invoke(true, false) - code.push('}else{') - invoke(false, false) - } else { - code.push('if(' + FLIP + '){') - invoke(true, true) - code.push('}else{') - invoke(true, false) - code.push('}}else{if(' + FLIP + '){') - invoke(false, true) - code.push('}else{') - invoke(false, false) - code.push('}') + start = total + i + mode = isnum ? INTEGER : isoperator ? OPERATOR : TOKEN + return i } - code.push('}}return ' + funcName) - - var codeStr = prefix.join('') + code.join('') - var proc = new Function(codeStr) - return proc() -} - -exports.partial = bruteForcePlanner(false) -exports.full = bruteForcePlanner(true) -},{}],359:[function(require,module,exports){ -'use strict' + function whitespace() { + if(/[^\s]/g.test(c)) { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } -module.exports = boxIntersectIter + function preprocessor() { + if(c === '\n' && last !== '\\') { + token(content.join('')) + mode = NORMAL + return i + } + content.push(c) + last = c + return i + 1 + } -var pool = require('typedarray-pool') -var bits = require('bit-twiddle') -var bruteForce = require('./brute') -var bruteForcePartial = bruteForce.partial -var bruteForceFull = bruteForce.full -var sweep = require('./sweep') -var findMedian = require('./median') -var genPartition = require('./partition') + function line_comment() { + return preprocessor() + } -//Twiddle parameters -var BRUTE_FORCE_CUTOFF = 128 //Cut off for brute force search -var SCAN_CUTOFF = (1<<22) //Cut off for two way scan -var SCAN_COMPLETE_CUTOFF = (1<<22) + function block_comment() { + if(c === '/' && last === '*') { + content.push(c) + token(content.join('')) + mode = NORMAL + return i + 1 + } -//Partition functions -var partitionInteriorContainsInterval = genPartition( - '!(lo>=p0)&&!(p1>=hi)', - ['p0', 'p1']) + content.push(c) + last = c + return i + 1 + } -var partitionStartEqual = genPartition( - 'lo===p0', - ['p0']) + function operator() { + if(last === '.' && /\d/.test(c)) { + mode = FLOAT + return i + } -var partitionStartLessThan = genPartition( - 'lo 0) continue + res = buf.slice(0, 1).join('') + } -//Special case: Intersect single point with list of intervals -function onePointPartial( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueOffset, blue, blueId) { + token(res) - var elemSize = 2 * d - var bluePtr = blueOffset * elemSize - var blueX = blue[bluePtr + axis] + start += res.length + content = content.slice(res.length) + return content.length + } while(1) + } -red_loop: - for(var i=redStart, redPtr=redStart*elemSize; i -1) { + mode = KEYWORD + } else if(builtins.indexOf(contentstr) > -1) { + mode = BUILTIN + } else { + mode = IDENT } + token(content.join('')) + mode = NORMAL + return i } - var retval = visit(redId, blueId) - if(retval !== void 0) { - return retval - } + content.push(c) + last = c + return i + 1 } } -//The main box intersection routine -function boxIntersectIter( - d, visit, initFull, - xSize, xBoxes, xIndex, - ySize, yBoxes, yIndex) { +},{"./lib/builtins":170,"./lib/literals":171,"./lib/operators":172}],170:[function(require,module,exports){ +module.exports = [ + 'gl_Position' + , 'gl_PointSize' + , 'gl_ClipVertex' + , 'gl_FragCoord' + , 'gl_FrontFacing' + , 'gl_FragColor' + , 'gl_FragData' + , 'gl_FragDepth' + , 'gl_Color' + , 'gl_SecondaryColor' + , 'gl_Normal' + , 'gl_Vertex' + , 'gl_MultiTexCoord0' + , 'gl_MultiTexCoord1' + , 'gl_MultiTexCoord2' + , 'gl_MultiTexCoord3' + , 'gl_MultiTexCoord4' + , 'gl_MultiTexCoord5' + , 'gl_MultiTexCoord6' + , 'gl_MultiTexCoord7' + , 'gl_FogCoord' + , 'gl_MaxLights' + , 'gl_MaxClipPlanes' + , 'gl_MaxTextureUnits' + , 'gl_MaxTextureCoords' + , 'gl_MaxVertexAttribs' + , 'gl_MaxVertexUniformComponents' + , 'gl_MaxVaryingFloats' + , 'gl_MaxVertexTextureImageUnits' + , 'gl_MaxCombinedTextureImageUnits' + , 'gl_MaxTextureImageUnits' + , 'gl_MaxFragmentUniformComponents' + , 'gl_MaxDrawBuffers' + , 'gl_ModelViewMatrix' + , 'gl_ProjectionMatrix' + , 'gl_ModelViewProjectionMatrix' + , 'gl_TextureMatrix' + , 'gl_NormalMatrix' + , 'gl_ModelViewMatrixInverse' + , 'gl_ProjectionMatrixInverse' + , 'gl_ModelViewProjectionMatrixInverse' + , 'gl_TextureMatrixInverse' + , 'gl_ModelViewMatrixTranspose' + , 'gl_ProjectionMatrixTranspose' + , 'gl_ModelViewProjectionMatrixTranspose' + , 'gl_TextureMatrixTranspose' + , 'gl_ModelViewMatrixInverseTranspose' + , 'gl_ProjectionMatrixInverseTranspose' + , 'gl_ModelViewProjectionMatrixInverseTranspose' + , 'gl_TextureMatrixInverseTranspose' + , 'gl_NormalScale' + , 'gl_DepthRangeParameters' + , 'gl_DepthRange' + , 'gl_ClipPlane' + , 'gl_PointParameters' + , 'gl_Point' + , 'gl_MaterialParameters' + , 'gl_FrontMaterial' + , 'gl_BackMaterial' + , 'gl_LightSourceParameters' + , 'gl_LightSource' + , 'gl_LightModelParameters' + , 'gl_LightModel' + , 'gl_LightModelProducts' + , 'gl_FrontLightModelProduct' + , 'gl_BackLightModelProduct' + , 'gl_LightProducts' + , 'gl_FrontLightProduct' + , 'gl_BackLightProduct' + , 'gl_FogParameters' + , 'gl_Fog' + , 'gl_TextureEnvColor' + , 'gl_EyePlaneS' + , 'gl_EyePlaneT' + , 'gl_EyePlaneR' + , 'gl_EyePlaneQ' + , 'gl_ObjectPlaneS' + , 'gl_ObjectPlaneT' + , 'gl_ObjectPlaneR' + , 'gl_ObjectPlaneQ' + , 'gl_FrontColor' + , 'gl_BackColor' + , 'gl_FrontSecondaryColor' + , 'gl_BackSecondaryColor' + , 'gl_TexCoord' + , 'gl_FogFragCoord' + , 'gl_Color' + , 'gl_SecondaryColor' + , 'gl_TexCoord' + , 'gl_FogFragCoord' + , 'gl_PointCoord' + , 'radians' + , 'degrees' + , 'sin' + , 'cos' + , 'tan' + , 'asin' + , 'acos' + , 'atan' + , 'pow' + , 'exp' + , 'log' + , 'exp2' + , 'log2' + , 'sqrt' + , 'inversesqrt' + , 'abs' + , 'sign' + , 'floor' + , 'ceil' + , 'fract' + , 'mod' + , 'min' + , 'max' + , 'clamp' + , 'mix' + , 'step' + , 'smoothstep' + , 'length' + , 'distance' + , 'dot' + , 'cross' + , 'normalize' + , 'faceforward' + , 'reflect' + , 'refract' + , 'matrixCompMult' + , 'lessThan' + , 'lessThanEqual' + , 'greaterThan' + , 'greaterThanEqual' + , 'equal' + , 'notEqual' + , 'any' + , 'all' + , 'not' + , 'texture2D' + , 'texture2DProj' + , 'texture2DLod' + , 'texture2DProjLod' + , 'textureCube' + , 'textureCubeLod' + , 'dFdx' + , 'dFdy' +] - //Reserve memory for stack - iterInit(d, xSize + ySize) +},{}],171:[function(require,module,exports){ +module.exports = [ + // current + 'precision' + , 'highp' + , 'mediump' + , 'lowp' + , 'attribute' + , 'const' + , 'uniform' + , 'varying' + , 'break' + , 'continue' + , 'do' + , 'for' + , 'while' + , 'if' + , 'else' + , 'in' + , 'out' + , 'inout' + , 'float' + , 'int' + , 'void' + , 'bool' + , 'true' + , 'false' + , 'discard' + , 'return' + , 'mat2' + , 'mat3' + , 'mat4' + , 'vec2' + , 'vec3' + , 'vec4' + , 'ivec2' + , 'ivec3' + , 'ivec4' + , 'bvec2' + , 'bvec3' + , 'bvec4' + , 'sampler1D' + , 'sampler2D' + , 'sampler3D' + , 'samplerCube' + , 'sampler1DShadow' + , 'sampler2DShadow' + , 'struct' - var top = 0 - var elemSize = 2 * d - var retval + // future + , 'asm' + , 'class' + , 'union' + , 'enum' + , 'typedef' + , 'template' + , 'this' + , 'packed' + , 'goto' + , 'switch' + , 'default' + , 'inline' + , 'noinline' + , 'volatile' + , 'public' + , 'static' + , 'extern' + , 'external' + , 'interface' + , 'long' + , 'short' + , 'double' + , 'half' + , 'fixed' + , 'unsigned' + , 'input' + , 'output' + , 'hvec2' + , 'hvec3' + , 'hvec4' + , 'dvec2' + , 'dvec3' + , 'dvec4' + , 'fvec2' + , 'fvec3' + , 'fvec4' + , 'sampler2DRect' + , 'sampler3DRect' + , 'sampler2DRectShadow' + , 'sizeof' + , 'cast' + , 'namespace' + , 'using' +] - iterPush(top++, - 0, - 0, xSize, - 0, ySize, - initFull ? 16 : 0, - -Infinity, Infinity) - if(!initFull) { - iterPush(top++, - 0, - 0, ySize, - 0, xSize, - 1, - -Infinity, Infinity) - } +},{}],172:[function(require,module,exports){ +module.exports = [ + '<<=' + , '>>=' + , '++' + , '--' + , '<<' + , '>>' + , '<=' + , '>=' + , '==' + , '!=' + , '&&' + , '||' + , '+=' + , '-=' + , '*=' + , '/=' + , '%=' + , '&=' + , '^^' + , '^=' + , '|=' + , '(' + , ')' + , '[' + , ']' + , '.' + , '!' + , '~' + , '*' + , '/' + , '%' + , '+' + , '-' + , '<' + , '>' + , '&' + , '^' + , '|' + , '?' + , ':' + , '=' + , ',' + , ';' + , '{' + , '}' +] - while(top > 0) { - top -= 1 +},{}],173:[function(require,module,exports){ +var tokenize = require('./index') - var iptr = top * IFRAME_SIZE - var axis = BOX_ISTACK[iptr] - var redStart = BOX_ISTACK[iptr+1] - var redEnd = BOX_ISTACK[iptr+2] - var blueStart = BOX_ISTACK[iptr+3] - var blueEnd = BOX_ISTACK[iptr+4] - var state = BOX_ISTACK[iptr+5] +module.exports = tokenizeString - var dptr = top * DFRAME_SIZE - var lo = BOX_DSTACK[dptr] - var hi = BOX_DSTACK[dptr+1] +function tokenizeString(str) { + var generator = tokenize() + var tokens = [] - //Unpack state info - var flip = (state & 1) - var full = !!(state & 16) + tokens = tokens.concat(generator(str)) + tokens = tokens.concat(generator(null)) - //Unpack indices - var red = xBoxes - var redIndex = xIndex - var blue = yBoxes - var blueIndex = yIndex - if(flip) { - red = yBoxes - redIndex = yIndex - blue = xBoxes - blueIndex = xIndex - } + return tokens +} - if(state & 2) { - redEnd = partitionStartLessThan( - d, axis, - redStart, redEnd, red, redIndex, - hi) - if(redStart >= redEnd) { - continue - } - } - if(state & 4) { - redStart = partitionEndLessThanEqual( - d, axis, - redStart, redEnd, red, redIndex, - lo) - if(redStart >= redEnd) { - continue - } +},{"./index":169}],174:[function(require,module,exports){ +(function(window) { + var re = { + not_string: /[^s]/, + number: /[diefg]/, + json: /[j]/, + not_json: /[^j]/, + text: /^[^\x25]+/, + modulo: /^\x25{2}/, + placeholder: /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosuxX])/, + key: /^([a-z_][a-z_\d]*)/i, + key_access: /^\.([a-z_][a-z_\d]*)/i, + index_access: /^\[(\d+)\]/, + sign: /^[\+\-]/ } - - var redCount = redEnd - redStart - var blueCount = blueEnd - blueStart - if(full) { - if(d * redCount * (redCount + blueCount) < SCAN_COMPLETE_CUTOFF) { - retval = sweep.scanComplete( - d, axis, visit, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - continue - } - } else { - if(d * Math.min(redCount, blueCount) < BRUTE_FORCE_CUTOFF) { - //If input small, then use brute force - retval = bruteForcePartial( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - continue - } else if(d * redCount * blueCount < SCAN_CUTOFF) { - //If input medium sized, then use sweep and prune - retval = sweep.scanBipartite( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval + function sprintf() { + var key = arguments[0], cache = sprintf.cache + if (!(cache[key] && cache.hasOwnProperty(key))) { + cache[key] = sprintf.parse(key) } - continue - } + return sprintf.format.call(null, cache[key], arguments) } - - //First, find all red intervals whose interior contains (lo,hi) - var red0 = partitionInteriorContainsInterval( - d, axis, - redStart, redEnd, red, redIndex, - lo, hi) - //Lower dimensional case - if(redStart < red0) { + sprintf.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = "", arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = true, sign = "" + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]) + if (node_type === "string") { + output[output.length] = parse_tree[i] + } + else if (node_type === "array") { + match = parse_tree[i] // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor] + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf("[sprintf] property '%s' does not exist", match[2][k])) + } + arg = arg[match[2][k]] + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]] + } + else { // positional argument (implicit) + arg = argv[cursor++] + } - if(d * (red0 - redStart) < BRUTE_FORCE_CUTOFF) { - //Special case for small inputs: use brute force - retval = bruteForceFull( - d, axis+1, visit, - redStart, red0, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - if(retval !== void 0) { - return retval - } - } else if(axis === d-2) { - if(flip) { - retval = sweep.sweepBipartite( - d, visit, - blueStart, blueEnd, blue, blueIndex, - redStart, red0, red, redIndex) - } else { - retval = sweep.sweepBipartite( - d, visit, - redStart, red0, red, redIndex, - blueStart, blueEnd, blue, blueIndex) - } - if(retval !== void 0) { - return retval - } - } else { - iterPush(top++, - axis+1, - redStart, red0, - blueStart, blueEnd, - flip, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blueStart, blueEnd, - redStart, red0, - flip^1, - -Infinity, Infinity) - } - } + if (get_type(arg) == "function") { + arg = arg() + } - //Divide and conquer phase - if(red0 < redEnd) { + if (re.not_string.test(match[8]) && re.not_json.test(match[8]) && (get_type(arg) != "number" && isNaN(arg))) { + throw new TypeError(sprintf("[sprintf] expecting number but found %s", get_type(arg))) + } - //Cut blue into 3 parts: - // - // Points < mid point - // Points = mid point - // Points > mid point - // - var blue0 = findMedian( - d, axis, - blueStart, blueEnd, blue, blueIndex) - var mid = blue[elemSize * blue0 + axis] - var blue1 = partitionStartEqual( - d, axis, - blue0, blueEnd, blue, blueIndex, - mid) + if (re.number.test(match[8])) { + is_positive = arg >= 0 + } - //Right case - if(blue1 < blueEnd) { - iterPush(top++, - axis, - red0, redEnd, - blue1, blueEnd, - (flip|4) + (full ? 16 : 0), - mid, hi) - } + switch (match[8]) { + case "b": + arg = arg.toString(2) + break + case "c": + arg = String.fromCharCode(arg) + break + case "d": + case "i": + arg = parseInt(arg, 10) + break + case "j": + arg = JSON.stringify(arg, null, match[6] ? parseInt(match[6]) : 0) + break + case "e": + arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential() + break + case "f": + arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg) + break + case "g": + arg = match[7] ? parseFloat(arg).toPrecision(match[7]) : parseFloat(arg) + break + case "o": + arg = arg.toString(8) + break + case "s": + arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg) + break + case "u": + arg = arg >>> 0 + break + case "x": + arg = arg.toString(16) + break + case "X": + arg = arg.toString(16).toUpperCase() + break + } + if (re.json.test(match[8])) { + output[output.length] = arg + } + else { + if (re.number.test(match[8]) && (!is_positive || match[3])) { + sign = is_positive ? "+" : "-" + arg = arg.toString().replace(re.sign, "") + } + else { + sign = "" + } + pad_character = match[4] ? match[4] === "0" ? "0" : match[4].charAt(1) : " " + pad_length = match[6] - (sign + arg).length + pad = match[6] ? (pad_length > 0 ? str_repeat(pad_character, pad_length) : "") : "" + output[output.length] = match[5] ? sign + arg + pad : (pad_character === "0" ? sign + pad + arg : pad + sign + arg) + } + } + } + return output.join("") + } - //Left case - if(blueStart < blue0) { - iterPush(top++, - axis, - red0, redEnd, - blueStart, blue0, - (flip|2) + (full ? 16 : 0), - lo, mid) - } + sprintf.cache = {} - //Center case (the hard part) - if(blue0 + 1 === blue1) { - //Optimization: Range with exactly 1 point, use a brute force scan - if(full) { - retval = onePointFull( - d, axis, visit, - red0, redEnd, red, redIndex, - blue0, blue, blueIndex[blue0]) - } else { - retval = onePointPartial( - d, axis, visit, flip, - red0, redEnd, red, redIndex, - blue0, blue, blueIndex[blue0]) - } - if(retval !== void 0) { - return retval - } - } else if(blue0 < blue1) { - var red1 - if(full) { - //If full intersection, need to handle special case - red1 = partitionContainsPoint( - d, axis, - red0, redEnd, red, redIndex, - mid) - if(red0 < red1) { - var redX = partitionStartEqual( - d, axis, - red0, red1, red, redIndex, - mid) - if(axis === d-2) { - //Degenerate sweep intersection: - // [red0, redX] with [blue0, blue1] - if(red0 < redX) { - retval = sweep.sweepComplete( - d, visit, - red0, redX, red, redIndex, - blue0, blue1, blue, blueIndex) - if(retval !== void 0) { - return retval + sprintf.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0 + while (_fmt) { + if ((match = re.text.exec(_fmt)) !== null) { + parse_tree[parse_tree.length] = match[0] + } + else if ((match = re.modulo.exec(_fmt)) !== null) { + parse_tree[parse_tree.length] = "%" + } + else if ((match = re.placeholder.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1 + var field_list = [], replacement_field = match[2], field_match = [] + if ((field_match = re.key.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1] + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== "") { + if ((field_match = re.key_access.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1] + } + else if ((field_match = re.index_access.exec(replacement_field)) !== null) { + field_list[field_list.length] = field_match[1] + } + else { + throw new SyntaxError("[sprintf] failed to parse named argument key") + } + } + } + else { + throw new SyntaxError("[sprintf] failed to parse named argument key") + } + match[2] = field_list } - } - - //Normal sweep intersection: - // [redX, red1] with [blue0, blue1] - if(redX < red1) { - retval = sweep.sweepBipartite( - d, visit, - redX, red1, red, redIndex, - blue0, blue1, blue, blueIndex) - if(retval !== void 0) { - return retval + else { + arg_names |= 2 } - } - } else { - if(red0 < redX) { - iterPush(top++, - axis+1, - red0, redX, - blue0, blue1, - 16, - -Infinity, Infinity) - } - if(redX < red1) { - iterPush(top++, - axis+1, - redX, red1, - blue0, blue1, - 0, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blue0, blue1, - redX, red1, - 1, - -Infinity, Infinity) - } + if (arg_names === 3) { + throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported") + } + parse_tree[parse_tree.length] = match } - } - } else { - if(flip) { - red1 = partitionContainsPointProper( - d, axis, - red0, redEnd, red, redIndex, - mid) - } else { - red1 = partitionContainsPoint( - d, axis, - red0, redEnd, red, redIndex, - mid) - } - if(red0 < red1) { - if(axis === d-2) { - if(flip) { - retval = sweep.sweepBipartite( - d, visit, - blue0, blue1, blue, blueIndex, - red0, red1, red, redIndex) - } else { - retval = sweep.sweepBipartite( - d, visit, - red0, red1, red, redIndex, - blue0, blue1, blue, blueIndex) - } - } else { - iterPush(top++, - axis+1, - red0, red1, - blue0, blue1, - flip, - -Infinity, Infinity) - iterPush(top++, - axis+1, - blue0, blue1, - red0, red1, - flip^1, - -Infinity, Infinity) + else { + throw new SyntaxError("[sprintf] unexpected placeholder") } - } + _fmt = _fmt.substring(match[0].length) } - } + return parse_tree } - } -} -},{"./brute":358,"./median":360,"./partition":361,"./sweep":363,"bit-twiddle":364,"typedarray-pool":366}],360:[function(require,module,exports){ -'use strict' -module.exports = findMedian + var vsprintf = function(fmt, argv, _argv) { + _argv = (argv || []).slice(0) + _argv.splice(0, 0, fmt) + return sprintf.apply(null, _argv) + } -var genPartition = require('./partition') + /** + * helpers + */ + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase() + } -var partitionStartLessThan = genPartition('lostart && boxes[ptr+axis] > x; - --j, ptr-=elemSize) { - //Swap - var aPtr = ptr - var bPtr = ptr+elemSize - for(var k=0; k>> 1) - var elemSize = 2*d - var pivot = mid - var value = boxes[elemSize*mid+axis] - - while(lo < hi) { - if(hi - lo < PARTITION_THRESHOLD) { - insertionSort(d, axis, lo, hi, boxes, ids) - value = boxes[elemSize*mid+axis] - break - } - - //Select pivot using median-of-3 - var count = hi - lo - var pivot0 = (Math.random()*count+lo)|0 - var value0 = boxes[elemSize*pivot0 + axis] - var pivot1 = (Math.random()*count+lo)|0 - var value1 = boxes[elemSize*pivot1 + axis] - var pivot2 = (Math.random()*count+lo)|0 - var value2 = boxes[elemSize*pivot2 + axis] - if(value0 <= value1) { - if(value2 >= value1) { - pivot = pivot1 - value = value1 - } else if(value0 >= value2) { - pivot = pivot0 - value = value0 - } else { - pivot = pivot2 - value = value2 - } - } else { - if(value1 >= value2) { - pivot = pivot1 - value = value1 - } else if(value2 >= value0) { - pivot = pivot0 - value = value0 - } else { - pivot = pivot2 - value = value2 - } - } +function hiddenStore(obj, key) { + var store = { identity: key }; + var valueOf = obj.valueOf; - //Swap pivot to end of array - var aPtr = elemSize * (hi-1) - var bPtr = elemSize * pivot - for(var i=0; i= 0) { - reads.push('lo=e[k+n]') +var TEMPLATE_CACHE = {} +var GRADIENT_CACHE = {} + +var EmptyProc = { + body: "", + args: [], + thisVars: [], + localVars: [] +} + +var centralDiff = cwiseCompiler({ + args: [ 'array', 'array', 'array' ], + pre: EmptyProc, + post: EmptyProc, + body: { + args: [ { + name: 'out', + lvalue: true, + rvalue: false, + count: 1 + }, { + name: 'left', + lvalue: false, + rvalue: true, + count: 1 + }, { + name: 'right', + lvalue: false, + rvalue: true, + count: 1 + }], + body: "out=0.5*(left-right)", + thisVars: [], + localVars: [] + }, + funcName: 'cdiff' +}) + +var zeroOut = cwiseCompiler({ + args: [ 'array' ], + pre: EmptyProc, + post: EmptyProc, + body: { + args: [ { + name: 'out', + lvalue: true, + rvalue: false, + count: 1 + }], + body: "out=0", + thisVars: [], + localVars: [] + }, + funcName: 'zero' +}) + +function generateTemplate(d) { + if(d in TEMPLATE_CACHE) { + return TEMPLATE_CACHE[d] } - if(predicate.indexOf('hi') >= 0) { - reads.push('hi=e[k+o]') + var code = [] + for(var i=0; i= 0) { + pickStr.push('0') + } else if(facet.indexOf(-(i+1)) >= 0) { + pickStr.push('s['+i+']-1') + } else { + pickStr.push('-1') + loStr.push('1') + hiStr.push('s['+i+']-2') + } + } + var boundStr = '.lo(' + loStr.join() + ').hi(' + hiStr.join() + ')' + if(loStr.length === 0) { + boundStr = '' + } + + if(cod > 0) { + code.push('if(1') + for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { + continue + } + code.push('&&s[', i, ']>2') + } + code.push('){grad', cod, '(src.pick(', pickStr.join(), ')', boundStr) + for(var i=0; i= 0 || facet.indexOf(-(i+1)) >= 0) { + continue + } + code.push(',dst.pick(', pickStr.join(), ',', i, ')', boundStr) + } + code.push(');') + } -var INSERT_SORT_CUTOFF = 32 + for(var i=0; i1){dst.set(', + pickStr.join(), ',', bnd, ',0.5*(src.get(', + cPickStr.join(), ')-src.get(', + dPickStr.join(), ')))}else{dst.set(', + pickStr.join(), ',', bnd, ',0)};') + } else { + code.push('if(s[', bnd, ']>1){diff(', outStr, + ',src.pick(', cPickStr.join(), ')', boundStr, + ',src.pick(', dPickStr.join(), ')', boundStr, + ');}else{zero(', outStr, ');};') + } + break -function insertionSort(left, right, data) { - var ptr = 2*(left+1) - for(var i=left+1; i<=right; ++i) { - var a = data[ptr++] - var b = data[ptr++] - var j = i - var jptr = ptr-2 - while(j-- > left) { - var x = data[jptr-2] - var y = data[jptr-1] - if(x < a) { + case 'mirror': + if(cod === 0) { + code.push('dst.set(', pickStr.join(), ',', bnd, ',0);') + } else { + code.push('zero(', outStr, ');') + } break - } else if(x === a && y < b) { + + case 'wrap': + var aPickStr = pickStr.slice() + var bPickStr = pickStr.slice() + if(facet[i] < 0) { + aPickStr[bnd] = 's[' + bnd + ']-2' + bPickStr[bnd] = '0' + + } else { + aPickStr[bnd] = 's[' + bnd + ']-1' + bPickStr[bnd] = '1' + } + if(cod === 0) { + code.push('if(s[', bnd, ']>2){dst.set(', + pickStr.join(), ',', bnd, ',0.5*(src.get(', + aPickStr.join(), ')-src.get(', + bPickStr.join(), ')))}else{dst.set(', + pickStr.join(), ',', bnd, ',0)};') + } else { + code.push('if(s[', bnd, ']>2){diff(', outStr, + ',src.pick(', aPickStr.join(), ')', boundStr, + ',src.pick(', bPickStr.join(), ')', boundStr, + ');}else{zero(', outStr, ');};') + } break + + default: + throw new Error('ndarray-gradient: Invalid boundary condition') } - data[jptr] = x - data[jptr+1] = y - jptr -= 2 } - data[jptr] = a - data[jptr+1] = b - } -} - -function swap(i, j, data) { - i *= 2 - j *= 2 - var x = data[i] - var y = data[i+1] - data[i] = data[j] - data[i+1] = data[j+1] - data[j] = x - data[j+1] = y -} -function move(i, j, data) { - i *= 2 - j *= 2 - data[i] = data[j] - data[i+1] = data[j+1] -} + if(cod > 0) { + code.push('};') + } + } -function rotate(i, j, k, data) { - i *= 2 - j *= 2 - k *= 2 - var x = data[i] - var y = data[i+1] - data[i] = data[j] - data[i+1] = data[j+1] - data[j] = data[k] - data[j+1] = data[k+1] - data[k] = x - data[k+1] = y -} + //Enumerate ridges, facets, etc. of hypercube + for(var i=0; i<(1< data[j+1] + //Compile and link routine, save cached procedure + var linkNames = [ 'diff', 'zero' ] + var linkArgs = [ centralDiff, zeroOut ] + for(var i=1; i<=d; ++i) { + linkNames.push('grad' + i) + linkArgs.push(generateTemplate(i)) } - return true -} + linkNames.push(code.join('')) -function comparePivot(i, y, b, data) { - i *= 2 - var x = data[i] - if(x < y) { - return true - } else if(x === y) { - return data[i+1] < b - } - return false + var link = Function.apply(void 0, linkNames) + var proc = link.apply(void 0, linkArgs) + TEMPLATE_CACHE[token] = proc + return proc } -function quickSort(left, right, data) { - var sixth = (right - left + 1) / 6 | 0, - index1 = left + sixth, - index5 = right - sixth, - index3 = left + right >> 1, - index2 = index3 - sixth, - index4 = index3 + sixth, - el1 = index1, - el2 = index2, - el3 = index3, - el4 = index4, - el5 = index5, - less = left + 1, - great = right - 1, - tmp = 0 - if(compare(el1, el2, data)) { - tmp = el1 - el1 = el2 - el2 = tmp - } - if(compare(el4, el5, data)) { - tmp = el4 - el4 = el5 - el5 = tmp - } - if(compare(el1, el3, data)) { - tmp = el1 - el1 = el3 - el3 = tmp - } - if(compare(el2, el3, data)) { - tmp = el2 - el2 = el3 - el3 = tmp - } - if(compare(el1, el4, data)) { - tmp = el1 - el1 = el4 - el4 = tmp - } - if(compare(el3, el4, data)) { - tmp = el3 - el3 = el4 - el4 = tmp - } - if(compare(el2, el5, data)) { - tmp = el2 - el2 = el5 - el5 = tmp - } - if(compare(el2, el3, data)) { - tmp = el2 - el2 = el3 - el3 = tmp +function gradient(out, inp, bc) { + if(Array.isArray(bc)) { + if(bc.length !== inp.dimension) { + throw new Error('ndarray-gradient: invalid boundary conditions') + } + } else if(typeof bc === 'string') { + bc = dup(inp.dimension, bc) + } else { + bc = dup(inp.dimension, 'clamp') } - if(compare(el4, el5, data)) { - tmp = el4 - el4 = el5 - el5 = tmp + if(out.dimension !== inp.dimension + 1) { + throw new Error('ndarray-gradient: output dimension must be +1 input dimension') } - - var pivot1X = data[2*el2] - var pivot1Y = data[2*el2+1] - var pivot2X = data[2*el4] - var pivot2Y = data[2*el4+1] - - var ptr0 = 2 * el1; - var ptr2 = 2 * el3; - var ptr4 = 2 * el5; - var ptr5 = 2 * index1; - var ptr6 = 2 * index3; - var ptr7 = 2 * index5; - for (var i1 = 0; i1 < 2; ++i1) { - var x = data[ptr0+i1]; - var y = data[ptr2+i1]; - var z = data[ptr4+i1]; - data[ptr5+i1] = x; - data[ptr6+i1] = y; - data[ptr7+i1] = z; + if(out.shape[inp.dimension] !== inp.dimension) { + throw new Error('ndarray-gradient: output shape must match input shape') } - - move(index2, left, data) - move(index4, right, data) - for (var k = less; k <= great; ++k) { - if (comparePivot(k, pivot1X, pivot1Y, data)) { - if (k !== less) { - swap(k, less, data) - } - ++less; - } else { - if (!comparePivot(k, pivot2X, pivot2Y, data)) { - while (true) { - if (!comparePivot(great, pivot2X, pivot2Y, data)) { - if (--great < k) { - break; - } - continue; - } else { - if (comparePivot(great, pivot1X, pivot1Y, data)) { - rotate(k, less, great, data) - ++less; - --great; - } else { - swap(k, great, data) - --great; - } - break; - } - } - } + for(var i=0; iright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - var blueActive = 0 - for(var i=0; i= BLUE_FLAG) { - //blue destroy event - e = (e-BLUE_FLAG)|0 - sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, e) - } else if(e >= 0) { - //red destroy event - sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e) - } else if(e <= -BLUE_FLAG) { - //blue create event - e = (-e-BLUE_FLAG)|0 - for(var j=0; jright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - var blueActive = 0 - var commonActive = 0 - for(var i=0; i>1) === (SWEEP_EVENTS[2*i+3]>>1)) { - color = 2 - i += 1 - } - - if(e < 0) { - //Create event - var id = -(e>>1) - 1 - - //Intersect with common - for(var j=0; j>1) - 1 - if(color === 0) { - //Red - sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, id) - } else if(color === 1) { - //Blue - sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, id) - } else if(color === 2) { - //Both - sqPop(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive--, id) - } - } +function clampVec(v) { + var result = new Array(3) + for(var i=0; i<3; ++i) { + result[i] = Math.min(Math.max(v[i], -1e8), 1e8) } + return result } -//Sweep and prune/scanline algorithm: -// Scan along axis, detect intersections -// Brute force all boxes along axis -function scanBipartite( - d, axis, visit, flip, - redStart, redEnd, red, redIndex, - blueStart, blueEnd, blue, blueIndex) { - - var ptr = 0 - var elemSize = 2*d - var istart = axis - var iend = axis+d +function SurfacePlot( + gl, + shape, + bounds, + shader, + pickShader, + coordinates, + vao, + colorMap, + contourShader, + contourPickShader, + contourBuffer, + contourVAO, + dynamicBuffer, + dynamicVAO) { - var redShift = 1 - var blueShift = 1 - if(flip) { - blueShift = BLUE_FLAG - } else { - redShift = BLUE_FLAG - } + this.gl = gl + this.shape = shape + this.bounds = bounds - for(var i=redStart; iright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - for(var i=0; i= BLUE_FLAG) { - isRed = !flip - idx -= BLUE_FLAG - } else { - isRed = !!flip - idx -= 1 - } - if(isRed) { - sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, idx) - } else { - var blueId = blueIndex[idx] - var bluePtr = elemSize * idx - - var b0 = blue[bluePtr+axis+1] - var b1 = blue[bluePtr+axis+1+d] + this._contourShader = contourShader + this._contourPickShader = contourPickShader + this._contourBuffer = contourBuffer + this._contourVAO = contourVAO + this._contourOffsets = [[], [], []] + this._contourCounts = [[], [], []] + this._vertexCount = 0 -red_loop: - for(var j=0; jright - var n = ptr >>> 1 - isort(SWEEP_EVENTS, n) - - var redActive = 0 - for(var i=0; i= BLUE_FLAG) { - RED_SWEEP_QUEUE[redActive++] = idx - BLUE_FLAG - } else { - idx -= 1 - var blueId = blueIndex[idx] - var bluePtr = elemSize * idx + this.colorBounds = [ false, false ] - var b0 = blue[bluePtr+axis+1] - var b1 = blue[bluePtr+axis+1+d] + //Store xyz fields, need this for picking + this._field = [ + ndarray(pool.mallocFloat(1024), [0,0]), + ndarray(pool.mallocFloat(1024), [0,0]), + ndarray(pool.mallocFloat(1024), [0,0]) ] -red_loop: - for(var j=0; j=0; --j) { - if(RED_SWEEP_QUEUE[j] === idx) { - for(var k=j+1; k>>0 +var proto = SurfacePlot.prototype -module.exports = nextafter +proto.isTransparent = function() { + return this.opacity < 1 +} -function nextafter(x, y) { - if(isNaN(x) || isNaN(y)) { - return NaN - } - if(x === y) { - return x - } - if(x === 0) { - if(y < 0) { - return -SMALLEST_DENORM - } else { - return SMALLEST_DENORM - } +proto.isOpaque = function() { + if(this.opacity >= 1) { + return true } - var hi = doubleBits.hi(x) - var lo = doubleBits.lo(x) - if((y > x) === (x > 0)) { - if(lo === UINT_MAX) { - hi += 1 - lo = 0 - } else { - lo += 1 - } - } else { - if(lo === 0) { - lo = UINT_MAX - hi -= 1 - } else { - lo -= 1 + for(var i=0; i<3; ++i) { + if(this._contourCounts[i].length > 0 || this._dynamicCounts[i] > 0) { + return true } } - return doubleBits.pack(lo, hi) + return false } -},{"double-bits":369}],369:[function(require,module,exports){ -arguments[4][353][0].apply(exports,arguments) -},{"buffer":48,"dup":353}],370:[function(require,module,exports){ -'use strict' - -var bnadd = require('big-rat/add') -module.exports = add +proto.pickSlots = 1 -function add(a, b) { - var n = a.length - var r = new Array(n) - for(var i=0; i0)][i] + multiply(axisSquish, camera.model, axisSquish) -var rat = require('big-rat') -var mul = require('big-rat/mul') + var nclipBounds = PROJECT_DATA.clipBounds[i] + for(var k=0; k<2; ++k) { + for(var j=0; j<3; ++j) { + nclipBounds[k][j] = camera.clipBounds[k][j] + } + } + nclipBounds[0][i] = -1e8 + nclipBounds[1][i] = 1e8 + } -module.exports = muls + PROJECT_DATA.showSurface = showSurface + PROJECT_DATA.showContour = showContour -function muls(a, x) { - var s = rat(x) - var n = a.length - var r = new Array(n) - for(var i=0; i 0 && y0 > 0) || (x0 < 0 && y0 < 0)) { - return false + for(var i=0; i<3; ++i) { + uniforms.eyePosition[i] = invCameraMatrix[12+i] / invCameraMatrix[15] } - var x1 = orient(b0, a0, a1) - var y1 = orient(b1, a0, a1) - if((x1 > 0 && y1 > 0) || (x1 < 0 && y1 < 0)) { - return false + var w = invCameraMatrix[15] + for(var i=0; i<3; ++i) { + w += this.lightPosition[i] * invCameraMatrix[4*i+3] } - - //Check for degenerate collinear case - if(x0 === 0 && y0 === 0 && x1 === 0 && y1 === 0) { - return checkCollinear(a0, a1, b0, b1) + for(var i=0; i<3; ++i) { + var s = invCameraMatrix[12+i] + for(var j=0; j<3; ++j) { + s += invCameraMatrix[4*j+i] * this.lightPosition[j] + } + uniforms.lightPosition[i] = s / w } - return true -} -},{"robust-orientation":996}],375:[function(require,module,exports){ -arguments[4][61][0].apply(exports,arguments) -},{"dup":61}],376:[function(require,module,exports){ -'use strict' - -module.exports = trimLeaves + var projectData = computeProjectionData(uniforms, this) -var e2a = require('edges-to-adjacency-list') + if(projectData.showSurface && (transparent === (this.opacity < 1))) { + //Set up uniforms + this._shader.bind() + this._shader.uniforms = uniforms -function trimLeaves(edges, positions) { - var adj = e2a(edges, positions.length) - var live = new Array(positions.length) - var nbhd = new Array(positions.length) + //Draw it + this._vao.bind() - var dead = [] - for(var i=0; i 0) { - var v = dead.pop() - live[v] = false - var n = adj[v] - for(var i=0; i 0) { - nextCell = adj[i][b][0] - nextDir = i - break + } else if(j === 0 || (j-1) === this.highlightLevel[i]) { + shader.uniforms.contourColor = this.contourColor[i] + shader.uniforms.contourTint = this.contourTint[i] + } + shader.uniforms.height = this.contourLevels[i][j] + vao.draw(gl.LINES, this._contourCounts[i][j], this._contourOffsets[i][j]) } } - nextVertex = nextCell[nextDir^1] - for(var dir=0; dir<2; ++dir) { - var nbhd = adj[dir][b] - for(var k=0; k 0) { - nextCell = e - nextVertex = p - nextDir = dir + //Draw projections of surface + for(var i=0; i<3; ++i) { + shader.uniforms.model = projectData.projections[i] + shader.uniforms.clipBounds = projectData.clipBounds[i] + for(var j=0; j<3; ++j) { + if(!this.contourProject[i][j]) { + continue + } + shader.uniforms.permutation = PERMUTATIONS[j] + gl.lineWidth(this.contourWidth[j]) + for(var k=0; k 0) { - var ni = adj[0][i].length - var ncycle = extractCycle(i,j) - if(shouldGlue(pcycle, ncycle)) { - //Glue together trivial cycles - pcycle.push.apply(pcycle, ncycle) - } else { - if(pcycle.length > 0) { - cycles.push(pcycle) - } - pcycle = ncycle + shader.uniforms.contourColor = this.dynamicColor[i] + shader.uniforms.contourTint = this.dynamicTint[i] + shader.uniforms.height = this.dynamicLevel[i] + vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) + + for(var j=0; j<3; ++j) { + if(!this.contourProject[j][i]) { + continue } - } - if(pcycle.length > 0) { - cycles.push(pcycle) + + shader.uniforms.model = projectData.projections[j] + shader.uniforms.clipBounds = projectData.clipBounds[j] + vao.draw(gl.LINES, this._dynamicCounts[i], this._dynamicOffsets[i]) } } + + vao.unbind() } +} - //Combine paths and loops together - return cycles +proto.draw = function(params) { + return drawCore.call(this, params, false) } -},{"compare-angle":379}],379:[function(require,module,exports){ -"use strict" -module.exports = compareAngle +proto.drawTransparent = function(params) { + return drawCore.call(this, params, true) +} -var orient = require("robust-orientation") -var sgn = require("signum") -var twoSum = require("two-sum") -var robustProduct = require("robust-product") -var robustSum = require("robust-sum") +var PICK_UNIFORMS = { + model: IDENTITY, + view: IDENTITY, + projection: IDENTITY, + inverseModel: IDENTITY, + clipBounds: [[0,0,0],[0,0,0]], + height: 0.0, + shape: [0,0], + pickId: 0, + lowerBound: [0,0,0], + upperBound: [0,0,0], + zOffset: 0.0, + permutation: [1,0,0,0,1,0,0,0,1], + lightPosition: [0,0,0], + eyePosition: [0,0,0] +} -function testInterior(a, b, c) { - var x0 = twoSum(a[0], -b[0]) - var y0 = twoSum(a[1], -b[1]) - var x1 = twoSum(c[0], -b[0]) - var y1 = twoSum(c[1], -b[1]) +proto.drawPick = function(params) { + params = params || {} + var gl = this.gl + gl.disable(gl.CULL_FACE) - var d = robustSum( - robustProduct(x0, x1), - robustProduct(y0, y1)) + var uniforms = PICK_UNIFORMS + uniforms.model = params.model || IDENTITY + uniforms.view = params.view || IDENTITY + uniforms.projection = params.projection || IDENTITY + uniforms.shape = this._field[2].shape + uniforms.pickId = this.pickId / 255.0 + uniforms.lowerBound = this.bounds[0] + uniforms.upperBound = this.bounds[1] + uniforms.permutation = DEFAULT_PERM - return d[d.length-1] >= 0 -} + for(var i=0; i<2; ++i) { + var clipClamped = uniforms.clipBounds[i] + for(var j=0; j<3; ++j) { + clipClamped[j] = Math.min(Math.max(this.clipBounds[i][j], -1e8), 1e8) + } + } -function compareAngle(a, b, c, d) { - var bcd = orient(b, c, d) - if(bcd === 0) { - //Handle degenerate cases - var sabc = sgn(orient(a, b, c)) - var sabd = sgn(orient(a, b, d)) - if(sabc === sabd) { - if(sabc === 0) { - var ic = testInterior(a, b, c) - var id = testInterior(a, b, d) - if(ic === id) { - return 0 - } else if(ic) { - return 1 - } else { - return -1 - } - } - return 0 - } else if(sabd === 0) { - if(sabc > 0) { - return -1 - } else if(testInterior(a, b, d)) { - return -1 - } else { - return 1 - } - } else if(sabc === 0) { - if(sabd > 0) { - return 1 - } else if(testInterior(a, b, c)) { - return 1 - } else { - return -1 + var projectData = computeProjectionData(uniforms, this) + + if(projectData.showSurface) { + //Set up uniforms + this._pickShader.bind() + this._pickShader.uniforms = uniforms + + //Draw it + this._vao.bind() + this._vao.draw(gl.TRIANGLES, this._vertexCount) + + //Draw projections of surface + for(var i=0; i<3; ++i) { + if(!this.surfaceProject[i]) { + continue } + this._pickShader.uniforms.model = projectData.projections[i] + this._pickShader.uniforms.clipBounds = projectData.clipBounds[i] + this._vao.draw(gl.TRIANGLES, this._vertexCount) } - return sgn(sabd - sabc) + + this._vao.unbind() } - var abc = orient(a, b, c) - if(abc > 0) { - if(bcd > 0 && orient(a, b, d) > 0) { - return 1 - } - return -1 - } else if(abc < 0) { - if(bcd > 0 || orient(a, b, d) > 0) { - return 1 - } - return -1 - } else { - var abd = orient(a, b, d) - if(abd > 0) { - return 1 - } else { - if(testInterior(a, b, c)) { - return 1 - } else { - return -1 + + if(projectData.showContour) { + var shader = this._contourPickShader + + shader.bind() + shader.uniforms = uniforms + + var vao = this._contourVAO + vao.bind() + + for(var j=0; j<3; ++j) { + gl.lineWidth(this.contourWidth[j]) + shader.uniforms.permutation = PERMUTATIONS[j] + for(var i=0; i 0) { return 1 } - return 0.0 + vao.unbind() + } } -},{}],383:[function(require,module,exports){ -arguments[4][36][0].apply(exports,arguments) -},{"dup":36}],384:[function(require,module,exports){ -arguments[4][4][0].apply(exports,arguments) -},{"dup":4}],385:[function(require,module,exports){ -"use strict" -var bounds = require("binary-search-bounds") -var NOT_FOUND = 0 -var SUCCESS = 1 -var EMPTY = 2 +proto.pick = function(selection) { + if(!selection) { + return null + } -module.exports = createWrapper + if(selection.id !== this.pickId) { + return null + } -function IntervalTreeNode(mid, left, right, leftPoints, rightPoints) { - this.mid = mid - this.left = left - this.right = right - this.leftPoints = leftPoints - this.rightPoints = rightPoints - this.count = (left ? left.count : 0) + (right ? right.count : 0) + leftPoints.length -} + var shape = this._field[2].shape -var proto = IntervalTreeNode.prototype + var result = this._pickResult -function copy(a, b) { - a.mid = b.mid - a.left = b.left - a.right = b.right - a.leftPoints = b.leftPoints - a.rightPoints = b.rightPoints - a.count = b.count -} + //Compute uv coordinate + var x = shape[0] * (selection.value[0] + (selection.value[2]>>4)/16.0)/255.0 + var ix = Math.floor(x) + var fx = x - ix -function rebuild(node, intervals) { - var ntree = createIntervalTree(intervals) - node.mid = ntree.mid - node.left = ntree.left - node.right = ntree.right - node.leftPoints = ntree.leftPoints - node.rightPoints = ntree.rightPoints - node.count = ntree.count -} + var y = shape[1] * (selection.value[1] + (selection.value[2]&15)/16.0)/255.0 + var iy = Math.floor(y) + var fy = y - iy -function rebuildWithInterval(node, interval) { - var intervals = node.intervals([]) - intervals.push(interval) - rebuild(node, intervals) -} + ix += 1 + iy += 1 -function rebuildWithoutInterval(node, interval) { - var intervals = node.intervals([]) - var idx = intervals.indexOf(interval) - if(idx < 0) { - return NOT_FOUND - } - intervals.splice(idx, 1) - rebuild(node, intervals) - return SUCCESS -} + //Compute xyz coordinate + var pos = result.position + pos[0] = pos[1] = pos[2] = 0 + for(var dx=0; dx<2; ++dx) { + var s = dx ? fx : 1.0 - fx + for(var dy=0; dy<2; ++dy) { + var t = dy ? fy : 1.0 - fy -proto.intervals = function(result) { - result.push.apply(result, this.leftPoints) - if(this.left) { - this.left.intervals(result) - } - if(this.right) { - this.right.intervals(result) - } - return result -} + var r = ix + dx + var c = iy + dy + var w = s * t -proto.insert = function(interval) { - var weight = this.count - this.leftPoints.length - this.count += 1 - if(interval[1] < this.mid) { - if(this.left) { - if(4*(this.left.count+1) > 3*(weight+1)) { - rebuildWithInterval(this, interval) - } else { - this.left.insert(interval) - } - } else { - this.left = createIntervalTree([interval]) - } - } else if(interval[0] > this.mid) { - if(this.right) { - if(4*(this.right.count+1) > 3*(weight+1)) { - rebuildWithInterval(this, interval) - } else { - this.right.insert(interval) + for(var i=0; i<3; ++i) { + pos[i] += this._field[i].get(r,c) * w } - } else { - this.right = createIntervalTree([interval]) } - } else { - var l = bounds.ge(this.leftPoints, interval, compareBegin) - var r = bounds.ge(this.rightPoints, interval, compareEnd) - this.leftPoints.splice(l, 0, interval) - this.rightPoints.splice(r, 0, interval) } -} -proto.remove = function(interval) { - var weight = this.count - this.leftPoints - if(interval[1] < this.mid) { - if(!this.left) { - return NOT_FOUND - } - var rw = this.right ? this.right.count : 0 - if(4 * rw > 3 * (weight-1)) { - return rebuildWithoutInterval(this, interval) - } - var r = this.left.remove(interval) - if(r === EMPTY) { - this.left = null - this.count -= 1 - return SUCCESS - } else if(r === SUCCESS) { - this.count -= 1 - } - return r - } else if(interval[0] > this.mid) { - if(!this.right) { - return NOT_FOUND - } - var lw = this.left ? this.left.count : 0 - if(4 * lw > 3 * (weight-1)) { - return rebuildWithoutInterval(this, interval) - } - var r = this.right.remove(interval) - if(r === EMPTY) { - this.right = null - this.count -= 1 - return SUCCESS - } else if(r === SUCCESS) { - this.count -= 1 - } - return r - } else { - if(this.count === 1) { - if(this.leftPoints[0] === interval) { - return EMPTY - } else { - return NOT_FOUND - } - } - if(this.leftPoints.length === 1 && this.leftPoints[0] === interval) { - if(this.left && this.right) { - var p = this - var n = this.left - while(n.right) { - p = n - n = n.right - } - if(p === this) { - n.right = this.right - } else { - var l = this.left - var r = this.right - p.count -= n.count - p.right = n.left - n.left = l - n.right = r - } - copy(this, n) - this.count = (this.left?this.left.count:0) + (this.right?this.right.count:0) + this.leftPoints.length - } else if(this.left) { - copy(this, this.left) - } else { - copy(this, this.right) - } - return SUCCESS - } - for(var l = bounds.ge(this.leftPoints, interval, compareBegin); l 0) { + levelIndex[j] = 0 } - if(this.leftPoints[l] === interval) { - this.count -= 1 - this.leftPoints.splice(l, 1) - for(var r = bounds.ge(this.rightPoints, interval, compareEnd); r Math.abs(b-pos[j])) { + levelIndex[j] += 1 } } - return NOT_FOUND } -} -function reportLeftRange(arr, hi, cb) { - for(var i=0; i=0 && arr[i][1] >= lo; --i) { - var r = cb(arr[i]) - if(r) { return r } - } +function padField(nfield, field) { + + var shape = field.shape.slice() + var nshape = nfield.shape.slice() + + //Center + ops.assign(nfield.lo(1,1).hi(shape[0], shape[1]), field) + + //Edges + ops.assign(nfield.lo(1).hi(shape[0], 1), + field.hi(shape[0], 1)) + ops.assign(nfield.lo(1,nshape[1]-1).hi(shape[0],1), + field.lo(0,shape[1]-1).hi(shape[0],1)) + ops.assign(nfield.lo(0,1).hi(1,shape[1]), + field.hi(1)) + ops.assign(nfield.lo(nshape[0]-1,1).hi(1,shape[1]), + field.lo(shape[0]-1)) + //Corners + nfield.set(0,0, field.get(0,0)) + nfield.set(0,nshape[1]-1, field.get(0,shape[1]-1)) + nfield.set(nshape[0]-1,0, field.get(shape[0]-1,0)) + nfield.set(nshape[0]-1,nshape[1]-1, field.get(shape[0]-1,shape[1]-1)) } -function reportRange(arr, cb) { - for(var i=0; i this.mid) { - if(this.right) { - var r = this.right.queryPoint(x, cb) - if(r) { return r } + return [x[0], x[1], x[2], x[3]] + } + return [0,0,0,1] +} + +function handleColor(param) { + if(Array.isArray(param)) { + if(Array.isArray(param)) { + return [ toColor(param[0]), + toColor(param[1]), + toColor(param[2]) ] + } else { + var c = toColor(param) + return [ + c.slice(), + c.slice(), + c.slice() ] } - return reportRightRange(this.rightPoints, x, cb) - } else { - return reportRange(this.leftPoints, cb) } } -proto.queryInterval = function(lo, hi, cb) { - if(lo < this.mid && this.left) { - var r = this.left.queryInterval(lo, hi, cb) - if(r) { return r } +proto.update = function(params) { + params = params || {} + + this.dirty = true + + if('contourWidth' in params) { + this.contourWidth = handleArray(params.contourWidth, Number) } - if(hi > this.mid && this.right) { - var r = this.right.queryInterval(lo, hi, cb) - if(r) { return r } + if('showContour' in params) { + this.showContour = handleArray(params.showContour, Boolean) } - if(hi < this.mid) { - return reportLeftRange(this.leftPoints, hi, cb) - } else if(lo > this.mid) { - return reportRightRange(this.rightPoints, lo, cb) - } else { - return reportRange(this.leftPoints, cb) + if('showSurface' in params) { + this.showSurface = !!params.showSurface + } + if('contourTint' in params) { + this.contourTint = handleArray(params.contourTint, Boolean) + } + if('contourColor' in params) { + this.contourColor = handleColor(params.contourColor) + } + if('contourProject' in params) { + this.contourProject = handleArray(params.contourProject, function(x) { + return handleArray(x, Boolean) + }) + } + if('surfaceProject' in params) { + this.surfaceProject = params.surfaceProject + } + if('dynamicColor' in params) { + this.dynamicColor = handleColor(params.dynamicColor) + } + if('dynamicTint' in params) { + this.dynamicTint = handleArray(params.dynamicTint, Number) + } + if('dynamicWidth' in params) { + this.dynamicWidth = handleArray(params.dynamicWidth, Number) + } + if('opacity' in params) { + this.opacity = params.opacity + } + if('colorBounds' in params) { + this.colorBounds = params.colorBounds } -} -function compareNumbers(a, b) { - return a - b -} + var field = params.field || (params.coords && params.coords[2]) || null -function compareBegin(a, b) { - var d = a[0] - b[0] - if(d) { return d } - return a[1] - b[1] -} + if(!field) { + if(this._field[2].shape[0] || this._field[2].shape[2]) { + field = this._field[2].lo(1,1).hi(this._field[2].shape[0]-2, this._field[2].shape[1]-2) + } else { + field = this._field[2].hi(0,0) + } + } -function compareEnd(a, b) { - var d = a[1] - b[1] - if(d) { return d } - return a[0] - b[0] -} + //Update field + if('field' in params || 'coords' in params) { + var fsize = (field.shape[0]+2)*(field.shape[1]+2) -function createIntervalTree(intervals) { - if(intervals.length === 0) { - return null - } - var pts = [] - for(var i=0; i this._field[2].data.length) { + pool.freeFloat(this._field[2].data) + this._field[2].data = pool.mallocFloat(bits.nextPow2(fsize)) + } - var mid = pts[pts.length>>1] + //Pad field + this._field[2] = ndarray(this._field[2].data, [field.shape[0]+2, field.shape[1]+2]) + padField(this._field[2], field) - var leftIntervals = [] - var rightIntervals = [] - var centerIntervals = [] - for(var i=0; i this._field[i].data.length) { + pool.freeFloat(this._field[i].data) + this._field[i].data = pool.mallocFloat(this._field[2].size) + } + this._field[i] = ndarray(this._field[i].data, [shape[0]+2, shape[1]+2]) + } + + //Generate x/y coordinates + if(params.coords) { + var coords = params.coords + if(!Array.isArray(coords) || coords.length !== 3) { + throw new Error('gl-surface: invalid coordinates for x/y') + } + for(var i=0; i<2; ++i) { + var coord = coords[i] + for(var j=0; j<2; ++j) { + if(coord.shape[j] !== shape[j]) { + throw new Error('gl-surface: coords have incorrect shape') + } + } + padField(this._field[i], coord) + } + } else if(params.ticks) { + var ticks = params.ticks + if(!Array.isArray(ticks) || ticks.length !== 2) { + throw new Error('gl-surface: invalid ticks') + } + for(var i=0; i<2; ++i) { + var tick = ticks[i] + if(Array.isArray(tick) || tick.length) { + tick = ndarray(tick) + } + if(tick.shape[0] !== shape[i]) { + throw new Error('gl-surface: invalid tick length') + } + //Make a copy view of the tick array + var tick2 = ndarray(tick.data, shape) + tick2.stride[i] = tick.stride[0] + tick2.stride[i^1] = 0 + + //Fill in field array + padField(this._field[i], tick2) + } } else { - centerIntervals.push(s) + for(var i=0; i<2; ++i) { + var offset = [0,0] + offset[i] = 1 + this._field[i] = ndarray(this._field[i].data, [shape[0]+2, shape[1]+2], offset, 0) + } + this._field[0].set(0,0,0) + for(var j=0; j b[1][0]) { - bl = b[1] - br = b[0] - } else { - var alo = Math.min(a[0][1], a[1][1]) - var ahi = Math.max(a[0][1], a[1][1]) - var blo = Math.min(b[0][1], b[1][1]) - var bhi = Math.max(b[0][1], b[1][1]) - if(ahi < blo) { - return ahi - blo - } - if(alo > bhi) { - return alo - bhi + hi[0] = Math.max(hi[0], tx) + hi[1] = Math.max(hi[1], ty) + hi[2] = Math.max(hi[2], f) + + vertexCount += 1 + } + } } - return ahi - bhi - } - var al, ar - if(a[0][1] < a[1][1]) { - al = a[0] - ar = a[1] - } else { - al = a[1] - ar = a[0] - } - var d = orient(br, bl, al) - if(d) { - return d - } - d = orient(br, bl, ar) - if(d) { - return d - } - return ar - br -} + this._vertexCount = vertexCount + this._coordinateBuffer.update(tverts.subarray(0,tptr)) + pool.freeFloat(tverts) + pool.free(normals.data) -function orderSegments(b, a) { - var al, ar - if(a[0][0] < a[1][0]) { - al = a[0] - ar = a[1] - } else if(a[0][0] > a[1][0]) { - al = a[1] - ar = a[0] - } else { - return horizontalOrder(a, b) - } - var bl, br - if(b[0][0] < b[1][0]) { - bl = b[0] - br = b[1] - } else if(b[0][0] > b[1][0]) { - bl = b[1] - br = b[0] - } else { - return -horizontalOrder(b, a) + //Update bounds + this.bounds = [lo, hi] } - var d1 = orient(al, ar, br) - var d2 = orient(al, ar, bl) - if(d1 < 0) { - if(d2 <= 0) { - return d1 - } - } else if(d1 > 0) { - if(d2 >= 0) { - return d1 + + //Update level crossings + var levelsChanged = false + if('levels' in params) { + var levels = params.levels + if(!Array.isArray(levels[0])) { + levels = [ [], [], levels ] + } else { + levels = levels.slice() } - } else if(d2) { - return d2 - } - d1 = orient(br, bl, ar) - d2 = orient(br, bl, al) - if(d1 < 0) { - if(d2 <= 0) { - return d1 + for(var i=0; i<3; ++i) { + levels[i] = levels[i].slice() + levels.sort(function(a,b) { + return a-b + }) } - } else if(d1 > 0) { - if(d2 >= 0) { - return d1 +change_test: + for(var i=0; i<3; ++i) { + if(levels[i].length !== this.contourLevels[i].length) { + levelsChanged = true + break + } + for(var j=0; j=0; --s) { - var n = n_stack[s] - if(d_stack[s] <= 0) { - n_stack[s] = new RBNode(n._color, n.key, n.value, n_stack[s+1], n.right, n._count+1) - } else { - n_stack[s] = new RBNode(n._color, n.key, n.value, n.left, n_stack[s+1], n._count+1) - } - } - //Rebalance tree using rotations - //console.log("start insert", key, d_stack) - for(var s=n_stack.length-1; s>1; --s) { - var p = n_stack[s-1] - var n = n_stack[s] - if(p._color === BLACK || n._color === BLACK) { - break - } - var pp = n_stack[s-2] - if(pp.left === p) { - if(p.left === n) { - var y = pp.right - if(y && y._color === RED) { - //console.log("LLr") - p._color = BLACK - pp.right = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("LLb") - pp._color = RED - pp.left = p.right - p._color = BLACK - p.right = pp - n_stack[s-2] = p - n_stack[s-1] = n - recount(pp) - recount(p) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.left === pp) { - ppp.left = p - } else { - ppp.right = p - } - } - break - } - } else { - var y = pp.right - if(y && y._color === RED) { - //console.log("LRr") - p._color = BLACK - pp.right = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("LRb") - p.right = n.left - pp._color = RED - pp.left = n.right - n._color = BLACK - n.left = p - n.right = pp - n_stack[s-2] = n - n_stack[s-1] = p - recount(pp) - recount(p) - recount(n) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.left === pp) { - ppp.left = n - } else { - ppp.right = n - } - } - break - } - } - } else { - if(p.right === n) { - var y = pp.left - if(y && y._color === RED) { - //console.log("RRr", y.key) - p._color = BLACK - pp.left = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("RRb") - pp._color = RED - pp.right = p.left - p._color = BLACK - p.left = pp - n_stack[s-2] = p - n_stack[s-1] = n - recount(pp) - recount(p) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.right === pp) { - ppp.right = p - } else { - ppp.left = p + var w = s * t + parts[dd] += w * f + } + } } - } - break - } - } else { - var y = pp.left - if(y && y._color === RED) { - //console.log("RLr") - p._color = BLACK - pp.left = repaint(BLACK, y) - pp._color = RED - s -= 1 - } else { - //console.log("RLb") - p.left = n.right - pp._color = RED - pp.right = n.left - n._color = BLACK - n.right = p - n.left = pp - n_stack[s-2] = n - n_stack[s-1] = p - recount(pp) - recount(p) - recount(n) - if(s >= 3) { - var ppp = n_stack[s-3] - if(ppp.right === pp) { - ppp.right = n + + if(!hole) { + contourVerts.push(parts[0], parts[1], p[0], p[1]) + vertexCount += 1 } else { - ppp.left = n + if(k > 0) { + //If we already added first edge, pop off verts + for(var l=0; l<4; ++l) { + contourVerts.pop() + } + vertexCount -= 1 + } + continue edge_loop } } - break } + levelCounts.push(vertexCount) } + + //Store results + this._contourOffsets[dim] = levelOffsets + this._contourCounts[dim] = levelCounts } - } - //Return new tree - n_stack[0]._color = BLACK - return new RedBlackTree(cmp, n_stack[0]) -} + var floatBuffer = pool.mallocFloat(contourVerts.length) + for(var i=0; i 0) { - v = visit(node.key, node.value) - if(v) { return v } + + this.dynamicLevel[d] = levels[d] + + var u = (d+1) % 3 + var v = (d+2) % 3 + + var f = this._field[d] + var g = this._field[u] + var h = this._field[v] + + var graph = surfaceNets(f, levels[d]) + var edges = graph.cells + var positions = graph.positions + + this._dynamicOffsets[d] = vertexCount + + for(var i=0; i 0 && node.right) { - return doVisit(lo, hi, compare, visit, node.right) - } + + this._dynamicBuffer.update(scratchBuffer.subarray(0, 2*vertexCount)) + pool.freeFloat(scratchBuffer) } +function createSurfacePlot(params) { + var gl = params.gl + var field = params.field || (params.coords && params.coords[2]) || ndarray([], [0,0]) -proto.forEach = function rbTreeForEach(visit, lo, hi) { - if(!this.root) { - return + var shader = createShader(gl) + var pickShader = createPickShader(gl) + var contourShader = createContourShader(gl) + var contourPickShader = createPickContourShader(gl) + + var coordinateBuffer = createBuffer(gl) + var vao = createVAO(gl, [ + { buffer: coordinateBuffer, + size: 4, + stride: SURFACE_VERTEX_SIZE, + offset: 0 + }, + { buffer: coordinateBuffer, + size: 2, + stride: SURFACE_VERTEX_SIZE, + offset: 16 + }, + { + buffer: coordinateBuffer, + size: 3, + stride: SURFACE_VERTEX_SIZE, + offset: 24 + } + ]) + + var contourBuffer = createBuffer(gl) + var contourVAO = createVAO(gl, [ + { + buffer: contourBuffer, + size: 4 + }]) + + var dynamicBuffer = createBuffer(gl) + var dynamicVAO = createVAO(gl, [ + { + buffer: dynamicBuffer, + size: 2, + type: gl.FLOAT + }]) + + var cmap = createTexture(gl, 1, N_COLORS, gl.RGBA, gl.UNSIGNED_BYTE) + cmap.minFilter = gl.LINEAR + cmap.magFilter = gl.LINEAR + + var surface = new SurfacePlot( + gl, + [0,0], + [[0,0,0], [0,0,0]], + shader, + pickShader, + coordinateBuffer, + vao, + cmap, + contourShader, + contourPickShader, + contourBuffer, + contourVAO, + dynamicBuffer, + dynamicVAO) + + var nparams = { + levels: [[], [], []] } - switch(arguments.length) { - case 1: - return doVisitFull(visit, this.root) - break + for(var id in params) { + nparams[id] = params[id] + } + nparams.colormap = nparams.colormap || 'jet' - case 2: - return doVisitHalf(lo, this._compare, visit, this.root) - break + surface.update(nparams) - case 3: - if(this._compare(lo, hi) >= 0) { - return - } - return doVisit(lo, hi, this._compare, visit, this.root) - break + return surface +} + +},{"./lib/shaders":179,"binary-search-bounds":180,"bit-twiddle":49,"colormap":57,"gl-buffer":75,"gl-mat4/invert":94,"gl-mat4/multiply":96,"gl-texture2d":185,"gl-vao":189,"ndarray":208,"ndarray-gradient":181,"ndarray-ops":207,"ndarray-pack":182,"surface-nets":227,"typedarray-pool":233}],185:[function(require,module,exports){ +'use strict' + +var ndarray = require('ndarray') +var ops = require('ndarray-ops') +var pool = require('typedarray-pool') + +module.exports = createTexture2D + +var linearTypes = null +var filterTypes = null +var wrapTypes = null + +function lazyInitLinearTypes(gl) { + linearTypes = [ + gl.LINEAR, + gl.NEAREST_MIPMAP_LINEAR, + gl.LINEAR_MIPMAP_NEAREST, + gl.LINEAR_MIPMAP_NEAREST + ] + filterTypes = [ + gl.NEAREST, + gl.LINEAR, + gl.NEAREST_MIPMAP_NEAREST, + gl.NEAREST_MIPMAP_LINEAR, + gl.LINEAR_MIPMAP_NEAREST, + gl.LINEAR_MIPMAP_LINEAR + ] + wrapTypes = [ + gl.REPEAT, + gl.CLAMP_TO_EDGE, + gl.MIRRORED_REPEAT + ] +} + +var convertFloatToUint8 = function(out, inp) { + ops.muls(out, inp, 255.0) +} + +function reshapeTexture(tex, w, h) { + var gl = tex.gl + var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(w < 0 || w > maxSize || h < 0 || h > maxSize) { + throw new Error('gl-texture2d: Invalid texture size') } + tex._shape = [w, h] + tex.bind() + gl.texImage2D(gl.TEXTURE_2D, 0, tex.format, w, h, 0, tex.format, tex.type, null) + tex._mipLevels = [0] + return tex } -//First item in list -Object.defineProperty(proto, "begin", { - get: function() { - var stack = [] - var n = this.root - while(n) { - stack.push(n) - n = n.left +function Texture2D(gl, handle, width, height, format, type) { + this.gl = gl + this.handle = handle + this.format = format + this.type = type + this._shape = [width, height] + this._mipLevels = [0] + this._magFilter = gl.NEAREST + this._minFilter = gl.NEAREST + this._wrapS = gl.CLAMP_TO_EDGE + this._wrapT = gl.CLAMP_TO_EDGE + this._anisoSamples = 1 + + var parent = this + var wrapVector = [this._wrapS, this._wrapT] + Object.defineProperties(wrapVector, [ + { + get: function() { + return parent._wrapS + }, + set: function(v) { + return parent.wrapS = v + } + }, + { + get: function() { + return parent._wrapT + }, + set: function(v) { + return parent.wrapT = v + } } - return new RedBlackTreeIterator(this, stack) - } -}) + ]) + this._wrapVector = wrapVector -//Last item in list -Object.defineProperty(proto, "end", { - get: function() { - var stack = [] - var n = this.root - while(n) { - stack.push(n) - n = n.right + var shapeVector = [this._shape[0], this._shape[1]] + Object.defineProperties(shapeVector, [ + { + get: function() { + return parent._shape[0] + }, + set: function(v) { + return parent.width = v + } + }, + { + get: function() { + return parent._shape[1] + }, + set: function(v) { + return parent.height = v + } } - return new RedBlackTreeIterator(this, stack) - } -}) + ]) + this._shapeVector = shapeVector +} -//Find the ith item in the tree -proto.at = function(idx) { - if(idx < 0) { - return new RedBlackTreeIterator(this, []) - } - var n = this.root - var stack = [] - while(true) { - stack.push(n) - if(n.left) { - if(idx < n.left._count) { - n = n.left - continue +var proto = Texture2D.prototype + +Object.defineProperties(proto, { + minFilter: { + get: function() { + return this._minFilter + }, + set: function(v) { + this.bind() + var gl = this.gl + if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { + if(!gl.getExtension('OES_texture_float_linear')) { + v = gl.NEAREST + } + } + if(filterTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown filter mode ' + v) + } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, v) + return this._minFilter = v + } + }, + magFilter: { + get: function() { + return this._magFilter + }, + set: function(v) { + this.bind() + var gl = this.gl + if(this.type === gl.FLOAT && linearTypes.indexOf(v) >= 0) { + if(!gl.getExtension('OES_texture_float_linear')) { + v = gl.NEAREST + } + } + if(filterTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown filter mode ' + v) + } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, v) + return this._magFilter = v + } + }, + mipSamples: { + get: function() { + return this._anisoSamples + }, + set: function(i) { + var psamples = this._anisoSamples + this._anisoSamples = Math.max(i, 1)|0 + if(psamples !== this._anisoSamples) { + var ext = gl.getExtension('EXT_texture_filter_anisotropic') + if(ext) { + this.gl.texParameterf(this.gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisoSamples) + } + } + return this._anisoSamples + } + }, + wrapS: { + get: function() { + return this._wrapS + }, + set: function(v) { + this.bind() + if(wrapTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) + } + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, v) + return this._wrapS = v + } + }, + wrapT: { + get: function() { + return this._wrapT + }, + set: function(v) { + this.bind() + if(wrapTypes.indexOf(v) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) } - idx -= n.left._count - } - if(!idx) { - return new RedBlackTreeIterator(this, stack) + this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, v) + return this._wrapT = v } - idx -= 1 - if(n.right) { - if(idx >= n.right._count) { - break + }, + wrap: { + get: function() { + return this._wrapVector + }, + set: function(v) { + if(!Array.isArray(v)) { + v = [v,v] } - n = n.right - } else { - break - } - } - return new RedBlackTreeIterator(this, []) -} + if(v.length !== 2) { + throw new Error('gl-texture2d: Must specify wrap mode for rows and columns') + } + for(var i=0; i<2; ++i) { + if(wrapTypes.indexOf(v[i]) < 0) { + throw new Error('gl-texture2d: Unknown wrap mode ' + v) + } + } + this._wrapS = v[0] + this._wrapT = v[1] -proto.ge = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d <= 0) { - last_ptr = stack.length + var gl = this.gl + this.bind() + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT) + + return v } - if(d <= 0) { - n = n.left - } else { - n = n.right + }, + shape: { + get: function() { + return this._shapeVector + }, + set: function(x) { + if(!Array.isArray(x)) { + x = [x|0,x|0] + } else { + if(x.length !== 2) { + throw new Error('gl-texture2d: Invalid texture shape') + } + } + reshapeTexture(this, x[0]|0, x[1]|0) + return [x[0]|0, x[1]|0] } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} - -proto.gt = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d < 0) { - last_ptr = stack.length + }, + width: { + get: function() { + return this._shape[0] + }, + set: function(w) { + w = w|0 + reshapeTexture(this, w, this._shape[1]) + return w } - if(d < 0) { - n = n.left - } else { - n = n.right + }, + height: { + get: function() { + return this._shape[1] + }, + set: function(h) { + h = h|0 + reshapeTexture(this, this._shape[0], h) + return h } } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) -} +}) -proto.lt = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d > 0) { - last_ptr = stack.length - } - if(d <= 0) { - n = n.left - } else { - n = n.right - } +proto.bind = function(unit) { + var gl = this.gl + if(unit !== undefined) { + gl.activeTexture(gl.TEXTURE0 + (unit|0)) } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) + gl.bindTexture(gl.TEXTURE_2D, this.handle) + if(unit !== undefined) { + return (unit|0) + } + return gl.getParameter(gl.ACTIVE_TEXTURE) - gl.TEXTURE0 } -proto.le = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - var last_ptr = 0 - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d >= 0) { - last_ptr = stack.length - } - if(d < 0) { - n = n.left - } else { - n = n.right - } - } - stack.length = last_ptr - return new RedBlackTreeIterator(this, stack) +proto.dispose = function() { + this.gl.deleteTexture(this.handle) } -//Finds the item with key if it exists -proto.find = function(key) { - var cmp = this._compare - var n = this.root - var stack = [] - while(n) { - var d = cmp(key, n.key) - stack.push(n) - if(d === 0) { - return new RedBlackTreeIterator(this, stack) - } - if(d <= 0) { - n = n.left - } else { - n = n.right +proto.generateMipmap = function() { + this.bind() + this.gl.generateMipmap(this.gl.TEXTURE_2D) + + //Update mip levels + var l = Math.min(this._shape[0], this._shape[1]) + for(var i=0; l>0; ++i, l>>>=1) { + if(this._mipLevels.indexOf(i) < 0) { + this._mipLevels.push(i) } } - return new RedBlackTreeIterator(this, []) } -//Removes item with key from tree -proto.remove = function(key) { - var iter = this.find(key) - if(iter) { - return iter.remove() +proto.setPixels = function(data, x_off, y_off, mip_level) { + var gl = this.gl + this.bind() + if(Array.isArray(x_off)) { + mip_level = y_off + y_off = x_off[1]|0 + x_off = x_off[0]|0 + } else { + x_off = x_off || 0 + y_off = y_off || 0 } - return this -} - -//Returns the item at `key` -proto.get = function(key) { - var cmp = this._compare - var n = this.root - while(n) { - var d = cmp(key, n.key) - if(d === 0) { - return n.value - } - if(d <= 0) { - n = n.left + mip_level = mip_level || 0 + if(data instanceof HTMLCanvasElement || + data instanceof ImageData || + data instanceof HTMLImageElement || + data instanceof HTMLVideoElement) { + var needsMip = this._mipLevels.indexOf(mip_level) < 0 + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, 0, this.format, this.format, this.type, data) + this._mipLevels.push(mip_level) } else { - n = n.right + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, this.format, this.type, data) + } + } else if(data.shape && data.stride && data.data) { + if(data.shape.length < 2 || + x_off + data.shape[1] > this._shape[1]>>>mip_level || + y_off + data.shape[0] > this._shape[0]>>>mip_level || + x_off < 0 || + y_off < 0) { + throw new Error('gl-texture2d: Texture dimensions are out of bounds') } + texSubImageArray(gl, x_off, y_off, mip_level, this.format, this.type, this._mipLevels, data) + } else { + throw new Error('gl-texture2d: Unsupported data type') } - return -} - -//Iterator for red black tree -function RedBlackTreeIterator(tree, stack) { - this.tree = tree - this._stack = stack } -var iproto = RedBlackTreeIterator.prototype -//Test if iterator is valid -Object.defineProperty(iproto, "valid", { - get: function() { - return this._stack.length > 0 +function isPacked(shape, stride) { + if(shape.length === 3) { + return (stride[2] === 1) && + (stride[1] === shape[0]*shape[2]) && + (stride[0] === shape[2]) } -}) - -//Node of the iterator -Object.defineProperty(iproto, "node", { - get: function() { - if(this._stack.length > 0) { - return this._stack[this._stack.length-1] - } - return null - }, - enumerable: true -}) - -//Makes a copy of an iterator -iproto.clone = function() { - return new RedBlackTreeIterator(this.tree, this._stack.slice()) -} - -//Swaps two nodes -function swapNode(n, v) { - n.key = v.key - n.value = v.value - n.left = v.left - n.right = v.right - n._color = v._color - n._count = v._count + return (stride[0] === 1) && + (stride[1] === shape[0]) } -//Fix up a double black node in a tree -function fixDoubleBlack(stack) { - var n, p, s, z - for(var i=stack.length-1; i>=0; --i) { - n = stack[i] - if(i === 0) { - n._color = BLACK - return - } - //console.log("visit node:", n.key, i, stack[i].key, stack[i-1].key) - p = stack[i-1] - if(p.left === n) { - //console.log("left child") - s = p.right - if(s.right && s.right._color === RED) { - //console.log("case 1: right sibling child red") - s = p.right = cloneNode(s) - z = s.right = cloneNode(s.right) - p.right = s.left - s.left = p - s.right = z - s._color = p._color - n._color = BLACK - p._color = BLACK - z._color = BLACK - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = s - } else { - pp.right = s - } - } - stack[i-1] = s - return - } else if(s.left && s.left._color === RED) { - //console.log("case 1: left sibling child red") - s = p.right = cloneNode(s) - z = s.left = cloneNode(s.left) - p.right = z.left - s.left = z.right - z.left = p - z.right = s - z._color = p._color - p._color = BLACK - s._color = BLACK - n._color = BLACK - recount(p) - recount(s) - recount(z) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = z - } else { - pp.right = z - } - } - stack[i-1] = z - return - } - if(s._color === BLACK) { - if(p._color === RED) { - //console.log("case 2: black sibling, red parent", p.right.value) - p._color = BLACK - p.right = repaint(RED, s) - return - } else { - //console.log("case 2: black sibling, black parent", p.right.value) - p.right = repaint(RED, s) - continue - } - } else { - //console.log("case 3: red sibling") - s = cloneNode(s) - p.right = s.left - s.left = p - s._color = p._color - p._color = RED - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.left === p) { - pp.left = s - } else { - pp.right = s - } - } - stack[i-1] = s - stack[i] = p - if(i+1 < stack.length) { - stack[i+1] = n - } else { - stack.push(n) - } - i = i+2 - } +function texSubImageArray(gl, x_off, y_off, mip_level, cformat, ctype, mipLevels, array) { + var dtype = array.dtype + var shape = array.shape.slice() + if(shape.length < 2 || shape.length > 3) { + throw new Error('gl-texture2d: Invalid ndarray, must be 2d or 3d') + } + var type = 0, format = 0 + var packed = isPacked(shape, array.stride.slice()) + if(dtype === 'float32') { + type = gl.FLOAT + } else if(dtype === 'float64') { + type = gl.FLOAT + packed = false + dtype = 'float32' + } else if(dtype === 'uint8') { + type = gl.UNSIGNED_BYTE + } else { + type = gl.UNSIGNED_BYTE + packed = false + dtype = 'uint8' + } + var channels = 1 + if(shape.length === 2) { + format = gl.LUMINANCE + shape = [shape[0], shape[1], 1] + array = ndarray(array.data, shape, [array.stride[0], array.stride[1], 1], array.offset) + } else if(shape.length === 3) { + if(shape[2] === 1) { + format = gl.ALPHA + } else if(shape[2] === 2) { + format = gl.LUMINANCE_ALPHA + } else if(shape[2] === 3) { + format = gl.RGB + } else if(shape[2] === 4) { + format = gl.RGBA } else { - //console.log("right child") - s = p.left - if(s.left && s.left._color === RED) { - //console.log("case 1: left sibling child red", p.value, p._color) - s = p.left = cloneNode(s) - z = s.left = cloneNode(s.left) - p.left = s.right - s.right = p - s.left = z - s._color = p._color - n._color = BLACK - p._color = BLACK - z._color = BLACK - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = s - } else { - pp.left = s - } - } - stack[i-1] = s - return - } else if(s.right && s.right._color === RED) { - //console.log("case 1: right sibling child red") - s = p.left = cloneNode(s) - z = s.right = cloneNode(s.right) - p.left = z.right - s.right = z.left - z.right = p - z.left = s - z._color = p._color - p._color = BLACK - s._color = BLACK - n._color = BLACK - recount(p) - recount(s) - recount(z) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = z - } else { - pp.left = z - } - } - stack[i-1] = z - return - } - if(s._color === BLACK) { - if(p._color === RED) { - //console.log("case 2: black sibling, red parent") - p._color = BLACK - p.left = repaint(RED, s) - return - } else { - //console.log("case 2: black sibling, black parent") - p.left = repaint(RED, s) - continue - } - } else { - //console.log("case 3: red sibling") - s = cloneNode(s) - p.left = s.right - s.right = p - s._color = p._color - p._color = RED - recount(p) - recount(s) - if(i > 1) { - var pp = stack[i-2] - if(pp.right === p) { - pp.right = s - } else { - pp.left = s - } - } - stack[i-1] = s - stack[i] = p - if(i+1 < stack.length) { - stack[i+1] = n - } else { - stack.push(n) - } - i = i+2 - } + throw new Error('gl-texture2d: Invalid shape for pixel coords') } + channels = shape[2] + } else { + throw new Error('gl-texture2d: Invalid shape for texture') + } + //For 1-channel textures allow conversion between formats + if((format === gl.LUMINANCE || format === gl.ALPHA) && + (cformat === gl.LUMINANCE || cformat === gl.ALPHA)) { + format = cformat } -} - -//Removes item at iterator from tree -iproto.remove = function() { - var stack = this._stack - if(stack.length === 0) { - return this.tree + if(format !== cformat) { + throw new Error('gl-texture2d: Incompatible texture format for setPixels') } - //First copy path to node - var cstack = new Array(stack.length) - var n = stack[stack.length-1] - cstack[cstack.length-1] = new RBNode(n._color, n.key, n.value, n.left, n.right, n._count) - for(var i=stack.length-2; i>=0; --i) { - var n = stack[i] - if(n.left === stack[i+1]) { - cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) + var size = array.size + var needsMip = mipLevels.indexOf(mip_level) < 0 + if(needsMip) { + mipLevels.push(mip_level) + } + if(type === ctype && packed) { + //Array data types are compatible, can directly copy into texture + if(array.offset === 0 && array.data.length === size) { + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data) + } } else { - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, array.data.subarray(array.offset, array.offset+size)) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, array.data.subarray(array.offset, array.offset+size)) + } + } + } else { + //Need to do type conversion to pack data into buffer + var pack_buffer + if(ctype === gl.FLOAT) { + pack_buffer = pool.mallocFloat32(size) + } else { + pack_buffer = pool.mallocUint8(size) + } + var pack_view = ndarray(pack_buffer, shape, [shape[2], shape[2]*shape[0], 1]) + if(type === gl.FLOAT && ctype === gl.UNSIGNED_BYTE) { + convertFloatToUint8(pack_view, array) + } else { + ops.assign(pack_view, array) + } + if(needsMip) { + gl.texImage2D(gl.TEXTURE_2D, mip_level, cformat, shape[0], shape[1], 0, cformat, ctype, pack_buffer.subarray(0, size)) + } else { + gl.texSubImage2D(gl.TEXTURE_2D, mip_level, x_off, y_off, shape[0], shape[1], cformat, ctype, pack_buffer.subarray(0, size)) + } + if(ctype === gl.FLOAT) { + pool.freeFloat32(pack_buffer) + } else { + pool.freeUint8(pack_buffer) } } +} - //Get node - n = cstack[cstack.length-1] - //console.log("start remove: ", n.value) +function initTexture(gl) { + var tex = gl.createTexture() + gl.bindTexture(gl.TEXTURE_2D, tex) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + return tex +} - //If not leaf, then swap with previous node - if(n.left && n.right) { - //console.log("moving to leaf") +function createTextureShape(gl, width, height, format, type) { + var maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(width < 0 || width > maxTextureSize || height < 0 || height > maxTextureSize) { + throw new Error('gl-texture2d: Invalid texture shape') + } + if(type === gl.FLOAT && !gl.getExtension('OES_texture_float')) { + throw new Error('gl-texture2d: Floating point textures not supported on this platform') + } + var tex = initTexture(gl) + gl.texImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, format, type, null) + return new Texture2D(gl, tex, width, height, format, type) +} - //First walk to previous leaf - var split = cstack.length - n = n.left - while(n.right) { - cstack.push(n) - n = n.right - } - //Copy path to leaf - var v = cstack[split-1] - cstack.push(new RBNode(n._color, v.key, v.value, n.left, n.right, n._count)) - cstack[split-1].key = n.key - cstack[split-1].value = n.value +function createTextureDOM(gl, element, format, type) { + var tex = initTexture(gl) + gl.texImage2D(gl.TEXTURE_2D, 0, format, format, type, element) + return new Texture2D(gl, tex, element.width|0, element.height|0, format, type) +} - //Fix up stack - for(var i=cstack.length-2; i>=split; --i) { - n = cstack[i] - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) - } - cstack[split-1].left = cstack[split] +//Creates a texture from an ndarray +function createTextureArray(gl, array) { + var dtype = array.dtype + var shape = array.shape.slice() + var maxSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) + if(shape[0] < 0 || shape[0] > maxSize || shape[1] < 0 || shape[1] > maxSize) { + throw new Error('gl-texture2d: Invalid texture size') } - //console.log("stack=", cstack.map(function(v) { return v.value })) - - //Remove leaf node - n = cstack[cstack.length-1] - if(n._color === RED) { - //Easy case: removing red leaf - //console.log("RED leaf") - var p = cstack[cstack.length-2] - if(p.left === n) { - p.left = null - } else if(p.right === n) { - p.right = null - } - cstack.pop() - for(var i=0; i 0) { - return this._stack[this._stack.length-1].key - } - return - }, - enumerable: true -}) - -//Returns value -Object.defineProperty(iproto, "value", { - get: function() { - if(this._stack.length > 0) { - return this._stack[this._stack.length-1].value +function createTexture2D(gl) { + if(arguments.length <= 1) { + throw new Error('gl-texture2d: Missing arguments for texture2d constructor') + } + if(!linearTypes) { + lazyInitLinearTypes(gl) + } + if(typeof arguments[1] === 'number') { + return createTextureShape(gl, arguments[1], arguments[2], arguments[3]||gl.RGBA, arguments[4]||gl.UNSIGNED_BYTE) + } + if(Array.isArray(arguments[1])) { + return createTextureShape(gl, arguments[1][0]|0, arguments[1][1]|0, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) + } + if(typeof arguments[1] === 'object') { + var obj = arguments[1] + if(obj instanceof HTMLCanvasElement || + obj instanceof HTMLImageElement || + obj instanceof HTMLVideoElement || + obj instanceof ImageData) { + return createTextureDOM(gl, obj, arguments[2]||gl.RGBA, arguments[3]||gl.UNSIGNED_BYTE) + } else if(obj.shape && obj.data && obj.stride) { + return createTextureArray(gl, obj) } - return - }, - enumerable: true -}) + } + throw new Error('gl-texture2d: Invalid arguments for texture2d constructor') +} +},{"ndarray":208,"ndarray-ops":207,"typedarray-pool":233}],186:[function(require,module,exports){ +"use strict" -//Returns the position of this iterator in the sorted list -Object.defineProperty(iproto, "index", { - get: function() { - var idx = 0 - var stack = this._stack - if(stack.length === 0) { - var r = this.tree.root - if(r) { - return r._count - } - return 0 - } else if(stack[stack.length-1].left) { - idx = stack[stack.length-1].left._count +function doBind(gl, elements, attributes) { + if(elements) { + elements.bind() + } else { + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) + } + var nattribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS)|0 + if(attributes) { + if(attributes.length > nattribs) { + throw new Error("gl-vao: Too many vertex attributes") } - for(var s=stack.length-2; s>=0; --s) { - if(stack[s+1] === stack[s].right) { - ++idx - if(stack[s].left) { - idx += stack[s].left._count + for(var i=0; i 0 && stack[stack.length-1].right === n) { - n = stack[stack.length-1] - stack.pop() + gl.bindBuffer(gl.ARRAY_BUFFER, null) + for(var i=0; i0; --s) { - if(stack[s-1].left === stack[s]) { - return true - } - } - return false - } -}) +module.exports = doBind +},{}],187:[function(require,module,exports){ +"use strict" -//Update value -iproto.update = function(value) { - var stack = this._stack - if(stack.length === 0) { - throw new Error("Can't update empty node!") - } - var cstack = new Array(stack.length) - var n = stack[stack.length-1] - cstack[cstack.length-1] = new RBNode(n._color, n.key, value, n.left, n.right, n._count) - for(var i=stack.length-2; i>=0; --i) { - n = stack[i] - if(n.left === stack[i+1]) { - cstack[i] = new RBNode(n._color, n.key, n.value, cstack[i+1], n.right, n._count) - } else { - cstack[i] = new RBNode(n._color, n.key, n.value, n.left, cstack[i+1], n._count) - } +var bindAttribs = require("./do-bind.js") + +function VAOEmulated(gl) { + this.gl = gl + this._elements = null + this._attributes = null + this._elementsType = gl.UNSIGNED_SHORT +} + +VAOEmulated.prototype.bind = function() { + bindAttribs(this.gl, this._elements, this._attributes) +} + +VAOEmulated.prototype.update = function(attributes, elements, elementsType) { + this._elements = elements + this._attributes = attributes + this._elementsType = elementsType || this.gl.UNSIGNED_SHORT +} + +VAOEmulated.prototype.dispose = function() { } +VAOEmulated.prototype.unbind = function() { } + +VAOEmulated.prototype.draw = function(mode, count, offset) { + offset = offset || 0 + var gl = this.gl + if(this._elements) { + gl.drawElements(mode, count, this._elementsType, offset) + } else { + gl.drawArrays(mode, offset, count) } - return new RedBlackTree(this.tree._compare, cstack[0]) } -//Moves iterator backward one element -iproto.prev = function() { - var stack = this._stack - if(stack.length === 0) { - return +function createVAOEmulated(gl) { + return new VAOEmulated(gl) +} + +module.exports = createVAOEmulated +},{"./do-bind.js":186}],188:[function(require,module,exports){ +"use strict" + +var bindAttribs = require("./do-bind.js") + +function VertexAttribute(location, dimension, a, b, c, d) { + this.location = location + this.dimension = dimension + this.a = a + this.b = b + this.c = c + this.d = d +} + +VertexAttribute.prototype.bind = function(gl) { + switch(this.dimension) { + case 1: + gl.vertexAttrib1f(this.location, this.a) + break + case 2: + gl.vertexAttrib2f(this.location, this.a, this.b) + break + case 3: + gl.vertexAttrib3f(this.location, this.a, this.b, this.c) + break + case 4: + gl.vertexAttrib4f(this.location, this.a, this.b, this.c, this.d) + break } - var n = stack[stack.length-1] - if(n.left) { - n = n.left - while(n) { - stack.push(n) - n = n.right - } - } else { - stack.pop() - while(stack.length > 0 && stack[stack.length-1].left === n) { - n = stack[stack.length-1] - stack.pop() - } +} + +function VAONative(gl, ext, handle) { + this.gl = gl + this._ext = ext + this.handle = handle + this._attribs = [] + this._useElements = false + this._elementsType = gl.UNSIGNED_SHORT +} + +VAONative.prototype.bind = function() { + this._ext.bindVertexArrayOES(this.handle) + for(var i=0; i0; --s) { - if(stack[s-1].right === stack[s]) { - return true - } +VAONative.prototype.unbind = function() { + this._ext.bindVertexArrayOES(null) +} + +VAONative.prototype.dispose = function() { + this._ext.deleteVertexArrayOES(this.handle) +} + +VAONative.prototype.update = function(attributes, elements, elementsType) { + this.bind() + bindAttribs(this.gl, elements, attributes) + this.unbind() + this._attribs.length = 0 + if(attributes) + for(var i=0; i b) { - return 1 +} + +function createVAONative(gl, ext) { + return new VAONative(gl, ext, ext.createVertexArrayOES()) +} + +module.exports = createVAONative +},{"./do-bind.js":186}],189:[function(require,module,exports){ +"use strict" + +var createVAONative = require("./lib/vao-native.js") +var createVAOEmulated = require("./lib/vao-emulated.js") + +function createVAO(gl, attributes, elements, elementsType) { + var ext = gl.getExtension('OES_vertex_array_object') + var vao + if(ext) { + vao = createVAONative(gl, ext) + } else { + vao = createVAOEmulated(gl) } - return 0 + vao.update(attributes, elements, elementsType) + return vao } -//Build a tree -function createRBTree(compare) { - return new RedBlackTree(compare || defaultCompare, null) +module.exports = createVAO + +},{"./lib/vao-emulated.js":187,"./lib/vao-native.js":188}],190:[function(require,module,exports){ +module.exports = transformMat4 + +/** + * Transforms the vec4 with a mat4. + * + * @param {vec4} out the receiving vector + * @param {vec4} a the vector to transform + * @param {mat4} m matrix to transform with + * @returns {vec4} out + */ +function transformMat4 (out, a, m) { + var x = a[0], y = a[1], z = a[2], w = a[3] + out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w + out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w + out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w + out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w + return out } -},{}],388:[function(require,module,exports){ + +},{}],191:[function(require,module,exports){ "use strict" -module.exports = createSlabDecomposition +//High level idea: +// 1. Use Clarkson's incremental construction to find convex hull +// 2. Point location in triangulation by jump and walk + +module.exports = incrementalConvexHull -var bounds = require("binary-search-bounds") -var createRBTree = require("functional-red-black-tree") var orient = require("robust-orientation") -var orderSegments = require("./lib/order-segments") +var compareCell = require("simplicial-complex").compareCells -function SlabDecomposition(slabs, coordinates, horizontal) { - this.slabs = slabs - this.coordinates = coordinates - this.horizontal = horizontal +function compareInt(a, b) { + return a - b } -var proto = SlabDecomposition.prototype +function Simplex(vertices, adjacent, boundary) { + this.vertices = vertices + this.adjacent = adjacent + this.boundary = boundary + this.lastVisited = -1 +} -function compareHorizontal(e, y) { - return e.y - y +Simplex.prototype.flip = function() { + var t = this.vertices[0] + this.vertices[0] = this.vertices[1] + this.vertices[1] = t + var u = this.adjacent[0] + this.adjacent[0] = this.adjacent[1] + this.adjacent[1] = u } -function searchBucket(root, p) { - var lastNode = null - while(root) { - var seg = root.key - var l, r - if(seg[0][0] < seg[1][0]) { - l = seg[0] - r = seg[1] - } else { - l = seg[1] - r = seg[0] - } - var o = orient(l, r, p) - if(o < 0) { - root = root.left - } else if(o > 0) { - if(p[0] !== seg[1][0]) { - lastNode = root - root = root.right - } else { - var val = searchBucket(root.right, p) - if(val) { - return val - } - root = root.left - } - } else { - if(p[0] !== seg[1][0]) { - return root - } else { - var val = searchBucket(root.right, p) - if(val) { - return val - } - root = root.left - } +function GlueFacet(vertices, cell, index) { + this.vertices = vertices + this.cell = cell + this.index = index +} + +function compareGlue(a, b) { + return compareCell(a.vertices, b.vertices) +} + +function bakeOrient(d) { + var code = ["function orient(){var tuple=this.tuple;return test("] + for(var i=0; i<=d; ++i) { + if(i > 0) { + code.push(",") } + code.push("tuple[", i, "]") } - return lastNode + code.push(")}return orient") + var proc = new Function("test", code.join("")) + var test = orient[d+1] + if(!test) { + test = orient + } + return proc(test) } -proto.castUp = function(p) { - var bucket = bounds.le(this.coordinates, p[0]) - if(bucket < 0) { - return -1 +var BAKED = [] + +function Triangulation(dimension, vertices, simplices) { + this.dimension = dimension + this.vertices = vertices + this.simplices = simplices + this.interior = simplices.filter(function(c) { + return !c.boundary + }) + + this.tuple = new Array(dimension+1) + for(var i=0; i<=dimension; ++i) { + this.tuple[i] = this.vertices[i] } - var root = this.slabs[bucket] - var hitNode = searchBucket(this.slabs[bucket], p) - var lastHit = -1 - if(hitNode) { - lastHit = hitNode.value + + var o = BAKED[dimension] + if(!o) { + o = BAKED[dimension] = bakeOrient(dimension) } - //Edge case: need to handle horizontal segments (sucks) - if(this.coordinates[bucket] === p[0]) { - var lastSegment = null - if(hitNode) { - lastSegment = hitNode.key - } - if(bucket > 0) { - var otherHitNode = searchBucket(this.slabs[bucket-1], p) - if(otherHitNode) { - if(lastSegment) { - if(orderSegments(otherHitNode.key, lastSegment) > 0) { - lastSegment = otherHitNode.key - lastHit = otherHitNode.value - } + this.orient = o +} + +var proto = Triangulation.prototype + +//Degenerate situation where we are on boundary, but coplanar to face +proto.handleBoundaryDegeneracy = function(cell, point) { + var d = this.dimension + var n = this.vertices.length - 1 + var tuple = this.tuple + var verts = this.vertices + + //Dumb solution: Just do dfs from boundary cell until we find any peak, or terminate + var toVisit = [ cell ] + cell.lastVisited = -n + while(toVisit.length > 0) { + cell = toVisit.pop() + var cellVerts = cell.vertices + var cellAdj = cell.adjacent + for(var i=0; i<=d; ++i) { + var neighbor = cellAdj[i] + if(!neighbor.boundary || neighbor.lastVisited <= -n) { + continue + } + var nv = neighbor.vertices + for(var j=0; j<=d; ++j) { + var vv = nv[j] + if(vv < 0) { + tuple[j] = point } else { - lastHit = otherHitNode.value - lastSegment = otherHitNode.key + tuple[j] = verts[vv] } } - } - var horiz = this.horizontal[bucket] - if(horiz.length > 0) { - var hbucket = bounds.ge(horiz, p[1], compareHorizontal) - if(hbucket < horiz.length) { - var e = horiz[hbucket] - if(p[1] === e.y) { - if(e.closed) { - return e.index - } else { - while(hbucket < horiz.length-1 && horiz[hbucket+1].y === p[1]) { - hbucket = hbucket+1 - e = horiz[hbucket] - if(e.closed) { - return e.index - } - } - if(e.y === p[1] && !e.start) { - hbucket = hbucket+1 - if(hbucket >= horiz.length) { - return lastHit - } - e = horiz[hbucket] - } - } - } - //Check if e is above/below last segment - if(e.start) { - if(lastSegment) { - var o = orient(lastSegment[0], lastSegment[1], [p[0], e.y]) - if(lastSegment[0][0] > lastSegment[1][0]) { - o = -o - } - if(o > 0) { - lastHit = e.index - } - } else { - lastHit = e.index - } - } else if(e.y !== p[1]) { - lastHit = e.index - } + var o = this.orient() + if(o > 0) { + return neighbor + } + neighbor.lastVisited = -n + if(o === 0) { + toVisit.push(neighbor) } } } - return lastHit + return null } -function IntervalSegment(y, index, start, closed) { - this.y = y - this.index = index - this.start = start - this.closed = closed -} +proto.walk = function(point, random) { + //Alias local properties + var n = this.vertices.length - 1 + var d = this.dimension + var verts = this.vertices + var tuple = this.tuple -function Event(x, segment, create, index) { - this.x = x - this.segment = segment - this.create = create - this.index = index -} + //Compute initial jump cell + var initIndex = random ? (this.interior.length * Math.random())|0 : (this.interior.length-1) + var cell = this.interior[ initIndex ] + //Start walking +outerLoop: + while(!cell.boundary) { + var cellVerts = cell.vertices + var cellAdj = cell.adjacent -function createSlabDecomposition(segments) { - var numSegments = segments.length - var numEvents = 2 * numSegments - var events = new Array(numEvents) - for(var i=0; i= n) { + continue } - i += 1 - if(e.segment[0][0] === e.x && e.segment[1][0] === e.x) { - if(e.create) { - if(e.segment[0][1] < e.segment[1][1]) { - horiz.push(new IntervalSegment( - e.segment[0][1], - e.index, - true, - true)) - horiz.push(new IntervalSegment( - e.segment[1][1], - e.index, - false, - false)) - } else { - horiz.push(new IntervalSegment( - e.segment[1][1], - e.index, - true, - false)) - horiz.push(new IntervalSegment( - e.segment[0][1], - e.index, - false, - true)) - } - } + var prev = tuple[i] + tuple[i] = point + var o = this.orient() + tuple[i] = prev + if(o < 0) { + cell = neighbor + continue outerLoop } else { - if(e.create) { - tree = tree.insert(e.segment, e.index) + if(!neighbor.boundary) { + neighbor.lastVisited = n } else { - tree = tree.remove(e.segment) + neighbor.lastVisited = -n } } } - slabs.push(tree.root) - lines.push(x) - horizontal.push(horiz) + return } - return new SlabDecomposition(slabs, lines, horizontal) + + return cell } -},{"./lib/order-segments":386,"binary-search-bounds":384,"functional-red-black-tree":387,"robust-orientation":996}],389:[function(require,module,exports){ -module.exports = preprocessPolygon -var orient = require('robust-orientation')[3] -var makeSlabs = require('slab-decomposition') -var makeIntervalTree = require('interval-tree-1d') -var bsearch = require('binary-search-bounds') +proto.addPeaks = function(point, cell) { + var n = this.vertices.length - 1 + var d = this.dimension + var verts = this.vertices + var tuple = this.tuple + var interior = this.interior + var simplices = this.simplices -function visitInterval() { - return true -} + //Walking finished at boundary, time to add peaks + var tovisit = [ cell ] -function intervalSearch(table) { - return function(x, y) { - var tree = table[x] - if(tree) { - return !!tree.queryPoint(y, visitInterval) - } - return false - } -} + //Stretch initial boundary cell into a peak + cell.lastVisited = n + cell.vertices[cell.vertices.indexOf(-1)] = n + cell.boundary = false + interior.push(cell) -function buildVerticalIndex(segments) { - var table = {} - for(var i=0; i 0) { + //Pop off peak and walk over adjacent cells + var cell = tovisit.pop() + var cellVerts = cell.vertices + var cellAdj = cell.adjacent + var indexOfN = cellVerts.indexOf(n) + if(indexOfN < 0) { + continue } - var root = slabs[bucket] - if(!root) { - if(bucket > 0 && coordinates[bucket] === p[0]) { - root = slabs[bucket-1] - } else { - return 1 + + for(var i=0; i<=d; ++i) { + if(i === indexOfN) { + continue } - } - var lastOrientation = 1 - while(root) { - var s = root.key - var o = orient(p, s[0], s[1]) - if(s[0][0] < s[1][0]) { - if(o < 0) { - root = root.left - } else if(o > 0) { - lastOrientation = -1 - root = root.right - } else { - return 0 + + //For each boundary neighbor of the cell + var neighbor = cellAdj[i] + if(!neighbor.boundary || neighbor.lastVisited >= n) { + continue + } + + var nv = neighbor.vertices + + //Test if neighbor is a peak + if(neighbor.lastVisited !== -n) { + //Compute orientation of p relative to each boundary peak + var indexOfNeg1 = 0 + for(var j=0; j<=d; ++j) { + if(nv[j] < 0) { + indexOfNeg1 = j + tuple[j] = point + } else { + tuple[j] = verts[nv[j]] + } } - } else { + var o = this.orient() + + //Test if neighbor cell is also a peak if(o > 0) { - root = root.left - } else if(o < 0) { - lastOrientation = 1 - root = root.right + nv[indexOfNeg1] = n + neighbor.boundary = false + interior.push(neighbor) + tovisit.push(neighbor) + neighbor.lastVisited = n + continue } else { - return 0 + neighbor.lastVisited = -n } } - } - return lastOrientation - } -} -function classifyEmpty(p) { - return 1 -} + var na = neighbor.adjacent -function createClassifyVertical(testVertical) { - return function classify(p) { - if(testVertical(p[0], p[1])) { - return 0 - } - return 1 - } -} + //Otherwise, replace neighbor with new face + var vverts = cellVerts.slice() + var vadj = cellAdj.slice() + var ncell = new Simplex(vverts, vadj, true) + simplices.push(ncell) -function createClassifyPointDegen(testVertical, testNormal) { - return function classify(p) { - if(testVertical(p[0], p[1])) { - return 0 - } - return testNormal(p) - } -} + //Connect to neighbor + var opposite = na.indexOf(cell) + if(opposite < 0) { + continue + } + na[opposite] = ncell + vadj[indexOfN] = neighbor -function preprocessPolygon(loops) { - //Compute number of loops - var numLoops = loops.length + //Connect to cell + vverts[i] = -1 + vadj[i] = cell + cellAdj[i] = ncell - //Unpack segments - var segments = [] - var vsegments = [] - var ptr = 0 - for(var i=0; i 0 } - //Extract all clockwise faces - faces = faces.filter(ccw) + //Add peaks + this.addPeaks(point, cell) +} - //Detect which loops are contained in one another to handle parent-of relation - var numFaces = faces.length - var parent = new Array(numFaces) - var containment = new Array(numFaces) - for(var i=0; i= 0) { + bcell[ptr++] = cv[j] + } else { + parity = j&1 } } - row[j] = 1 - count += 1 - } - containment[i] = [count, i, row] - } - containment.sort(function(a,b) { - return b[0] - a[0] - }) - for(var i=0; i 0) { - var top = toVisit.pop() - var nbhd = fadj[top] - uniq(nbhd, function(a,b) { - return a-b - }) - var nnbhr = nbhd.length - var p = parity[top] - var polyline - if(p === 0) { - var c = faces[top] - polyline = [c] + //Create initial topological index, glue pointers together (kind of messy) + var initialCell = new Simplex(initialCoords, new Array(d+1), false) + var boundary = initialCell.adjacent + var list = new Array(d+2) + for(var i=0; i<=d; ++i) { + var verts = initialCoords.slice() + for(var j=0; j<=d; ++j) { + if(j === i) { + verts[j] = -1 + } } - for(var i=0; i= 0) { + var t = verts[0] + verts[0] = verts[1] + verts[1] = t + var cell = new Simplex(verts, new Array(d+1), true) + boundary[i] = cell + list[i] = cell + } + list[d+1] = initialCell + for(var i=0; i<=d; ++i) { + var verts = boundary[i].vertices + var adj = boundary[i].adjacent + for(var j=0; j<=d; ++j) { + var v = verts[j] + if(v < 0) { + adj[j] = initialCell continue } - parity[f] = p^1 - toVisit.push(f) - if(p === 0) { - var c = faces[f] - if(!sharedBoundary(c)) { - c.reverse() - polyline.push(c) + for(var k=0; k<=d; ++k) { + if(boundary[k].vertices.indexOf(v) < 0) { + adj[j] = boundary[k] } } } - if(p === 0) { - result.push(polyline) - } } - return result + //Initialize triangles + var triangles = new Triangulation(d, initialSimplex, list) + + //Insert remaining points + var useRandom = !!randomSearch + for(var i=d+1; i> 1 +//Finds a cell in a normalized cell complex +function findCell(cells, c) { + var lo = 0 + , hi = cells.length-1 + , r = -1 + while (lo <= hi) { + var mid = (lo + hi) >> 1 + , s = compareCells(cells[mid], c) + if(s <= 0) { + if(s === 0) { + r = mid + } + lo = mid + 1 + } else if(s > 0) { + hi = mid - 1 } - return (i >> 1) - 1 } + return r +} +exports.findCell = findCell; - //Bubble element i down the heap - function heapDown(i) { - var w = heapWeight(i) - while(true) { - var tw = w - var left = 2*i + 1 - var right = 2*(i + 1) - var next = i - if(left < heapCount) { - var lw = heapWeight(left) - if(lw < tw) { - next = left - tw = lw - } - } - if(right < heapCount) { - var rw = heapWeight(right) - if(rw < tw) { - next = right +//Builds an index for an n-cell. This is more general than dual, but less efficient +function incidence(from_cells, to_cells) { + var index = new Array(from_cells.length) + for(var i=0, il=index.length; i 0) { - var parent = heapParent(i) - if(parent >= 0) { - var pw = heapWeight(parent) - if(w < pw) { - heapSwap(i, parent) - i = parent - continue + while(true) { + index[idx++].push(i) + if(idx >= from_cells.length || compareCells(from_cells[idx], b) !== 0) { + break } } - return i } } + return index +} +exports.incidence = incidence - //Pop minimum element - function heapPop() { - if(heapCount > 0) { - var head = heap[0] - heapSwap(0, heapCount-1) - heapCount -= 1 - heapDown(0) - return head +//Computes the dual of the mesh. This is basically an optimized version of buildIndex for the situation where from_cells is just the list of vertices +function dual(cells, vertex_count) { + if(!vertex_count) { + return incidence(unique(skeleton(cells, 0)), cells, 0) + } + var res = new Array(vertex_count) + for(var i=0; i>> k) & 1) { + b.push(c[k]) + } + } + result.push(b) } - weights[a] = -Infinity - heapUp(i) - heapPop() - weights[a] = w - heapCount += 1 - return heapUp(heapCount-1) } + return normalize(result) +} +exports.explode = explode - //Kills a vertex (assume vertex already removed from heap) - function kill(i) { - if(dead[i]) { - return - } - //Kill vertex - dead[i] = true - //Fixup topology - var s = inv[i] - var t = outv[i] - if(inv[t] >= 0) { - inv[t] = s - } - if(outv[s] >= 0) { - outv[s] = t +//Enumerates all of the n-cells of a cell complex +function skeleton(cells, n) { + if(n < 0) { + return [] + } + var result = [] + , k0 = (1<<(n+1))-1 + for(var i=0; i= 0) { - heapUpdate(index[s], computeWeight(s)) - } - if(index[t] >= 0) { - heapUpdate(index[t], computeWeight(t)) +//Computes the boundary of all cells, does not remove duplicates +function boundary(cells) { + var res = [] + for(var i=0,il=cells.length; i>1; i>=0; --i) { - heapDown(i) - } - - //Kill vertices - while(true) { - var hmin = heapPop() - if((hmin < 0) || (weights[hmin] > minArea)) { - break - } - kill(hmin) + var components = [] + , component_labels = labels.ranks + for(var i=0; i= 0 && tout >= 0 && tin !== tout) { - var cin = index[tin] - var cout = index[tout] - if(cin !== cout) { - ncells.push([ cin, cout ]) - } + var components = [] + , component_labels = labels.ranks + for(var i=0; i 0) { - stepVal.push(stride(i, order[j-1]) + "*" + shape(order[j-1]) ) - } - vars.push(step(i,order[j]) + "=(" + stepVal.join("-") + ")|0") + if('ctrlKey' in ev) { + changed = changed || ev.ctrlKey !== mods.control + mods.control = !!ev.ctrlKey } + if('metaKey' in ev) { + changed = changed || ev.metaKey !== mods.meta + mods.meta = !!ev.metaKey + } + return changed } - //Create index variables - for(var i=0; i=0; --i) { - sizeVariable.push(shape(order[i])) - } - //Previous phases and vertex_ids - vars.push(POOL_SIZE + "=(" + sizeVariable.join("*") + ")|0", - PHASES + "=mallocUint32(" + POOL_SIZE + ")", - VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")", - POINTER + "=0") - //Create cube variables for phases - vars.push(pcube(0) + "=0") - for(var j=1; j<(1<=0; --i) { - forLoopBegin(i, 0) - } - var phaseFuncArgs = [] - for(var i=0; i0; k=(k-1)&subset) { - faceArgs.push(VERTEX_IDS + "[" + POINTER + "+" + pdelta(k) + "]") - } - faceArgs.push(vert(0)) - for(var k=0; k 0) { + return 1<<(b-1) + } + } else if('button' in ev) { + var b = ev.button + if(b === 1) { + return 4 + } else if(b === 2) { + return 2 + } else if(b >= 0) { + return 1<0){", - index(order[i]), "=1;") - createLoop(i-1, mask|(1< 0") - } - if(typeof args.vertex !== "function") { - error("Must specify vertex creation function") - } - if(typeof args.cell !== "function") { - error("Must specify cell creation function") - } - if(typeof args.phase !== "function") { - error("Must specify phase function") - } - var getters = args.getters || [] - var typesig = new Array(arrays) - for(var i=0; i= 0) { - typesig[i] = true - } else { - typesig[i] = false - } - } - return compileSurfaceProcedure( - args.vertex, - args.cell, - args.phase, - scalars, - order, - typesig) +module.exports = function(array, f) { + fill(array, f) + return array } -},{"typedarray-pool":401}],399:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],400:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],401:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":399,"buffer":48,"dup":102}],402:[function(require,module,exports){ -// transliterated from the python snippet here: -// http://en.wikipedia.org/wiki/Lanczos_approximation -var g = 7; -var p = [ - 0.99999999999980993, - 676.5203681218851, - -1259.1392167224028, - 771.32342877765313, - -176.61502916214059, - 12.507343278686905, - -0.13857109526572012, - 9.9843695780195716e-6, - 1.5056327351493116e-7 -]; +},{"cwise/lib/wrapper":69}],202:[function(require,module,exports){ +'use strict' -var g_ln = 607/128; -var p_ln = [ - 0.99999999999999709182, - 57.156235665862923517, - -59.597960355475491248, - 14.136097974741747174, - -0.49191381609762019978, - 0.33994649984811888699e-4, - 0.46523628927048575665e-4, - -0.98374475304879564677e-4, - 0.15808870322491248884e-3, - -0.21026444172410488319e-3, - 0.21743961811521264320e-3, - -0.16431810653676389022e-3, - 0.84418223983852743293e-4, - -0.26190838401581408670e-4, - 0.36899182659531622704e-5 -]; +module.exports = invert -// Spouge approximation (suitable for large arguments) -function lngamma(z) { +var invert2 = require('gl-mat2/invert') +var invert3 = require('gl-mat3/invert') +var invert4 = require('gl-mat4/invert') - if(z < 0) return Number('0/0'); - var x = p_ln[0]; - for(var i = p_ln.length - 1; i > 0; --i) x += p_ln[i] / (z + i); - var t = z + g_ln + 0.5; - return .5*Math.log(2*Math.PI)+(z+.5)*Math.log(t)-t+Math.log(x)-Math.log(z); +function invert(out, M) { + switch(M.length) { + case 0: + break + case 1: + out[0] = 1.0 / M[0] + break + case 4: + invert2(out, M) + break + case 9: + invert3(out, M) + break + case 16: + invert4(out, M) + break + default: + throw new Error('currently supports matrices up to 4x4') + break + } + return out } +},{"gl-mat2/invert":203,"gl-mat3/invert":87,"gl-mat4/invert":94}],203:[function(require,module,exports){ +module.exports = invert -module.exports = function gamma (z) { - if (z < 0.5) { - return Math.PI / (Math.sin(Math.PI * z) * gamma(1 - z)); - } - else if(z > 100) return Math.exp(lngamma(z)); - else { - z -= 1; - var x = p[0]; - for (var i = 1; i < g + 2; i++) { - x += p[i] / (z + i); - } - var t = z + g + 0.5; +/** + * Inverts a mat2 + * + * @alias mat2.invert + * @param {mat2} out the receiving matrix + * @param {mat2} a the source matrix + * @returns {mat2} out + */ +function invert(out, a) { + var a0 = a[0] + var a1 = a[1] + var a2 = a[2] + var a3 = a[3] + var det = a0 * a3 - a2 * a1 - return Math.sqrt(2 * Math.PI) - * Math.pow(t, z + 0.5) - * Math.exp(-t) - * x - ; - } -}; + if (!det) return null + det = 1.0 / det -module.exports.log = lngamma; + out[0] = a3 * det + out[1] = -a1 * det + out[2] = -a2 * det + out[3] = a0 * det + + return out +} -},{}],403:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],404:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],405:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":403,"buffer":48,"dup":102}],406:[function(require,module,exports){ +},{}],204:[function(require,module,exports){ "use strict" -module.exports = permutationSign +function interp1d(arr, x) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , w0 = s0 ? +arr.get(ix) : 0.0 + , w1 = s1 ? +arr.get(ix+1) : 0.0 + return (1.0-fx)*w0 + fx*w1 +} -var BRUTE_FORCE_CUTOFF = 32 +function interp2d(arr, x, y) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , iy = Math.floor(y) + , fy = y - iy + , t0 = 0 <= iy && iy < arr.shape[1] + , t1 = 0 <= iy+1 && iy+1 < arr.shape[1] + , w00 = s0&&t0 ? arr.get(ix ,iy ) : 0.0 + , w01 = s0&&t1 ? arr.get(ix ,iy+1) : 0.0 + , w10 = s1&&t0 ? arr.get(ix+1,iy ) : 0.0 + , w11 = s1&&t1 ? arr.get(ix+1,iy+1) : 0.0 + return (1.0-fy) * ((1.0-fx)*w00 + fx*w10) + fy * ((1.0-fx)*w01 + fx*w11) +} -var pool = require("typedarray-pool") +function interp3d(arr, x, y, z) { + var ix = Math.floor(x) + , fx = x - ix + , s0 = 0 <= ix && ix < arr.shape[0] + , s1 = 0 <= ix+1 && ix+1 < arr.shape[0] + , iy = Math.floor(y) + , fy = y - iy + , t0 = 0 <= iy && iy < arr.shape[1] + , t1 = 0 <= iy+1 && iy+1 < arr.shape[1] + , iz = Math.floor(z) + , fz = z - iz + , u0 = 0 <= iz && iz < arr.shape[2] + , u1 = 0 <= iz+1 && iz+1 < arr.shape[2] + , w000 = s0&&t0&&u0 ? arr.get(ix,iy,iz) : 0.0 + , w010 = s0&&t1&&u0 ? arr.get(ix,iy+1,iz) : 0.0 + , w100 = s1&&t0&&u0 ? arr.get(ix+1,iy,iz) : 0.0 + , w110 = s1&&t1&&u0 ? arr.get(ix+1,iy+1,iz) : 0.0 + , w001 = s0&&t0&&u1 ? arr.get(ix,iy,iz+1) : 0.0 + , w011 = s0&&t1&&u1 ? arr.get(ix,iy+1,iz+1) : 0.0 + , w101 = s1&&t0&&u1 ? arr.get(ix+1,iy,iz+1) : 0.0 + , w111 = s1&&t1&&u1 ? arr.get(ix+1,iy+1,iz+1) : 0.0 + return (1.0-fz) * ((1.0-fy) * ((1.0-fx)*w000 + fx*w100) + fy * ((1.0-fx)*w010 + fx*w110)) + fz * ((1.0-fy) * ((1.0-fx)*w001 + fx*w101) + fy * ((1.0-fx)*w011 + fx*w111)) +} -function permutationSign(p) { - var n = p.length - if(n < BRUTE_FORCE_CUTOFF) { - //Use quadratic algorithm for small n - var sgn = 1 - for(var i=0; i0; --i) { - t = pinv[i] - s = p[i] - p[i] = p[t] - p[t] = s - pinv[i] = pinv[s] - pinv[s] = t - r = (r + s) * i + r += w * arr.data[idx] } - pool.freeUint32(pinv) - pool.freeUint32(p) return r } -function unrank(n, r, p) { - switch(n) { +function interpolate(arr, x, y, z) { + switch(arr.shape.length) { case 0: - if(p) { return p } - return [] + return 0.0 case 1: - if(p) { - p[0] = 0 - return p - } else { - return [0] - } + return interp1d(arr, x) case 2: - if(p) { - if(r) { - p[0] = 0 - p[1] = 1 - } else { - p[0] = 1 - p[1] = 0 - } - return p - } else { - return r ? [0,1] : [1,0] - } + return interp2d(arr, x, y) + case 3: + return interp3d(arr, x, y, z) default: - break - } - p = p || new Array(n) - var s, t, i, nf=1 - p[0] = 0 - for(i=1; i0; --i) { - s = (r / nf)|0 - r = (r - s * nf)|0 - nf = (nf / i)|0 - t = p[i]|0 - p[i] = p[s]|0 - p[s] = t|0 + return interpNd.apply(undefined, arguments) } - return p } +module.exports = interpolate +module.exports.d1 = interp1d +module.exports.d2 = interp2d +module.exports.d3 = interp3d -exports.rank = rank -exports.unrank = unrank - -},{"invert-permutation":408,"typedarray-pool":411}],408:[function(require,module,exports){ -"use strict" +},{}],205:[function(require,module,exports){ +'use strict' -function invertPermutation(pi, result) { - result = result || new Array(pi.length) - for(var i=0; i= 0) !== (_inline_1_db >= 0)) {\n _inline_1_arg2_.push(_inline_1_arg4_[0] + 0.5 + 0.5 * (_inline_1_da + _inline_1_db) / (_inline_1_da - _inline_1_db))\n }\n }", - "args": [{ - "name": "_inline_1_arg0_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg1_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg2_", - "lvalue": false, - "rvalue": true, - "count": 1 - }, { - "name": "_inline_1_arg3_", - "lvalue": false, - "rvalue": true, - "count": 2 - }, { - "name": "_inline_1_arg4_", - "lvalue": false, - "rvalue": true, - "count": 1 - }], - "thisVars": [], - "localVars": ["_inline_1_da", "_inline_1_db"] - }, - funcName: 'zeroCrossings' -}) +var do_warp_2 = require('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_25_arg2_(this_warped,_inline_25_arg0_),_inline_25_arg1_=_inline_25_arg3_(_inline_25_arg4_,this_warped[0],this_warped[1])}","args":[{"name":"_inline_25_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_25_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_25_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_25_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_25_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp2D","blockSize":64}) -},{"cwise-compiler":414}],414:[function(require,module,exports){ -arguments[4][290][0].apply(exports,arguments) -},{"./lib/thunk.js":416,"dup":290}],415:[function(require,module,exports){ -arguments[4][291][0].apply(exports,arguments) -},{"dup":291,"uniq":417}],416:[function(require,module,exports){ -arguments[4][292][0].apply(exports,arguments) -},{"./compile.js":415,"dup":292}],417:[function(require,module,exports){ -arguments[4][69][0].apply(exports,arguments) -},{"dup":69}],418:[function(require,module,exports){ -"use strict" +var do_warp_3 = require('cwise/lib/wrapper')({"args":["index","array","scalar","scalar","scalar"],"pre":{"body":"{this_warped=[0,0,0]}","args":[],"thisVars":["this_warped"],"localVars":[]},"body":{"body":"{_inline_28_arg2_(this_warped,_inline_28_arg0_),_inline_28_arg1_=_inline_28_arg3_(_inline_28_arg4_,this_warped[0],this_warped[1],this_warped[2])}","args":[{"name":"_inline_28_arg0_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_28_arg1_","lvalue":true,"rvalue":false,"count":1},{"name":"_inline_28_arg2_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_28_arg3_","lvalue":false,"rvalue":true,"count":1},{"name":"_inline_28_arg4_","lvalue":false,"rvalue":true,"count":1}],"thisVars":["this_warped"],"localVars":[]},"post":{"body":"{}","args":[],"thisVars":[],"localVars":[]},"debug":false,"funcName":"warp3D","blockSize":64}) -module.exports = findZeroCrossings +module.exports = function warp(dest, src, func) { + switch(src.shape.length) { + case 1: + do_warp_1(dest, func, interp.d1, src) + break + case 2: + do_warp_2(dest, func, interp.d2, src) + break + case 3: + do_warp_3(dest, func, interp.d3, src) + break + default: + do_warp(dest, func, interp.bind(undefined, src), src.shape.length) + break + } + return dest +} -var core = require("./lib/zc-core") +},{"cwise/lib/wrapper":69,"ndarray-linear-interpolate":204}],206:[function(require,module,exports){ +'use strict' -function findZeroCrossings(array, level) { - var cross = [] - level = +level || 0.0 - core(array.hi(array.shape[0]-1), cross, level) - return cross +var warp = require('ndarray-warp') +var invert = require('gl-matrix-invert') + +module.exports = applyHomography + +function applyHomography(dest, src, Xi) { + var n = src.dimension + var X = invert([], Xi) + warp(dest, src, function(out_c, inp_c) { + for(var i=0; i c)|0 },") - if(dtype === "generic") { - code.push("getters:[0],") +function fixup(x) { + if(!x) { + return EmptyProc } - - //Generate vertex function - var cubeArgs = [] - var extraArgs = [] - for(var i=0; i>>7){") + var wrapper = new Function("P", [ + "return function ", user_args.funcName, "_ndarrayops(", args.join(","), ") {P(", args.join(","), ");return a0}" + ].join("")) + return wrapper(pcompile(user_args)) +} + +var assign_ops = { + add: "+", + sub: "-", + mul: "*", + div: "/", + mod: "%", + band: "&", + bor: "|", + bxor: "^", + lshift: "<<", + rshift: ">>", + rrshift: ">>>" +} +;(function(){ + for(var id in assign_ops) { + var op = assign_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a","b","c"], + body: "a=b"+op+"c"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array","array"], + body: {args:["a","b"], + body:"a"+op+"=b"}, + rvalue: true, + funcName: id+"eq" + }) + exports[id+"s"] = makeOp({ + args: ["array", "array", "scalar"], + body: {args:["a","b","s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"seq"] = makeOp({ + args: ["array","scalar"], + body: {args:["a","s"], + body:"a"+op+"=s"}, + rvalue: true, + funcName: id+"seq" + }) } - for(var i=0; i<1<<(1< 128) { - if((i%128)===0) { - if(extraFuncs.length > 0) { - currentFunc.push("}}") - } - var efName = "vExtra" + extraFuncs.length - code.push("case ", (i>>>7), ":", efName, "(m&0x7f,", extraArgs.join(), ");break;") - currentFunc = [ - "function ", efName, "(m,", extraArgs.join(), "){switch(m){" - ] - extraFuncs.push(currentFunc) - } - } - currentFunc.push("case ", (i&0x7f), ":") - var crossings = new Array(dimension) - var denoms = new Array(dimension) - var crossingCount = new Array(dimension) - var bias = new Array(dimension) - var totalCrossings = 0 - for(var j=0; j j) { - continue - } - if(!(i&(1< 0) { - cStr = "+" + crossingCount[k] + "*c" - } - var weight = 0.5 * (crossings[k].length / totalCrossings) - var shift = 0.5 + 0.5 * (bias[k] / totalCrossings) - vertexStr.push("d" + k + "-" + shift + "-" + weight + "*(" + crossings[k].join("+") + cStr + ")/(" + denoms[k].join("+") + ")") - - } - } - currentFunc.push("a.push([", vertexStr.join(), "]);", - "break;") +})(); + +var unary_ops = { + not: "!", + bnot: "~", + neg: "-", + recip: "1.0/" +} +;(function(){ + for(var id in unary_ops) { + var op = unary_ops[id] + exports[id] = makeOp({ + args: ["array", "array"], + body: {args:["a","b"], + body:"a="+op+"b"}, + funcName: id + }) + exports[id+"eq"] = makeOp({ + args: ["array"], + body: {args:["a"], + body:"a="+op+"a"}, + rvalue: true, + count: 2, + funcName: id+"eq" + }) } - code.push("}},") - if(extraFuncs.length > 0) { - currentFunc.push("}}") +})(); + +var binary_ops = { + and: "&&", + or: "||", + eq: "===", + neq: "!==", + lt: "<", + gt: ">", + leq: "<=", + geq: ">=" +} +;(function() { + for(var id in binary_ops) { + var op = binary_ops[id] + exports[id] = makeOp({ + args: ["array","array","array"], + body: {args:["a", "b", "c"], + body:"a=b"+op+"c"}, + funcName: id + }) + exports[id+"s"] = makeOp({ + args: ["array","array","scalar"], + body: {args:["a", "b", "s"], + body:"a=b"+op+"s"}, + funcName: id+"s" + }) + exports[id+"eq"] = makeOp({ + args: ["array", "array"], + body: {args:["a", "b"], + body:"a=a"+op+"b"}, + rvalue:true, + count:2, + funcName: id+"eq" + }) + exports[id+"seq"] = makeOp({ + args: ["array", "scalar"], + body: {args:["a","s"], + body:"a=a"+op+"s"}, + rvalue:true, + count:2, + funcName: id+"seq" + }) } +})(); - //Create face function - var faceArgs = [] - for(var i=0; i<(1<<(dimension-1)); ++i) { - faceArgs.push("v" + i) +var math_unary = [ + "abs", + "acos", + "asin", + "atan", + "ceil", + "cos", + "exp", + "floor", + "log", + "round", + "sin", + "sqrt", + "tan" +] +;(function() { + for(var i=0; ithis_s){this_s=-a}else if(a>this_s){this_s=a}", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norminf" +}) -var CACHE = {} +exports.norm1 = compile({ + args:["array"], + pre: {args:[], localVars:[], thisVars:["this_s"], body:"this_s=0"}, + body: {args:[{name:"a", lvalue:false, rvalue:true, count:3}], body: "this_s+=a<0?-a:a", localVars: [], thisVars: ["this_s"]}, + post: {args:[], localVars:[], thisVars:["this_s"], body:"return this_s"}, + funcName: "norm1" +}) -function surfaceNets(array,level) { - if(array.dimension <= 0) { - return { positions: [], cells: [] } - } else if(array.dimension === 1) { - return mesh1D(array, level) - } - var typesig = array.order.join() + "-" + array.dtype - var proc = CACHE[typesig] - var level = (+level) || 0.0 - if(!proc) { - proc = CACHE[typesig] = buildSurfaceNets(array.order, array.dtype) - } - return proc(array,level) -} -},{"ndarray-extract-contour":398,"triangulate-hypercube":412,"zero-crossings":418}],420:[function(require,module,exports){ -(function (process){ -'use strict' +exports.sup = compile({ + args: [ "array" ], + pre: + { body: "this_h=-Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_>this_h)this_h=_inline_1_arg0_", + args: [{"name":"_inline_1_arg0_","lvalue":false,"rvalue":true,"count":2} ], + thisVars: [ "this_h" ], + localVars: [] }, + post: + { body: "return this_h", + args: [], + thisVars: [ "this_h" ], + localVars: [] } + }) -module.exports = textGet +exports.inf = compile({ + args: [ "array" ], + pre: + { body: "this_h=Infinity", + args: [], + thisVars: [ "this_h" ], + localVars: [] }, + body: + { body: "if(_inline_1_arg0_this_v){this_v=_inline_1_arg1_;for(var _inline_1_k=0;_inline_1_k<_inline_1_arg0_.length;++_inline_1_k){this_i[_inline_1_k]=_inline_1_arg0_[_inline_1_k]}}}", + args:[ + {name:"_inline_1_arg0_",lvalue:false,rvalue:true,count:2}, + {name:"_inline_1_arg1_",lvalue:false,rvalue:true,count:2}], + thisVars:["this_i","this_v"], + localVars:["_inline_1_k"]}, + post:{ + body:"{return this_i}", + args:[], + thisVars:["this_i"], + localVars:[]} +}) -function unwrap(mesh) { - var cells = mesh.cells - var positions = mesh.positions - var data = new Float32Array(cells.length * 6) - var ptr = 0 - var shapeX = 0 - for(var i=0; i0) { - shapeX += 0.02 - } - } +exports.assign = makeOp({ + args:["array", "array"], + body: {args:["a", "b"], body:"a=b"}, + funcName: "assign" }) - var data = new Float32Array(bufferSize) - var ptr = 0 - var xOffset = -0.5 * shapeX - for(var i=0; iMath.abs(this.stride[1]))?[1,0]:[0,1]}})") + } else if(dimension === 3) { + code.push( +"var s0=Math.abs(this.stride[0]),s1=Math.abs(this.stride[1]),s2=Math.abs(this.stride[2]);\ +if(s0>s1){\ +if(s1>s2){\ +return [2,1,0];\ +}else if(s0>s2){\ +return [1,2,0];\ +}else{\ +return [1,0,2];\ +}\ +}else if(s0>s2){\ +return [2,0,1];\ +}else if(s2>s1){\ +return [0,1,2];\ +}else{\ +return [0,2,1];\ +}}})") + } + } else { + code.push("ORDER})") + } + } - this.borderColor = [0,0,0,0] - this.backgroundColor = [0,0,0,0] + //view.set(i0, ..., v): + code.push( +"proto.set=function "+className+"_set("+args.join(",")+",v){") + if(useGetters) { + code.push("return this.data.set("+index_str+",v)}") + } else { + code.push("return this.data["+index_str+"]=v}") + } - this.zeroLineEnable = [true, true] - this.zeroLineWidth = [4, 4] - this.zeroLineColor = [[0, 0, 0, 1],[0, 0, 0, 1]] + //view.get(i0, ...): + code.push("proto.get=function "+className+"_get("+args.join(",")+"){") + if(useGetters) { + code.push("return this.data.get("+index_str+")}") + } else { + code.push("return this.data["+index_str+"]}") + } - this.borderLineEnable = [true,true,true,true] - this.borderLineWidth = [2,2,2,2] - this.borderLineColor = [[0,0,0,1], - [0,0,0,1], - [0,0,0,1], - [0,0,0,1]] + //view.index: + code.push( + "proto.index=function "+className+"_index(", args.join(), "){return "+index_str+"}") - //Drawing parameters - this.grid = null - this.text = null - this.line = null - this.box = null - this.objects = [] - this.overlays = [] + //view.hi(): + code.push("proto.hi=function "+className+"_hi("+args.join(",")+"){return new "+className+"(this.data,"+ + indices.map(function(i) { + return ["(typeof i",i,"!=='number'||i",i,"<0)?this.shape[", i, "]:i", i,"|0"].join("") + }).join(",")+","+ + indices.map(function(i) { + return "this.stride["+i + "]" + }).join(",")+",this.offset)}") - this._tickBounds = [Infinity, Infinity, -Infinity, -Infinity] + //view.lo(): + var a_vars = indices.map(function(i) { return "a"+i+"=this.shape["+i+"]" }) + var c_vars = indices.map(function(i) { return "c"+i+"=this.stride["+i+"]" }) + code.push("proto.lo=function "+className+"_lo("+args.join(",")+"){var b=this.offset,d=0,"+a_vars.join(",")+","+c_vars.join(",")) + for(var i=0; i=0){\ +d=i"+i+"|0;\ +b+=c"+i+"*d;\ +a"+i+"-=d}") + } + code.push("return new "+className+"(this.data,"+ + indices.map(function(i) { + return "a"+i + }).join(",")+","+ + indices.map(function(i) { + return "c"+i + }).join(",")+",b)}") - this.dirty = false - this.pickDirty = false - this.pickDelay = 120 - this.pickRadius = 10 - this._pickTimeout = null - this._drawPick = this.drawPick.bind(this) + //view.step(): + code.push("proto.step=function "+className+"_step("+args.join(",")+"){var "+ + indices.map(function(i) { + return "a"+i+"=this.shape["+i+"]" + }).join(",")+","+ + indices.map(function(i) { + return "b"+i+"=this.stride["+i+"]" + }).join(",")+",c=this.offset,d=0,ceil=Math.ceil") + for(var i=0; i=0){c=(c+this.stride["+i+"]*i"+i+")|0}else{a.push(this.shape["+i+"]);b.push(this.stride["+i+"])}") + } + code.push("var ctor=CTOR_LIST[a.length+1];return ctor(this.data,a,b,c)}") -proto.setDirty = function() { - this.dirty = this.pickDirty = true -} + //Add return statement + code.push("return function construct_"+className+"(data,shape,stride,offset){return new "+className+"(data,"+ + indices.map(function(i) { + return "shape["+i+"]" + }).join(",")+","+ + indices.map(function(i) { + return "stride["+i+"]" + }).join(",")+",offset)}") -proto.setOverlayDirty = function() { - this.dirty = true + //Compile procedure + var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n")) + return procedure(CACHED_CONSTRUCTORS[dtype], order) } -proto.nextDepthValue = function() { - return (this._depthCounter++) / 65536.0 +function arrayDType(data) { + if(isBuffer(data)) { + return "buffer" + } + if(hasTypedArrays) { + switch(Object.prototype.toString.call(data)) { + case "[object Float64Array]": + return "float64" + case "[object Float32Array]": + return "float32" + case "[object Int8Array]": + return "int8" + case "[object Int16Array]": + return "int16" + case "[object Int32Array]": + return "int32" + case "[object Uint8Array]": + return "uint8" + case "[object Uint16Array]": + return "uint16" + case "[object Uint32Array]": + return "uint32" + case "[object Uint8ClampedArray]": + return "uint8_clamped" + } + } + if(Array.isArray(data)) { + return "array" + } + return "generic" } -function lerp(a, b, t) { - var s = 0.5 * (t + 1.0) - return Math.floor((1.0-s)*a + s*b)|0 +var CACHED_CONSTRUCTORS = { + "float32":[], + "float64":[], + "int8":[], + "int16":[], + "int32":[], + "uint8":[], + "uint16":[], + "uint32":[], + "array":[], + "uint8_clamped":[], + "buffer":[], + "generic":[] } -proto.draw = (function() { -var TICK_MARK_BOX = [0,0,0,0] -return function() { - var gl = this.gl - var screenBox = this.screenBox - var viewPixels = this.viewBox - var dataBox = this.dataBox - var pixelRatio = this.pixelRatio - var grid = this.grid - var line = this.line - var text = this.text - var objects = this.objects - - this._depthCounter = 0 +;(function() { + for(var id in CACHED_CONSTRUCTORS) { + CACHED_CONSTRUCTORS[id].push(compileConstructor(id, -1)) + } +}); - if(this.pickDirty) { - if(this._pickTimeout) { - clearTimeout(this._pickTimeout) +function wrappedNDArrayCtor(data, shape, stride, offset) { + if(data === undefined) { + var ctor = CACHED_CONSTRUCTORS.array[0] + return ctor([]) + } else if(typeof data === "number") { + data = [data] + } + if(shape === undefined) { + shape = [ data.length ] + } + var d = shape.length + if(stride === undefined) { + stride = new Array(d) + for(var i=d-1, sz=1; i>=0; --i) { + stride[i] = sz + sz *= shape[i] } - this.pickDirty = false - this._pickTimeout = setTimeout(this._drawPick, this.pickDelay) } - - if(!this.dirty) { - return + if(offset === undefined) { + offset = 0 + for(var i=0; i + * License: MIT + * + * `npm install is-buffer` + */ - //Turn off depth buffer - gl.disable(gl.DEPTH_TEST) - gl.depthFunc(gl.LESS) - gl.depthMask(false) +module.exports = function (obj) { + return !!(obj != null && + (obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor) + (obj.constructor && + typeof obj.constructor.isBuffer === 'function' && + obj.constructor.isBuffer(obj)) + )) +} - //Configure premultiplied alpha blending - gl.enable(gl.BLEND) - gl.blendEquation(gl.FUNC_ADD, gl.FUNC_ADD); - gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); +},{}],210:[function(require,module,exports){ +(function (global){ +module.exports = + global.performance && + global.performance.now ? function now() { + return performance.now() + } : Date.now || function now() { + return +new Date + } - //Draw border - gl.scissor( - screenBox[0], - screenBox[1], - screenBox[2]-screenBox[0], - screenBox[3]-screenBox[1]) - var borderColor = this.borderColor - gl.clearColor( - borderColor[0]*borderColor[3], - borderColor[1]*borderColor[3], - borderColor[2]*borderColor[3], - borderColor[3]) - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],211:[function(require,module,exports){ +"use strict" - //Draw center pane - gl.scissor( - viewPixels[0], - viewPixels[1], - viewPixels[2]-viewPixels[0], - viewPixels[3]-viewPixels[1]) - gl.viewport( - viewPixels[0], - viewPixels[1], - viewPixels[2]-viewPixels[0], - viewPixels[3]-viewPixels[1]) - var backgroundColor = this.backgroundColor - gl.clearColor( - backgroundColor[0]*backgroundColor[3], - backgroundColor[1]*backgroundColor[3], - backgroundColor[2]*backgroundColor[3], - backgroundColor[3]) - gl.clear(gl.COLOR_BUFFER_BIT) +var determinant = require("robust-determinant") - //Draw grid - grid.draw() +var NUM_EXPAND = 6 - //Draw zero lines separately - var zeroLineEnable = this.zeroLineEnable - var zeroLineColor = this.zeroLineColor - var zeroLineWidth = this.zeroLineWidth - if(zeroLineEnable[0] || zeroLineEnable[1]) { - line.bind() - for(var i=0; i<2; ++i) { - if(!zeroLineEnable[i] || - !(dataBox[i] <= 0 && dataBox[i+2] >= 0)) { - continue +function generateSolver(n) { + var funcName = "robustLinearSolve" + n + "d" + var code = ["function ", funcName, "(A,b){return ["] + for(var i=0; i 0) { + code.push(",") } - - var zeroIntercept = screenBox[i] - - dataBox[i] * (screenBox[i+2] - screenBox[i]) / (dataBox[i+2] - dataBox[i]) - - if(i === 0) { - line.drawLine( - zeroIntercept, screenBox[1], zeroIntercept, screenBox[3], - zeroLineWidth[i], - zeroLineColor[i]) - } else { - line.drawLine( - screenBox[0], zeroIntercept, screenBox[2], zeroIntercept, - zeroLineWidth[i], - zeroLineColor[i]) + code.push("[") + for(var k=0; k 0) { + code.push(",") + } + if(k === i) { + code.push("+b[", j, "]") + } else { + code.push("+A[", j, "][", k, "]") + } } + code.push("]") } + code.push("]),") } - - //Draw traces - for(var i=0; i=0; --i) { + var a = Q + var b = e[i] + Q = a + b + var bv = Q - a + var q = b - bv + if(q) { + e[--bottom] = Q + Q = q + } } - if(this.titleEnable) { - text.drawTitle() + var top = 0 + for(var i=bottom; i>1 + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") } +} - pickBuffer.end() +function determinant(m) { + if(m.length === 2) { + return ["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("") + } else { + var expr = [] + for(var i=0; i>1 + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") + } } -proto.setDataBox = function(nbox) { - var dataBox = this.dataBox - - var different = - dataBox[0] !== nbox[0] || - dataBox[1] !== nbox[1] || - dataBox[2] !== nbox[2] || - dataBox[3] !== nbox[3] - - if(different) { - dataBox[0] = nbox[0] - dataBox[1] = nbox[1] - dataBox[2] = nbox[2] - dataBox[3] = nbox[3] - - this.setDirty() +function determinant(m) { + if(m.length === 2) { + return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")] + } else { + var expr = [] + for(var i=0; i 0) { + if(r <= 0) { + return det + } else { + s = l + r + } + } else if(l < 0) { + if(r >= 0) { + return det + } else { + s = -(l + r) + } + } else { + return det + } + var tol = ERRBOUND3 * s + if(det >= tol || det <= -tol) { + return det + } + return orientation3Exact(a, b, c) + }, + function orientation4(a,b,c,d) { + var adx = a[0] - d[0] + var bdx = b[0] - d[0] + var cdx = c[0] - d[0] + var ady = a[1] - d[1] + var bdy = b[1] - d[1] + var cdy = c[1] - d[1] + var adz = a[2] - d[2] + var bdz = b[2] - d[2] + var cdz = c[2] - d[2] + var bdxcdy = bdx * cdy + var cdxbdy = cdx * bdy + var cdxady = cdx * ady + var adxcdy = adx * cdy + var adxbdy = adx * bdy + var bdxady = bdx * ady + var det = adz * (bdxcdy - cdxbdy) + + bdz * (cdxady - adxcdy) + + cdz * (adxbdy - bdxady) + var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) + + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) + + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz) + var tol = ERRBOUND4 * permanent + if ((det > tol) || (-det > tol)) { + return det + } + return orientation4Exact(a,b,c,d) + } +] - this.tickMarkLength = (options.tickMarkLength || [0,0,0,0]).slice() - this.tickMarkWidth = (options.tickMarkWidth || [0,0,0,0]).slice() - this.tickMarkColor = deepClone(options.tickMarkColor || - [[0,0,0,1],[0,0,0,1],[0,0,0,1],[0,0,0,1]]) +function slowOrient(args) { + var proc = CACHED[args.length] + if(!proc) { + proc = CACHED[args.length] = orientation(args.length) + } + return proc.apply(undefined, args) +} - this.titleCenter = (options.titleCenter || [ - 0.5*(viewBox[0]+viewBox[2])/pixelRatio,(viewBox[3]+120)/pixelRatio]).slice() - this.titleEnable = !('titleEnable' in options) || !!options.titleEnable - this.titleAngle = options.titleAngle || 0 - this.titleColor = (options.titleColor || [0,0,0,1]).slice() +function generateOrientationProc() { + while(CACHED.length <= NUM_EXPAND) { + CACHED.push(orientation(CACHED.length)) + } + var args = [] + var procArgs = ["slow"] + for(var i=0; i<=NUM_EXPAND; ++i) { + args.push("a" + i) + procArgs.push("o" + i) + } + var code = [ + "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;" + ] + for(var i=2; i<=NUM_EXPAND; ++i) { + code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");") + } + code.push("}var s=new Array(arguments.length);for(var i=0;i=0; --i) { - this.objects[i].dispose() + var g = new Array(2 * n) + var q = [0.1, 0.1] + var t = [0.1, 0.1] + var count = 0 + twoProduct(e[0], scale, q) + if(q[0]) { + g[count++] = q[0] } - this.objects.length = 0 - for(var i=this.overlays.length-1; i>=0; --i) { - this.overlays[i].dispose() + for(var i=1; i= nf)) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = -f[fptr] + fa = abs(fi) + } } -} - -proto.removeOverlay = function(object) { - var objects = this.overlays - for(var i=0; i= nf)) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) + } + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + fa = abs(fi) + } } - - var view = createView({ - center: options.center || [0,0,0], - up: options.up || [0,1,0], - eye: options.eye || [0,0,10], - mode: options.mode || 'orbit', - distanceLimits: limits - }) - - var pmatrix = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] - var distance = 0.0 - var width = element.clientWidth - var height = element.clientHeight - - var camera = { - view: view, - element: element, - delay: options.delay || 16, - rotateSpeed: options.rotateSpeed || 1, - zoomSpeed: options.zoomSpeed || 1, - translateSpeed: options.translateSpeed || 1, - flipX: !!options.flipX, - flipY: !!options.flipY, - modes: view.modes, - tick: function() { - var t = now() - var delay = this.delay - view.idle(t-delay) - view.flush(t-(100+delay*2)) - var ctime = t - 2 * delay - view.recalcMatrix(ctime) - var allEqual = true - var matrix = view.computedMatrix - for(var i=0; i<16; ++i) { - allEqual = allEqual && (pmatrix[i] === matrix[i]) - pmatrix[i] = matrix[i] + var x = a + b + var bv = x - a + var y = b - bv + var q0 = y + var q1 = x + var _x, _bv, _av, _br, _ar + while(eptr < ne && fptr < nf) { + if(ea < fa) { + a = ei + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + ea = abs(ei) } - var sizeChanged = - element.clientWidth === width && - element.clientHeight === height - width = element.clientWidth - height = element.clientHeight - if(allEqual) { - return !sizeChanged + } else { + a = fi + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + fa = abs(fi) } - distance = Math.exp(view.computedRadius[0]) - return true - }, - lookAt: function(center, eye, up) { - view.lookAt(view.lastT(), center, eye, up) - }, - rotate: function(pitch, yaw, roll) { - view.rotate(view.lastT(), pitch, yaw, roll) - }, - pan: function(dx, dy, dz) { - view.pan(view.lastT(), dx, dy, dz) - }, - translate: function(dx, dy, dz) { - view.translate(view.lastT(), dx, dy, dz) } + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x } - - Object.defineProperties(camera, { - matrix: { - get: function() { - return view.computedMatrix - }, - set: function(mat) { - view.setMatrix(view.lastT(), mat) - return view.computedMatrix - }, - enumerable: true - }, - mode: { - get: function() { - return view.getMode() - }, - set: function(mode) { - view.setMode(mode) - return view.getMode() - }, - enumerable: true - }, - center: { - get: function() { - return view.computedCenter - }, - set: function(ncenter) { - view.lookAt(view.lastT(), ncenter) - return view.computedCenter - }, - enumerable: true - }, - eye: { - get: function() { - return view.computedEye - }, - set: function(neye) { - view.lookAt(view.lastT(), null, neye) - return view.computedEye - }, - enumerable: true - }, - up: { - get: function() { - return view.computedUp - }, - set: function(nup) { - view.lookAt(view.lastT(), null, null, nup) - return view.computedUp - }, - enumerable: true - }, - distance: { - get: function() { - return distance - }, - set: function(d) { - view.setDistance(view.lastT(), d) - return d - }, - enumerable: true - }, - distanceLimits: { - get: function() { - return view.getDistanceLimits(limits) - }, - set: function(v) { - view.setDistanceLimits(v) - return v - }, - enumerable: true + while(eptr < ne) { + a = ei + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y } - }) - - element.addEventListener('contextmenu', function(ev) { - ev.preventDefault() - return false - }) - - var lastX = 0, lastY = 0 - mouseChange(element, function(buttons, x, y, mods) { - var scale = 1.0 / element.clientHeight - var dx = scale * (x - lastX) - var dy = scale * (y - lastY) - - var flipX = camera.flipX ? 1 : -1 - var flipY = camera.flipY ? 1 : -1 + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + eptr += 1 + if(eptr < ne) { + ei = e[eptr] + } + } + while(fptr < nf) { + a = fi + b = q0 + x = a + b + bv = x - a + y = b - bv + if(y) { + g[count++] = y + } + _x = q1 + x + _bv = _x - q1 + _av = _x - _bv + _br = x - _bv + _ar = q1 - _av + q0 = _ar + _br + q1 = _x + fptr += 1 + if(fptr < nf) { + fi = f[fptr] + } + } + if(q0) { + g[count++] = q0 + } + if(q1) { + g[count++] = q1 + } + if(!count) { + g[count++] = 0.0 + } + g.length = count + return g +} +},{}],218:[function(require,module,exports){ +'use strict' - var drot = Math.PI * camera.rotateSpeed +module.exports = toSuperScript - var t = now() +var SUPERSCRIPTS = { + ' ': ' ', + '0': '⁰', + '1': '¹', + '2': '²', + '3': '³', + '4': '⁴', + '5': '⁵', + '6': '⁶', + '7': '⁷', + '8': '⁸', + '9': '⁹', + '+': '⁺', + '-': '⁻', + 'a': 'ᵃ', + 'b': 'ᵇ', + 'c': 'ᶜ', + 'd': 'ᵈ', + 'e': 'ᵉ', + 'f': 'ᶠ', + 'g': 'ᵍ', + 'h': 'ʰ', + 'i': 'ⁱ', + 'j': 'ʲ', + 'k': 'ᵏ', + 'l': 'ˡ', + 'm': 'ᵐ', + 'n': 'ⁿ', + 'o': 'ᵒ', + 'p': 'ᵖ', + 'r': 'ʳ', + 's': 'ˢ', + 't': 'ᵗ', + 'u': 'ᵘ', + 'v': 'ᵛ', + 'w': 'ʷ', + 'x': 'ˣ', + 'y': 'ʸ', + 'z': 'ᶻ' +} - if(buttons & 1) { - if(mods.shift) { - view.rotate(t, 0, 0, -dx * drot) - } else { - view.rotate(t, flipX * drot * dx, -flipY * drot * dy, 0) - } - } else if(buttons & 2) { - view.pan(t, -camera.translateSpeed * dx * distance, camera.translateSpeed * dy * distance, 0) - } else if(buttons & 4) { - var kzoom = camera.zoomSpeed * dy / window.innerHeight * (t - view.lastT()) * 50.0 - view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) +function toSuperScript(x) { + return x.split('').map(function(c) { + if(c in SUPERSCRIPTS) { + return SUPERSCRIPTS[c] } + return '' + }).join('') +} - lastX = x - lastY = y - }) +},{}],219:[function(require,module,exports){ +"use strict" - mouseWheel(element, function(dx, dy, dz) { - var flipX = camera.flipX ? 1 : -1 - var flipY = camera.flipY ? 1 : -1 - var t = now() - if(Math.abs(dx) > Math.abs(dy)) { - view.rotate(t, 0, 0, -dx * flipX * Math.PI * camera.rotateSpeed / window.innerWidth) - } else { - var kzoom = camera.zoomSpeed * flipY * dy / window.innerHeight * (t - view.lastT()) / 100.0 - view.pan(t, 0, 0, distance * (Math.exp(kzoom) - 1)) - } - }, true) +var pool = require("typedarray-pool") - return camera -} -},{"3d-view":28,"mouse-change":960,"mouse-wheel":964,"right-now":990}],424:[function(require,module,exports){ -arguments[4][75][0].apply(exports,arguments) -},{"dup":75,"ndarray":987,"ndarray-ops":982,"typedarray-pool":427}],425:[function(require,module,exports){ -arguments[4][60][0].apply(exports,arguments) -},{"dup":60}],426:[function(require,module,exports){ -arguments[4][33][0].apply(exports,arguments) -},{"dup":33}],427:[function(require,module,exports){ -arguments[4][102][0].apply(exports,arguments) -},{"bit-twiddle":425,"buffer":48,"dup":102}],428:[function(require,module,exports){ -arguments[4][132][0].apply(exports,arguments) -},{"dup":132}],429:[function(require,module,exports){ -arguments[4][133][0].apply(exports,arguments) -},{"./do-bind.js":428,"dup":133}],430:[function(require,module,exports){ -arguments[4][134][0].apply(exports,arguments) -},{"./do-bind.js":428,"dup":134}],431:[function(require,module,exports){ -arguments[4][135][0].apply(exports,arguments) -},{"./lib/vao-emulated.js":429,"./lib/vao-native.js":430,"dup":135}],432:[function(require,module,exports){ -// Copyright (C) 2011 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +module.exports = createSurfaceExtractor -/** - * @fileoverview Install a leaky WeakMap emulation on platforms that - * don't provide a built-in one. - * - *

Assumes that an ES5 platform where, if {@code WeakMap} is - * already present, then it conforms to the anticipated ES6 - * specification. To run this file on an ES5 or almost ES5 - * implementation where the {@code WeakMap} specification does not - * quite conform, run repairES5.js first. - * - *

Even though WeakMapModule is not global, the linter thinks it - * is, which is why it is in the overrides list below. - * - *

NOTE: Before using this WeakMap emulation in a non-SES - * environment, see the note below about hiddenRecord. - * - * @author Mark S. Miller - * @requires crypto, ArrayBuffer, Uint8Array, navigator, console - * @overrides WeakMap, ses, Proxy - * @overrides WeakMapModule - */ +//Helper macros +function array(i) { + return "a" + i +} +function data(i) { + return "d" + i +} +function cube(i,bitmask) { + return "c" + i + "_" + bitmask +} +function shape(i) { + return "s" + i +} +function stride(i,j) { + return "t" + i + "_" + j +} +function offset(i) { + return "o" + i +} +function scalar(i) { + return "x" + i +} +function pointer(i) { + return "p" + i +} +function delta(i,bitmask) { + return "d" + i + "_" + bitmask +} +function index(i) { + return "i" + i +} +function step(i,j) { + return "u" + i + "_" + j +} +function pcube(bitmask) { + return "b" + bitmask +} +function qcube(bitmask) { + return "y" + bitmask +} +function pdelta(bitmask) { + return "e" + bitmask +} +function vert(i) { + return "v" + i +} +var VERTEX_IDS = "V" +var PHASES = "P" +var VERTEX_COUNT = "N" +var POOL_SIZE = "Q" +var POINTER = "X" +var TEMPORARY = "T" -/** - * This {@code WeakMap} emulation is observably equivalent to the - * ES-Harmony WeakMap, but with leakier garbage collection properties. - * - *

As with true WeakMaps, in this emulation, a key does not - * retain maps indexed by that key and (crucially) a map does not - * retain the keys it indexes. A map by itself also does not retain - * the values associated with that map. - * - *

However, the values associated with a key in some map are - * retained so long as that key is retained and those associations are - * not overridden. For example, when used to support membranes, all - * values exported from a given membrane will live for the lifetime - * they would have had in the absence of an interposed membrane. Even - * when the membrane is revoked, all objects that would have been - * reachable in the absence of revocation will still be reachable, as - * far as the GC can tell, even though they will no longer be relevant - * to ongoing computation. - * - *

The API implemented here is approximately the API as implemented - * in FF6.0a1 and agreed to by MarkM, Andreas Gal, and Dave Herman, - * rather than the offially approved proposal page. TODO(erights): - * upgrade the ecmascript WeakMap proposal page to explain this API - * change and present to EcmaScript committee for their approval. - * - *

The first difference between the emulation here and that in - * FF6.0a1 is the presence of non enumerable {@code get___, has___, - * set___, and delete___} methods on WeakMap instances to represent - * what would be the hidden internal properties of a primitive - * implementation. Whereas the FF6.0a1 WeakMap.prototype methods - * require their {@code this} to be a genuine WeakMap instance (i.e., - * an object of {@code [[Class]]} "WeakMap}), since there is nothing - * unforgeable about the pseudo-internal method names used here, - * nothing prevents these emulated prototype methods from being - * applied to non-WeakMaps with pseudo-internal methods of the same - * names. - * - *

Another difference is that our emulated {@code - * WeakMap.prototype} is not itself a WeakMap. A problem with the - * current FF6.0a1 API is that WeakMap.prototype is itself a WeakMap - * providing ambient mutability and an ambient communications - * channel. Thus, if a WeakMap is already present and has this - * problem, repairES5.js wraps it in a safe wrappper in order to - * prevent access to this channel. (See - * PATCH_MUTABLE_FROZEN_WEAKMAP_PROTO in repairES5.js). - */ +function permBitmask(dimension, mask, order) { + var r = 0 + for(var i=0; isecureable ES5 platform and the ES-Harmony {@code WeakMap} is - * absent, install an approximate emulation. - * - *

If WeakMap is present but cannot store some objects, use our approximate - * emulation as a wrapper. - * - *

If this is almost a secureable ES5 platform, then WeakMap.js - * should be run after repairES5.js. - * - *

See {@code WeakMap} for documentation of the garbage collection - * properties of this WeakMap emulation. - */ -(function WeakMapModule() { - "use strict"; +//Generates the surface procedure +function compileSurfaceProcedure(vertexFunc, faceFunc, phaseFunc, scalarArgs, order, typesig) { + var arrayArgs = typesig.length + var dimension = order.length - if (typeof ses !== 'undefined' && ses.ok && !ses.ok()) { - // already too broken, so give up - return; + if(dimension < 2) { + throw new Error("ndarray-extract-contour: Dimension must be at least 2") } - /** - * In some cases (current Firefox), we must make a choice betweeen a - * WeakMap which is capable of using all varieties of host objects as - * keys and one which is capable of safely using proxies as keys. See - * comments below about HostWeakMap and DoubleWeakMap for details. - * - * This function (which is a global, not exposed to guests) marks a - * WeakMap as permitted to do what is necessary to index all host - * objects, at the cost of making it unsafe for proxies. - * - * Do not apply this function to anything which is not a genuine - * fresh WeakMap. - */ - function weakMapPermitHostObjects(map) { - // identity of function used as a secret -- good enough and cheap - if (map.permitHostObjects___) { - map.permitHostObjects___(weakMapPermitHostObjects); - } + var funcName = "extractContour" + order.join("_") + var code = [] + var vars = [] + var args = [] + + //Assemble arguments + for(var i=0; i 0) { + stepVal.push(stride(i, order[j-1]) + "*" + shape(order[j-1]) ) + } + vars.push(step(i,order[j]) + "=(" + stepVal.join("-") + ")|0") + } + } + //Create index variables + for(var i=0; i=0; --i) { + sizeVariable.push(shape(order[i])) + } + //Previous phases and vertex_ids + vars.push(POOL_SIZE + "=(" + sizeVariable.join("*") + ")|0", + PHASES + "=mallocUint32(" + POOL_SIZE + ")", + VERTEX_IDS + "=mallocUint32(" + POOL_SIZE + ")", + POINTER + "=0") + //Create cube variables for phases + vars.push(pcube(0) + "=0") + for(var j=1; j<(1<=0; --i) { + forLoopBegin(i, 0) + } + var phaseFuncArgs = [] + for(var i=0; iunguessable and - * undiscoverable by untrusted code. - * - *

Given the known weaknesses of Math.random() on existing - * browsers, it does not generate unguessability we can be confident - * of. - * - *

It is the monkey patching logic in this file that is intended - * to ensure undiscoverability. The basic idea is that there are - * three fundamental means of discovering properties of an object: - * The for/in loop, Object.keys(), and Object.getOwnPropertyNames(), - * as well as some proposed ES6 extensions that appear on our - * whitelist. The first two only discover enumerable properties, and - * we only use HIDDEN_NAME to name a non-enumerable property, so the - * only remaining threat should be getOwnPropertyNames and some - * proposed ES6 extensions that appear on our whitelist. We monkey - * patch them to remove HIDDEN_NAME from the list of properties they - * returns. - * - *

TODO(erights): On a platform with built-in Proxies, proxies - * could be used to trap and thereby discover the HIDDEN_NAME, so we - * need to monkey patch Proxy.create, Proxy.createFunction, etc, in - * order to wrap the provided handler with the real handler which - * filters out all traps using HIDDEN_NAME. - * - *

TODO(erights): Revisit Mike Stay's suggestion that we use an - * encapsulated function at a not-necessarily-secret name, which - * uses the Stiegler shared-state rights amplification pattern to - * reveal the associated value only to the WeakMap in which this key - * is associated with that value. Since only the key retains the - * function, the function can also remember the key without causing - * leakage of the key, so this doesn't violate our general gc - * goals. In addition, because the name need not be a guarded - * secret, we could efficiently handle cross-frame frozen keys. - */ - var HIDDEN_NAME_PREFIX = 'weakmap:'; - var HIDDEN_NAME = HIDDEN_NAME_PREFIX + 'ident:' + Math.random() + '___'; + function processGridCell(mask) { + //Read in local data + for(var i=0; iThe ES5.1 spec requires each name to appear only once, but as - * of this writing, this requirement is controversial for ES6, so we - * made this code robust against this case. If the resulting extra - * search turns out to be expensive, we can probably relax this once - * ES6 is adequately supported on all major browsers, iff no browser - * versions we support at that time have relaxed this constraint - * without providing built-in ES6 WeakMaps. - */ - defProp(Object, 'getOwnPropertyNames', { - value: function fakeGetOwnPropertyNames(obj) { - return gopn(obj).filter(isNotHiddenName); + //Read in boundary data + var vertexArgs = [] + for(var i=0; i0; k=(k-1)&subset) { + faceArgs.push(VERTEX_IDS + "[" + POINTER + "+" + pdelta(k) + "]") + } + faceArgs.push(vert(0)) + for(var k=0; kTo treat objects as identity-keys with reasonable efficiency - * on ES5 by itself (i.e., without any object-keyed collections), we - * need to add a hidden property to such key objects when we - * can. This raises several issues: - *

    - *
  • Arranging to add this property to objects before we lose the - * chance, and - *
  • Hiding the existence of this new property from most - * JavaScript code. - *
  • Preventing certification theft, where one object is - * created falsely claiming to be the key of an association - * actually keyed by another object. - *
  • Preventing value theft, where untrusted code with - * access to a key object but not a weak map nevertheless - * obtains access to the value associated with that key in that - * weak map. - *
- * We do so by - *
    - *
  • Making the name of the hidden property unguessable, so "[]" - * indexing, which we cannot intercept, cannot be used to access - * a property without knowing the name. - *
  • Making the hidden property non-enumerable, so we need not - * worry about for-in loops or {@code Object.keys}, - *
  • monkey patching those reflective methods that would - * prevent extensions, to add this hidden property first, - *
  • monkey patching those methods that would reveal this - * hidden property. - *
- * Unfortunately, because of same-origin iframes, we cannot reliably - * add this hidden property before an object becomes - * non-extensible. Instead, if we encounter a non-extensible object - * without a hidden record that we can detect (whether or not it has - * a hidden record stored under a name secret to us), then we just - * use the key object itself to represent its identity in a brute - * force leaky map stored in the weak map, losing all the advantages - * of weakness for these. - */ - function getHiddenRecord(key) { - if (key !== Object(key)) { - throw new TypeError('Not an object: ' + key); + function flip() { + for(var j=1; j<(1<0){", + index(order[i]), "=1;") + createLoop(i-1, mask|(1<